sti_drm_plane.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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, fb, &crtc->mode, mixer->id,
  42. crtc_x, crtc_y, crtc_w, crtc_h,
  43. src_x >> 16, src_y >> 16,
  44. src_w >> 16, src_h >> 16);
  45. if (res) {
  46. DRM_ERROR("Layer prepare failed\n");
  47. return res;
  48. }
  49. res = sti_layer_commit(layer);
  50. if (res) {
  51. DRM_ERROR("Layer commit failed\n");
  52. return res;
  53. }
  54. res = sti_mixer_set_layer_status(mixer, layer, true);
  55. if (res) {
  56. DRM_ERROR("Can not enable layer at mixer\n");
  57. return res;
  58. }
  59. return 0;
  60. }
  61. static int sti_drm_disable_plane(struct drm_plane *plane)
  62. {
  63. struct sti_layer *layer;
  64. struct sti_mixer *mixer;
  65. int lay_res, mix_res;
  66. if (!plane->crtc) {
  67. DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", plane->base.id);
  68. return 0;
  69. }
  70. layer = to_sti_layer(plane);
  71. mixer = to_sti_mixer(plane->crtc);
  72. DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n",
  73. plane->crtc->base.id, sti_mixer_to_str(mixer),
  74. plane->base.id, sti_layer_to_str(layer));
  75. /* Disable layer at mixer level */
  76. mix_res = sti_mixer_set_layer_status(mixer, layer, false);
  77. if (mix_res)
  78. DRM_ERROR("Can not disable layer at mixer\n");
  79. /* Wait a while to be sure that a Vsync event is received */
  80. msleep(WAIT_NEXT_VSYNC_MS);
  81. /* Then disable layer itself */
  82. lay_res = sti_layer_disable(layer);
  83. if (lay_res)
  84. DRM_ERROR("Layer disable failed\n");
  85. if (lay_res || mix_res)
  86. return -EINVAL;
  87. return 0;
  88. }
  89. static void sti_drm_plane_destroy(struct drm_plane *plane)
  90. {
  91. DRM_DEBUG_DRIVER("\n");
  92. sti_drm_disable_plane(plane);
  93. drm_plane_cleanup(plane);
  94. }
  95. static int sti_drm_plane_set_property(struct drm_plane *plane,
  96. struct drm_property *property,
  97. uint64_t val)
  98. {
  99. struct drm_device *dev = plane->dev;
  100. struct sti_drm_private *private = dev->dev_private;
  101. struct sti_layer *layer = to_sti_layer(plane);
  102. DRM_DEBUG_DRIVER("\n");
  103. if (property == private->plane_zorder_property) {
  104. layer->zorder = val;
  105. return 0;
  106. }
  107. return -EINVAL;
  108. }
  109. static struct drm_plane_funcs sti_drm_plane_funcs = {
  110. .update_plane = sti_drm_update_plane,
  111. .disable_plane = sti_drm_disable_plane,
  112. .destroy = sti_drm_plane_destroy,
  113. .set_property = sti_drm_plane_set_property,
  114. };
  115. static void sti_drm_plane_attach_zorder_property(struct drm_plane *plane,
  116. uint64_t default_val)
  117. {
  118. struct drm_device *dev = plane->dev;
  119. struct sti_drm_private *private = dev->dev_private;
  120. struct drm_property *prop;
  121. struct sti_layer *layer = to_sti_layer(plane);
  122. prop = private->plane_zorder_property;
  123. if (!prop) {
  124. prop = drm_property_create_range(dev, 0, "zpos", 0,
  125. GAM_MIXER_NB_DEPTH_LEVEL - 1);
  126. if (!prop)
  127. return;
  128. private->plane_zorder_property = prop;
  129. }
  130. drm_object_attach_property(&plane->base, prop, default_val);
  131. layer->zorder = default_val;
  132. }
  133. struct drm_plane *sti_drm_plane_init(struct drm_device *dev,
  134. struct sti_layer *layer,
  135. unsigned int possible_crtcs,
  136. enum drm_plane_type type)
  137. {
  138. int err, i;
  139. uint64_t default_zorder = 0;
  140. err = drm_universal_plane_init(dev, &layer->plane, possible_crtcs,
  141. &sti_drm_plane_funcs,
  142. sti_layer_get_formats(layer),
  143. sti_layer_get_nb_formats(layer), type);
  144. if (err) {
  145. DRM_ERROR("Failed to initialize plane\n");
  146. return NULL;
  147. }
  148. for (i = 0; i < ARRAY_SIZE(sti_layer_default_zorder); i++)
  149. if (sti_layer_default_zorder[i] == layer->desc)
  150. break;
  151. default_zorder = i;
  152. if (type == DRM_PLANE_TYPE_OVERLAY)
  153. sti_drm_plane_attach_zorder_property(&layer->plane,
  154. default_zorder);
  155. DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%llu\n",
  156. layer->plane.base.id,
  157. sti_layer_to_str(layer), default_zorder);
  158. return &layer->plane;
  159. }