sti_drm_plane.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Copyright (C) STMicroelectronics SA 2014
  3. * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
  4. * Fabien Dessenne <fabien.dessenne@st.com>
  5. * for STMicroelectronics.
  6. * License terms: GNU General Public License (GPL), version 2
  7. */
  8. #include <drm/drmP.h>
  9. #include <drm/drm_atomic_helper.h>
  10. #include <drm/drm_plane_helper.h>
  11. #include "sti_compositor.h"
  12. #include "sti_drm_drv.h"
  13. #include "sti_drm_plane.h"
  14. #include "sti_vtg.h"
  15. enum sti_layer_desc sti_layer_default_zorder[] = {
  16. STI_GDP_0,
  17. STI_VID_0,
  18. STI_GDP_1,
  19. STI_VID_1,
  20. STI_GDP_2,
  21. STI_GDP_3,
  22. };
  23. /* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
  24. static int
  25. sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
  26. struct drm_framebuffer *fb, int crtc_x, int crtc_y,
  27. unsigned int crtc_w, unsigned int crtc_h,
  28. uint32_t src_x, uint32_t src_y,
  29. uint32_t src_w, uint32_t src_h)
  30. {
  31. struct sti_layer *layer = to_sti_layer(plane);
  32. struct sti_mixer *mixer = to_sti_mixer(crtc);
  33. int res;
  34. DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
  35. crtc->base.id, sti_mixer_to_str(mixer),
  36. plane->base.id, sti_layer_to_str(layer));
  37. DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
  38. res = sti_mixer_set_layer_depth(mixer, layer);
  39. if (res) {
  40. DRM_ERROR("Can not set layer depth\n");
  41. return res;
  42. }
  43. /* src_x are in 16.16 format. */
  44. res = sti_layer_prepare(layer, crtc, fb,
  45. &crtc->mode, mixer->id,
  46. crtc_x, crtc_y, crtc_w, crtc_h,
  47. src_x >> 16, src_y >> 16,
  48. src_w >> 16, src_h >> 16);
  49. if (res) {
  50. DRM_ERROR("Layer prepare failed\n");
  51. return res;
  52. }
  53. res = sti_layer_commit(layer);
  54. if (res) {
  55. DRM_ERROR("Layer commit failed\n");
  56. return res;
  57. }
  58. res = sti_mixer_set_layer_status(mixer, layer, true);
  59. if (res) {
  60. DRM_ERROR("Can not enable layer at mixer\n");
  61. return res;
  62. }
  63. return 0;
  64. }
  65. static int sti_drm_disable_plane(struct drm_plane *plane)
  66. {
  67. struct sti_layer *layer;
  68. struct sti_mixer *mixer;
  69. int lay_res, mix_res;
  70. if (!plane->crtc) {
  71. DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
  72. return 0;
  73. }
  74. layer = to_sti_layer(plane);
  75. mixer = to_sti_mixer(plane->crtc);
  76. DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
  77. plane->crtc->base.id, sti_mixer_to_str(mixer),
  78. plane->base.id, sti_layer_to_str(layer));
  79. /* Disable layer at mixer level */
  80. mix_res = sti_mixer_set_layer_status(mixer, layer, false);
  81. if (mix_res)
  82. DRM_ERROR("Can not disable layer at mixer\n");
  83. /* Wait a while to be sure that a Vsync event is received */
  84. msleep(WAIT_NEXT_VSYNC_MS);
  85. /* Then disable layer itself */
  86. lay_res = sti_layer_disable(layer);
  87. if (lay_res)
  88. DRM_ERROR("Layer disable failed\n");
  89. if (lay_res || mix_res)
  90. return -EINVAL;
  91. return 0;
  92. }
  93. static void sti_drm_plane_destroy(struct drm_plane *plane)
  94. {
  95. DRM_DEBUG_DRIVER("\n");
  96. drm_plane_helper_disable(plane);
  97. drm_plane_cleanup(plane);
  98. }
  99. static int sti_drm_plane_set_property(struct drm_plane *plane,
  100. struct drm_property *property,
  101. uint64_t val)
  102. {
  103. struct drm_device *dev = plane->dev;
  104. struct sti_drm_private *private = dev->dev_private;
  105. struct sti_layer *layer = to_sti_layer(plane);
  106. DRM_DEBUG_DRIVER("\n");
  107. if (property == private->plane_zorder_property) {
  108. layer->zorder = val;
  109. return 0;
  110. }
  111. return -EINVAL;
  112. }
  113. static struct drm_plane_funcs sti_drm_plane_funcs = {
  114. .update_plane = drm_atomic_helper_update_plane,
  115. .disable_plane = drm_atomic_helper_disable_plane,
  116. .destroy = sti_drm_plane_destroy,
  117. .set_property = sti_drm_plane_set_property,
  118. .reset = drm_atomic_helper_plane_reset,
  119. .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
  120. .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
  121. };
  122. static int sti_drm_plane_prepare_fb(struct drm_plane *plane,
  123. struct drm_framebuffer *fb,
  124. const struct drm_plane_state *new_state)
  125. {
  126. return 0;
  127. }
  128. static void sti_drm_plane_cleanup_fb(struct drm_plane *plane,
  129. struct drm_framebuffer *fb,
  130. const struct drm_plane_state *old_fb)
  131. {
  132. }
  133. static int sti_drm_plane_atomic_check(struct drm_plane *plane,
  134. struct drm_plane_state *state)
  135. {
  136. return 0;
  137. }
  138. static void sti_drm_plane_atomic_update(struct drm_plane *plane,
  139. struct drm_plane_state *oldstate)
  140. {
  141. struct drm_plane_state *state = plane->state;
  142. sti_drm_update_plane(plane, state->crtc, state->fb,
  143. state->crtc_x, state->crtc_y,
  144. state->crtc_w, state->crtc_h,
  145. state->src_x, state->src_y,
  146. state->src_w, state->src_h);
  147. }
  148. static void sti_drm_plane_atomic_disable(struct drm_plane *plane,
  149. struct drm_plane_state *oldstate)
  150. {
  151. sti_drm_disable_plane(plane);
  152. }
  153. static const struct drm_plane_helper_funcs sti_drm_plane_helpers_funcs = {
  154. .prepare_fb = sti_drm_plane_prepare_fb,
  155. .cleanup_fb = sti_drm_plane_cleanup_fb,
  156. .atomic_check = sti_drm_plane_atomic_check,
  157. .atomic_update = sti_drm_plane_atomic_update,
  158. .atomic_disable = sti_drm_plane_atomic_disable,
  159. };
  160. static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
  161. uint64_t default_val)
  162. {
  163. struct drm_device *dev = plane->dev;
  164. struct sti_drm_private *private = dev->dev_private;
  165. struct drm_property *prop;
  166. struct sti_layer *layer = to_sti_layer(plane);
  167. prop = private->plane_zorder_property;
  168. if (!prop) {
  169. prop = drm_property_create_range(dev, 0, "zpos", 0,
  170. GAM_MIXER_NB_DEPTH_LEVEL - 1);
  171. if (!prop)
  172. return;
  173. private->plane_zorder_property = prop;
  174. }
  175. drm_object_attach_property(&plane->base, prop, default_val);
  176. layer->zorder = default_val;
  177. }
  178. struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
  179. struct sti_layer *layer,
  180. unsigned int possible_crtcs,
  181. enum drm_plane_type type)
  182. {
  183. int err, i;
  184. uint64_t default_zorder = 0;
  185. err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
  186. &sti_drm_plane_funcs,
  187. sti_layer_get_formats(layer),
  188. sti_layer_get_nb_formats(layer), type);
  189. if (err) {
  190. DRM_ERROR("Failed to initialize plane\n");
  191. return NULL;
  192. }
  193. drm_plane_helper_add(&layer->plane, &sti_drm_plane_helpers_funcs);
  194. for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
  195. if (sti_layer_default_zorder[i] == layer->desc)
  196. break;
  197. default_zorder = i + 1;
  198. if (type == DRM_PLANE_TYPE_OVERLAY)
  199. sti_drm_plane_attach_zorder_property(&layer->plane,
  200. default_zorder);
  201. DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
  202. layer->plane.base.id,
  203. sti_layer_to_str(layer), default_zorder);
  204. return &layer->plane;
  205. }
  206. EXPORT_SYMBOL(sti_drm_plane_init);