fsl_dcu_drm_plane.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright 2015 Freescale Semiconductor, Inc.
  3. *
  4. * Freescale DCU drm device driver
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #include <linux/regmap.h>
  12. #include <drm/drmP.h>
  13. #include <drm/drm_atomic_helper.h>
  14. #include <drm/drm_crtc.h>
  15. #include <drm/drm_crtc_helper.h>
  16. #include <drm/drm_fb_cma_helper.h>
  17. #include <drm/drm_gem_cma_helper.h>
  18. #include <drm/drm_plane_helper.h>
  19. #include "fsl_dcu_drm_drv.h"
  20. #include "fsl_dcu_drm_plane.h"
  21. static int fsl_dcu_drm_plane_index(struct drm_plane *plane)
  22. {
  23. struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  24. unsigned int total_layer = fsl_dev->soc->total_layer;
  25. unsigned int index;
  26. index = drm_plane_index(plane);
  27. if (index < total_layer)
  28. return total_layer - index - 1;
  29. dev_err(fsl_dev->dev, "No more layer left\n");
  30. return -EINVAL;
  31. }
  32. static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
  33. struct drm_plane_state *state)
  34. {
  35. struct drm_framebuffer *fb = state->fb;
  36. if (!state->fb || !state->crtc)
  37. return 0;
  38. switch (fb->format->format) {
  39. case DRM_FORMAT_RGB565:
  40. case DRM_FORMAT_RGB888:
  41. case DRM_FORMAT_XRGB8888:
  42. case DRM_FORMAT_ARGB8888:
  43. case DRM_FORMAT_XRGB4444:
  44. case DRM_FORMAT_ARGB4444:
  45. case DRM_FORMAT_XRGB1555:
  46. case DRM_FORMAT_ARGB1555:
  47. case DRM_FORMAT_YUV422:
  48. return 0;
  49. default:
  50. return -EINVAL;
  51. }
  52. }
  53. static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
  54. struct drm_plane_state *old_state)
  55. {
  56. struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  57. unsigned int value;
  58. int index;
  59. index = fsl_dcu_drm_plane_index(plane);
  60. if (index < 0)
  61. return;
  62. regmap_read(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), &value);
  63. value &= ~DCU_LAYER_EN;
  64. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), value);
  65. }
  66. static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
  67. struct drm_plane_state *old_state)
  68. {
  69. struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
  70. struct drm_plane_state *state = plane->state;
  71. struct drm_framebuffer *fb = plane->state->fb;
  72. struct drm_gem_cma_object *gem;
  73. unsigned int alpha = DCU_LAYER_AB_NONE, bpp;
  74. int index;
  75. if (!fb)
  76. return;
  77. index = fsl_dcu_drm_plane_index(plane);
  78. if (index < 0)
  79. return;
  80. gem = drm_fb_cma_get_gem_obj(fb, 0);
  81. switch (fb->format->format) {
  82. case DRM_FORMAT_RGB565:
  83. bpp = FSL_DCU_RGB565;
  84. break;
  85. case DRM_FORMAT_RGB888:
  86. bpp = FSL_DCU_RGB888;
  87. break;
  88. case DRM_FORMAT_ARGB8888:
  89. alpha = DCU_LAYER_AB_WHOLE_FRAME;
  90. /* fall-through */
  91. case DRM_FORMAT_XRGB8888:
  92. bpp = FSL_DCU_ARGB8888;
  93. break;
  94. case DRM_FORMAT_ARGB4444:
  95. alpha = DCU_LAYER_AB_WHOLE_FRAME;
  96. /* fall-through */
  97. case DRM_FORMAT_XRGB4444:
  98. bpp = FSL_DCU_ARGB4444;
  99. break;
  100. case DRM_FORMAT_ARGB1555:
  101. alpha = DCU_LAYER_AB_WHOLE_FRAME;
  102. /* fall-through */
  103. case DRM_FORMAT_XRGB1555:
  104. bpp = FSL_DCU_ARGB1555;
  105. break;
  106. case DRM_FORMAT_YUV422:
  107. bpp = FSL_DCU_YUV422;
  108. break;
  109. default:
  110. return;
  111. }
  112. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 1),
  113. DCU_LAYER_HEIGHT(state->crtc_h) |
  114. DCU_LAYER_WIDTH(state->crtc_w));
  115. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
  116. DCU_LAYER_POSY(state->crtc_y) |
  117. DCU_LAYER_POSX(state->crtc_x));
  118. regmap_write(fsl_dev->regmap,
  119. DCU_CTRLDESCLN(index, 3), gem->paddr);
  120. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
  121. DCU_LAYER_EN |
  122. DCU_LAYER_TRANS(0xff) |
  123. DCU_LAYER_BPP(bpp) |
  124. alpha);
  125. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 5),
  126. DCU_LAYER_CKMAX_R(0xFF) |
  127. DCU_LAYER_CKMAX_G(0xFF) |
  128. DCU_LAYER_CKMAX_B(0xFF));
  129. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 6),
  130. DCU_LAYER_CKMIN_R(0) |
  131. DCU_LAYER_CKMIN_G(0) |
  132. DCU_LAYER_CKMIN_B(0));
  133. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 7), 0);
  134. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 8),
  135. DCU_LAYER_FG_FCOLOR(0));
  136. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 9),
  137. DCU_LAYER_BG_BCOLOR(0));
  138. if (!strcmp(fsl_dev->soc->name, "ls1021a")) {
  139. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 10),
  140. DCU_LAYER_POST_SKIP(0) |
  141. DCU_LAYER_PRE_SKIP(0));
  142. }
  143. return;
  144. }
  145. static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
  146. .atomic_check = fsl_dcu_drm_plane_atomic_check,
  147. .atomic_disable = fsl_dcu_drm_plane_atomic_disable,
  148. .atomic_update = fsl_dcu_drm_plane_atomic_update,
  149. };
  150. static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
  151. {
  152. drm_plane_cleanup(plane);
  153. kfree(plane);
  154. }
  155. static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
  156. .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
  157. .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
  158. .destroy = fsl_dcu_drm_plane_destroy,
  159. .disable_plane = drm_atomic_helper_disable_plane,
  160. .reset = drm_atomic_helper_plane_reset,
  161. .update_plane = drm_atomic_helper_update_plane,
  162. };
  163. static const u32 fsl_dcu_drm_plane_formats[] = {
  164. DRM_FORMAT_RGB565,
  165. DRM_FORMAT_RGB888,
  166. DRM_FORMAT_XRGB8888,
  167. DRM_FORMAT_ARGB8888,
  168. DRM_FORMAT_XRGB4444,
  169. DRM_FORMAT_ARGB4444,
  170. DRM_FORMAT_XRGB1555,
  171. DRM_FORMAT_ARGB1555,
  172. DRM_FORMAT_YUV422,
  173. };
  174. void fsl_dcu_drm_init_planes(struct drm_device *dev)
  175. {
  176. struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  177. int i, j;
  178. for (i = 0; i < fsl_dev->soc->total_layer; i++) {
  179. for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
  180. regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
  181. }
  182. }
  183. struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
  184. {
  185. struct drm_plane *primary;
  186. int ret;
  187. primary = kzalloc(sizeof(*primary), GFP_KERNEL);
  188. if (!primary) {
  189. DRM_DEBUG_KMS("Failed to allocate primary plane\n");
  190. return NULL;
  191. }
  192. /* possible_crtc's will be filled in later by crtc_init */
  193. ret = drm_universal_plane_init(dev, primary, 0,
  194. &fsl_dcu_drm_plane_funcs,
  195. fsl_dcu_drm_plane_formats,
  196. ARRAY_SIZE(fsl_dcu_drm_plane_formats),
  197. NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
  198. if (ret) {
  199. kfree(primary);
  200. primary = NULL;
  201. }
  202. drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
  203. return primary;
  204. }