shmob_drm_kms.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * shmob_drm_kms.c -- SH Mobile DRM Mode Setting
  4. *
  5. * Copyright (C) 2012 Renesas Electronics Corporation
  6. *
  7. * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  8. */
  9. #include <drm/drm_atomic_helper.h>
  10. #include <drm/drm_crtc.h>
  11. #include <drm/drm_crtc_helper.h>
  12. #include <drm/drm_fourcc.h>
  13. #include <drm/drm_gem_dma_helper.h>
  14. #include <drm/drm_gem_framebuffer_helper.h>
  15. #include <drm/drm_probe_helper.h>
  16. #include "shmob_drm_crtc.h"
  17. #include "shmob_drm_drv.h"
  18. #include "shmob_drm_kms.h"
  19. #include "shmob_drm_plane.h"
  20. #include "shmob_drm_regs.h"
  21. /* -----------------------------------------------------------------------------
  22. * Format helpers
  23. */
  24. static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
  25. {
  26. .fourcc = DRM_FORMAT_RGB565,
  27. .bpp = 16,
  28. .lddfr = LDDFR_PKF_RGB16,
  29. .ldddsr = LDDDSR_LS | LDDDSR_WS,
  30. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  31. LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16,
  32. }, {
  33. .fourcc = DRM_FORMAT_RGB888,
  34. .bpp = 24,
  35. .lddfr = LDDFR_PKF_RGB24,
  36. .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
  37. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  38. LDBBSIFR_SWPB | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24,
  39. }, {
  40. .fourcc = DRM_FORMAT_ARGB8888,
  41. .bpp = 32,
  42. .lddfr = LDDFR_PKF_ARGB32,
  43. .ldddsr = LDDDSR_LS,
  44. .ldbbsifr = LDBBSIFR_AL_PK | LDBBSIFR_SWPL | LDBBSIFR_RY |
  45. LDBBSIFR_RPKF_ARGB32,
  46. }, {
  47. .fourcc = DRM_FORMAT_XRGB8888,
  48. .bpp = 32,
  49. .lddfr = LDDFR_PKF_ARGB32,
  50. .ldddsr = LDDDSR_LS,
  51. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_RY |
  52. LDBBSIFR_RPKF_ARGB32,
  53. }, {
  54. .fourcc = DRM_FORMAT_NV12,
  55. .bpp = 12,
  56. .lddfr = LDDFR_CC | LDDFR_YF_420,
  57. .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
  58. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  59. LDBBSIFR_SWPB | LDBBSIFR_CHRR_420,
  60. }, {
  61. .fourcc = DRM_FORMAT_NV21,
  62. .bpp = 12,
  63. .lddfr = LDDFR_CC | LDDFR_YF_420,
  64. .ldddsr = LDDDSR_LS | LDDDSR_WS,
  65. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  66. LDBBSIFR_CHRR_420,
  67. }, {
  68. .fourcc = DRM_FORMAT_NV16,
  69. .bpp = 16,
  70. .lddfr = LDDFR_CC | LDDFR_YF_422,
  71. .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
  72. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  73. LDBBSIFR_SWPB | LDBBSIFR_CHRR_422,
  74. }, {
  75. .fourcc = DRM_FORMAT_NV61,
  76. .bpp = 16,
  77. .lddfr = LDDFR_CC | LDDFR_YF_422,
  78. .ldddsr = LDDDSR_LS | LDDDSR_WS,
  79. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  80. LDBBSIFR_CHRR_422,
  81. }, {
  82. .fourcc = DRM_FORMAT_NV24,
  83. .bpp = 24,
  84. .lddfr = LDDFR_CC | LDDFR_YF_444,
  85. .ldddsr = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS,
  86. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  87. LDBBSIFR_SWPB | LDBBSIFR_CHRR_444,
  88. }, {
  89. .fourcc = DRM_FORMAT_NV42,
  90. .bpp = 24,
  91. .lddfr = LDDFR_CC | LDDFR_YF_444,
  92. .ldddsr = LDDDSR_LS | LDDDSR_WS,
  93. .ldbbsifr = LDBBSIFR_AL_1 | LDBBSIFR_SWPL | LDBBSIFR_SWPW |
  94. LDBBSIFR_CHRR_444,
  95. },
  96. };
  97. const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc)
  98. {
  99. unsigned int i;
  100. for (i = 0; i < ARRAY_SIZE(shmob_drm_format_infos); ++i) {
  101. if (shmob_drm_format_infos[i].fourcc == fourcc)
  102. return &shmob_drm_format_infos[i];
  103. }
  104. return NULL;
  105. }
  106. /* -----------------------------------------------------------------------------
  107. * Frame buffer
  108. */
  109. static struct drm_framebuffer *
  110. shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
  111. const struct drm_format_info *info,
  112. const struct drm_mode_fb_cmd2 *mode_cmd)
  113. {
  114. const struct shmob_drm_format_info *format;
  115. format = shmob_drm_format_info(mode_cmd->pixel_format);
  116. if (format == NULL) {
  117. dev_dbg(dev->dev, "unsupported pixel format %p4cc\n",
  118. &mode_cmd->pixel_format);
  119. return ERR_PTR(-EINVAL);
  120. }
  121. if (mode_cmd->pitches[0] & 7 || mode_cmd->pitches[0] >= 65536) {
  122. dev_dbg(dev->dev, "invalid pitch value %u\n",
  123. mode_cmd->pitches[0]);
  124. return ERR_PTR(-EINVAL);
  125. }
  126. if (shmob_drm_format_is_yuv(format)) {
  127. unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
  128. if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
  129. dev_dbg(dev->dev,
  130. "luma and chroma pitches do not match\n");
  131. return ERR_PTR(-EINVAL);
  132. }
  133. }
  134. return drm_gem_fb_create(dev, file_priv, info, mode_cmd);
  135. }
  136. static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
  137. .fb_create = shmob_drm_fb_create,
  138. .atomic_check = drm_atomic_helper_check,
  139. .atomic_commit = drm_atomic_helper_commit,
  140. };
  141. int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
  142. {
  143. struct drm_device *dev = &sdev->ddev;
  144. int ret;
  145. ret = drmm_mode_config_init(dev);
  146. if (ret)
  147. return ret;
  148. ret = shmob_drm_crtc_create(sdev);
  149. if (ret < 0)
  150. return ret;
  151. ret = shmob_drm_encoder_create(sdev);
  152. if (ret < 0)
  153. return ret;
  154. ret = shmob_drm_connector_create(sdev, &sdev->encoder);
  155. if (ret < 0)
  156. return ret;
  157. drm_mode_config_reset(dev);
  158. drm_kms_helper_poll_init(dev);
  159. sdev->ddev.mode_config.min_width = 0;
  160. sdev->ddev.mode_config.min_height = 0;
  161. sdev->ddev.mode_config.max_width = 4095;
  162. sdev->ddev.mode_config.max_height = 4095;
  163. sdev->ddev.mode_config.funcs = &shmob_drm_mode_config_funcs;
  164. return 0;
  165. }