sti_drm_plane.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 "sti_compositor.h"
  9. #include "sti_drm_drv.h"
  10. #include "sti_drm_plane.h"
  11. #include "sti_vtg.h"
  12. enum sti_layer_desc sti_layer_default_zorder[] = {
  13. STI_GDP_0,
  14. STI_VID_0,
  15. STI_GDP_1,
  16. STI_VID_1,
  17. STI_GDP_2,
  18. STI_GDP_3,
  19. };
  20. /* (Background) < GDP0 < VID0 < GDP1 < VID1 < GDP2 < GDP3 < (ForeGround) */
  21. static int
  22. sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
  23. struct drm_framebuffer *fb, int crtc_x, int crtc_y,
  24. unsigned int crtc_w, unsigned int crtc_h,
  25. uint32_t src_x, uint32_t src_y,
  26. uint32_t src_w, uint32_t src_h)
  27. {
  28. struct sti_layer *layer = to_sti_layer(plane);
  29. struct sti_mixer *mixer = to_sti_mixer(crtc);
  30. int res;
  31. DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s) drm fb:%d\n",
  32. crtc->base.id, sti_mixer_to_str(mixer),
  33. plane->base.id, sti_layer_to_str(layer), fb->base.id);
  34. DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", crtc_w, crtc_h, crtc_x, crtc_y);
  35. res = sti_mixer_set_layer_depth(mixer, layer);
  36. if (res) {
  37. DRM_ERROR("Can not set layer depth\n");
  38. return res;
  39. }
  40. /* src_x are in 16.16 format. */
  41. res = sti_layer_prepare(layer, crtc, fb,
  42. &crtc->mode, mixer->id,
  43. crtc_x, crtc_y, crtc_w, crtc_h,
  44. src_x >> 16, src_y >> 16,
  45. src_w >> 16, src_h >> 16);
  46. if (res) {
  47. DRM_ERROR("Layer prepare failed\n");
  48. return res;
  49. }
  50. res = sti_layer_commit(layer);
  51. if (res) {
  52. DRM_ERROR("Layer commit failed\n");
  53. return res;
  54. }
  55. res = sti_mixer_set_layer_status(mixer, layer, true);
  56. if (res) {
  57. DRM_ERROR("Can not enable layer at mixer\n");
  58. return res;
  59. }
  60. return 0;
  61. }
  62. static int sti_drm_disable_plane(struct drm_plane *plane)
  63. {
  64. struct sti_layer *layer;
  65. struct sti_mixer *mixer;
  66. int lay_res, mix_res;
  67. if (!plane->crtc) {
  68. DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
  69. return 0;
  70. }
  71. layer = to_sti_layer(plane);
  72. mixer = to_sti_mixer(plane->crtc);
  73. DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
  74. plane->crtc->base.id, sti_mixer_to_str(mixer),
  75. plane->base.id, sti_layer_to_str(layer));
  76. /* Disable layer at mixer level */
  77. mix_res = sti_mixer_set_layer_status(mixer, layer, false);
  78. if (mix_res)
  79. DRM_ERROR("Can not disable layer at mixer\n");
  80. /* Wait a while to be sure that a Vsync event is received */
  81. msleep(WAIT_NEXT_VSYNC_MS);
  82. /* Then disable layer itself */
  83. lay_res = sti_layer_disable(layer);
  84. if (lay_res)
  85. DRM_ERROR("Layer disable failed\n");
  86. if (lay_res || mix_res)
  87. return -EINVAL;
  88. return 0;
  89. }
  90. static void sti_drm_plane_destroy(struct drm_plane *plane)
  91. {
  92. DRM_DEBUG_DRIVER("\n");
  93. sti_drm_disable_plane(plane);
  94. drm_plane_cleanup(plane);
  95. }
  96. static int sti_drm_plane_set_property(struct drm_plane *plane,
  97. struct drm_property *property,
  98. uint64_t val)
  99. {
  100. struct drm_device *dev = plane->dev;
  101. struct sti_drm_private *private = dev->dev_private;
  102. struct sti_layer *layer = to_sti_layer(plane);
  103. DRM_DEBUG_DRIVER("\n");
  104. if (property == private->plane_zorder_property) {
  105. layer->zorder = val;
  106. return 0;
  107. }
  108. return -EINVAL;
  109. }
  110. static struct drm_plane_funcs sti_drm_plane_funcs = {
  111. .update_plane = sti_drm_update_plane,
  112. .disable_plane = sti_drm_disable_plane,
  113. .destroy = sti_drm_plane_destroy,
  114. .set_property = sti_drm_plane_set_property,
  115. };
  116. static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
  117. uint64_t default_val)
  118. {
  119. struct drm_device *dev = plane->dev;
  120. struct sti_drm_private *private = dev->dev_private;
  121. struct drm_property *prop;
  122. struct sti_layer *layer = to_sti_layer(plane);
  123. prop = private->plane_zorder_property;
  124. if (!prop) {
  125. prop = drm_property_create_range(dev, 0, "zpos", 0,
  126. GAM_MIXER_NB_DEPTH_LEVEL - 1);
  127. if (!prop)
  128. return;
  129. private->plane_zorder_property = prop;
  130. }
  131. drm_object_attach_property(&plane->base, prop, default_val);
  132. layer->zorder = default_val;
  133. }
  134. struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
  135. struct sti_layer *layer,
  136. unsigned int possible_crtcs,
  137. enum drm_plane_type type)
  138. {
  139. int err, i;
  140. uint64_t default_zorder = 0;
  141. err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
  142. &sti_drm_plane_funcs,
  143. sti_layer_get_formats(layer),
  144. sti_layer_get_nb_formats(layer), type);
  145. if (err) {
  146. DRM_ERROR("Failed to initialize plane\n");
  147. return NULL;
  148. }
  149. for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
  150. if (sti_layer_default_zorder[i] == layer->desc)
  151. break;
  152. default_zorder = i;
  153. if (type == DRM_PLANE_TYPE_OVERLAY)
  154. sti_drm_plane_attach_zorder_property(&layer->plane,
  155. default_zorder);
  156. DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
  157. layer->plane.base.id,
  158. sti_layer_to_str(layer), default_zorder);
  159. return &layer->plane;
  160. }
  161. EXPORT_SYMBOL(sti_drm_plane_init);