0280-drm-vc4-Add-a-proper-short-circut-path-for-legacy-cu.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. From bdd4e13374cb436ccb534f5f58bd840e7d055ec9 Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <eric@anholt.net>
  3. Date: Wed, 30 Dec 2015 11:50:22 -0800
  4. Subject: [PATCH 280/381] drm/vc4: Add a proper short-circut path for legacy
  5. cursor updates.
  6. Previously, on every modeset we would allocate new display list
  7. memory, recompute changed planes, write all of them to the new memory,
  8. and pointed scanout at the new list (which will latch approximately at
  9. the next line of scanout). We let
  10. drm_atomic_helper_wait_for_vblanks() decide whether we needed to wait
  11. for a vblank after a modeset before cleaning up the old state and
  12. letting the next modeset proceed, and on legacy cursor updates we
  13. wouldn't wait. If you moved the cursor fast enough, we could
  14. potentially wrap around the display list memory area and overwrite the
  15. existing display list while it was still being scanned out, resulting
  16. in the HVS scanning out garbage or just halting.
  17. Instead of making cursor updates wait for scanout to move to the new
  18. display list area (which introduces significant cursor lag in X), we
  19. just rewrite our current display list.
  20. Signed-off-by: Eric Anholt <eric@anholt.net>
  21. (cherry picked from commit 6674a904d68041d982ffb284d2827410765a097a)
  22. ---
  23. drivers/gpu/drm/vc4/vc4_kms.c | 9 ++++
  24. drivers/gpu/drm/vc4/vc4_plane.c | 94 ++++++++++++++++++++++++++++++++++++++---
  25. 2 files changed, 96 insertions(+), 7 deletions(-)
  26. --- a/drivers/gpu/drm/vc4/vc4_kms.c
  27. +++ b/drivers/gpu/drm/vc4/vc4_kms.c
  28. @@ -49,6 +49,15 @@ vc4_atomic_complete_commit(struct vc4_co
  29. drm_atomic_helper_commit_modeset_enables(dev, state);
  30. + /* Make sure that drm_atomic_helper_wait_for_vblanks()
  31. + * actually waits for vblank. If we're doing a full atomic
  32. + * modeset (as opposed to a vc4_update_plane() short circuit),
  33. + * then we need to wait for scanout to be done with our
  34. + * display lists before we free it and potentially reallocate
  35. + * and overwrite the dlist memory with a new modeset.
  36. + */
  37. + state->legacy_cursor_update = false;
  38. +
  39. drm_atomic_helper_wait_for_vblanks(dev, state);
  40. drm_atomic_helper_cleanup_planes(dev, state);
  41. --- a/drivers/gpu/drm/vc4/vc4_plane.c
  42. +++ b/drivers/gpu/drm/vc4/vc4_plane.c
  43. @@ -33,8 +33,12 @@ struct vc4_plane_state {
  44. u32 dlist_size; /* Number of dwords allocated for the display list */
  45. u32 dlist_count; /* Number of used dwords in the display list. */
  46. - /* Offset in the dlist to pointer word 0. */
  47. - u32 pw0_offset;
  48. + /* Offset in the dlist to various words, for pageflip or
  49. + * cursor updates.
  50. + */
  51. + u32 pos0_offset;
  52. + u32 pos2_offset;
  53. + u32 ptr0_offset;
  54. /* Offset where the plane's dlist was last stored in the
  55. * hardware at vc4_crtc_atomic_flush() time.
  56. @@ -239,6 +243,7 @@ static int vc4_plane_mode_set(struct drm
  57. SCALER_CTL0_UNITY);
  58. /* Position Word 0: Image Positions and Alpha Value */
  59. + vc4_state->pos0_offset = vc4_state->dlist_count;
  60. vc4_dlist_write(vc4_state,
  61. VC4_SET_FIELD(0xff, SCALER_POS0_FIXED_ALPHA) |
  62. VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
  63. @@ -249,6 +254,7 @@ static int vc4_plane_mode_set(struct drm
  64. */
  65. /* Position Word 2: Source Image Size, Alpha Mode */
  66. + vc4_state->pos2_offset = vc4_state->dlist_count;
  67. vc4_dlist_write(vc4_state,
  68. VC4_SET_FIELD(format->has_alpha ?
  69. SCALER_POS2_ALPHA_MODE_PIPELINE :
  70. @@ -260,9 +266,8 @@ static int vc4_plane_mode_set(struct drm
  71. /* Position Word 3: Context. Written by the HVS. */
  72. vc4_dlist_write(vc4_state, 0xc0c0c0c0);
  73. - vc4_state->pw0_offset = vc4_state->dlist_count;
  74. -
  75. /* Pointer Word 0: RGB / Y Pointer */
  76. + vc4_state->ptr0_offset = vc4_state->dlist_count;
  77. vc4_dlist_write(vc4_state, bo->paddr + vc4_state->offset);
  78. /* Pointer Context Word 0: Written by the HVS */
  79. @@ -348,13 +353,13 @@ void vc4_plane_async_set_fb(struct drm_p
  80. * scanout will start from this address as soon as the FIFO
  81. * needs to refill with pixels.
  82. */
  83. - writel(addr, &vc4_state->hw_dlist[vc4_state->pw0_offset]);
  84. + writel(addr, &vc4_state->hw_dlist[vc4_state->ptr0_offset]);
  85. /* Also update the CPU-side dlist copy, so that any later
  86. * atomic updates that don't do a new modeset on our plane
  87. * also use our updated address.
  88. */
  89. - vc4_state->dlist[vc4_state->pw0_offset] = addr;
  90. + vc4_state->dlist[vc4_state->ptr0_offset] = addr;
  91. }
  92. static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
  93. @@ -370,8 +375,83 @@ static void vc4_plane_destroy(struct drm
  94. drm_plane_cleanup(plane);
  95. }
  96. +/* Implements immediate (non-vblank-synced) updates of the cursor
  97. + * position, or falls back to the atomic helper otherwise.
  98. + */
  99. +static int
  100. +vc4_update_plane(struct drm_plane *plane,
  101. + struct drm_crtc *crtc,
  102. + struct drm_framebuffer *fb,
  103. + int crtc_x, int crtc_y,
  104. + unsigned int crtc_w, unsigned int crtc_h,
  105. + uint32_t src_x, uint32_t src_y,
  106. + uint32_t src_w, uint32_t src_h)
  107. +{
  108. + struct drm_plane_state *plane_state;
  109. + struct vc4_plane_state *vc4_state;
  110. +
  111. + if (plane != crtc->cursor)
  112. + goto out;
  113. +
  114. + plane_state = plane->state;
  115. + vc4_state = to_vc4_plane_state(plane_state);
  116. +
  117. + if (!plane_state)
  118. + goto out;
  119. +
  120. + /* If we're changing the cursor contents, do that in the
  121. + * normal vblank-synced atomic path.
  122. + */
  123. + if (fb != plane_state->fb)
  124. + goto out;
  125. +
  126. + /* No configuring new scaling in the fast path. */
  127. + if (crtc_w != plane_state->crtc_w ||
  128. + crtc_h != plane_state->crtc_h ||
  129. + src_w != plane_state->src_w ||
  130. + src_h != plane_state->src_h) {
  131. + goto out;
  132. + }
  133. +
  134. + /* Set the cursor's position on the screen. This is the
  135. + * expected change from the drm_mode_cursor_universal()
  136. + * helper.
  137. + */
  138. + plane_state->crtc_x = crtc_x;
  139. + plane_state->crtc_y = crtc_y;
  140. +
  141. + /* Allow changing the start position within the cursor BO, if
  142. + * that matters.
  143. + */
  144. + plane_state->src_x = src_x;
  145. + plane_state->src_y = src_y;
  146. +
  147. + /* Update the display list based on the new crtc_x/y. */
  148. + vc4_plane_atomic_check(plane, plane_state);
  149. +
  150. + /* Note that we can't just call vc4_plane_write_dlist()
  151. + * because that would smash the context data that the HVS is
  152. + * currently using.
  153. + */
  154. + writel(vc4_state->dlist[vc4_state->pos0_offset],
  155. + &vc4_state->hw_dlist[vc4_state->pos0_offset]);
  156. + writel(vc4_state->dlist[vc4_state->pos2_offset],
  157. + &vc4_state->hw_dlist[vc4_state->pos2_offset]);
  158. + writel(vc4_state->dlist[vc4_state->ptr0_offset],
  159. + &vc4_state->hw_dlist[vc4_state->ptr0_offset]);
  160. +
  161. + return 0;
  162. +
  163. +out:
  164. + return drm_atomic_helper_update_plane(plane, crtc, fb,
  165. + crtc_x, crtc_y,
  166. + crtc_w, crtc_h,
  167. + src_x, src_y,
  168. + src_w, src_h);
  169. +}
  170. +
  171. static const struct drm_plane_funcs vc4_plane_funcs = {
  172. - .update_plane = drm_atomic_helper_update_plane,
  173. + .update_plane = vc4_update_plane,
  174. .disable_plane = drm_atomic_helper_disable_plane,
  175. .destroy = vc4_plane_destroy,
  176. .set_property = NULL,