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