diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2017-07-08 05:22:33 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2017-12-08 07:21:53 -0500 |
commit | 65843e9af759eb0d1a0f0ee6dc64b3162793132c (patch) | |
tree | b141cdf2a83d241f46359e695c98bcfb26add661 | |
parent | d19f6ee5051be073939b6a013455355711708215 (diff) |
drm/armada: move overlay plane register update generation
Move the overlay plane register update generation to a separate function
as this is independent of the legacy or atomic update.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_overlay.c | 203 |
2 files changed, 112 insertions, 93 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 0c7b519c09e8..445829b8877a 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h | |||
@@ -52,6 +52,8 @@ struct armada_plane_state { | |||
52 | u32 dst_hw; | 52 | u32 dst_hw; |
53 | u32 dst_yx; | 53 | u32 dst_yx; |
54 | u32 ctrl0; | 54 | u32 ctrl0; |
55 | bool changed; | ||
56 | bool vsync_update; | ||
55 | }; | 57 | }; |
56 | 58 | ||
57 | struct armada_plane { | 59 | struct armada_plane { |
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 00da2c58701c..e5fa346f572b 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c | |||
@@ -75,153 +75,172 @@ static void armada_ovl_plane_work(struct armada_crtc *dcrtc, | |||
75 | spin_unlock_irqrestore(&dcrtc->irq_lock, flags); | 75 | spin_unlock_irqrestore(&dcrtc->irq_lock, flags); |
76 | } | 76 | } |
77 | 77 | ||
78 | static int | 78 | static void armada_ovl_plane_update_state(struct drm_plane_state *state, |
79 | armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | 79 | struct armada_regs *regs) |
80 | struct drm_framebuffer *fb, | ||
81 | int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, | ||
82 | uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, | ||
83 | struct drm_modeset_acquire_ctx *ctx) | ||
84 | { | 80 | { |
85 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); | 81 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(state->plane); |
86 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | 82 | struct armada_framebuffer *dfb = drm_fb_to_armada_fb(state->fb); |
87 | struct armada_plane_work *work; | ||
88 | const struct drm_format_info *format; | 83 | const struct drm_format_info *format; |
89 | struct drm_plane_state state = { | 84 | unsigned int idx = 0; |
90 | .plane = plane, | ||
91 | .crtc = crtc, | ||
92 | .fb = fb, | ||
93 | .src_x = src_x, | ||
94 | .src_y = src_y, | ||
95 | .src_w = src_w, | ||
96 | .src_h = src_h, | ||
97 | .crtc_x = crtc_x, | ||
98 | .crtc_y = crtc_y, | ||
99 | .crtc_w = crtc_w, | ||
100 | .crtc_h = crtc_h, | ||
101 | .rotation = DRM_MODE_ROTATE_0, | ||
102 | }; | ||
103 | const struct drm_rect clip = { | ||
104 | .x2 = crtc->mode.hdisplay, | ||
105 | .y2 = crtc->mode.vdisplay, | ||
106 | }; | ||
107 | uint32_t val, ctrl0; | ||
108 | unsigned idx = 0; | ||
109 | bool fb_changed; | 85 | bool fb_changed; |
110 | int ret; | 86 | u32 val, ctrl0; |
87 | u16 src_x, src_y; | ||
111 | 88 | ||
112 | trace_armada_ovl_plane_update(plane, crtc, fb, | 89 | ctrl0 = CFG_DMA_FMT(dfb->fmt) | CFG_DMA_MOD(dfb->mod) | CFG_CBSH_ENA; |
113 | crtc_x, crtc_y, crtc_w, crtc_h, | 90 | if (state->visible) |
114 | src_x, src_y, src_w, src_h); | ||
115 | |||
116 | ret = drm_plane_helper_check_state(&state, &clip, 0, INT_MAX, true, | ||
117 | false); | ||
118 | if (ret) | ||
119 | return ret; | ||
120 | |||
121 | work = &dplane->base.works[dplane->base.next_work]; | ||
122 | |||
123 | ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) | | ||
124 | CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) | | ||
125 | CFG_CBSH_ENA; | ||
126 | if (state.visible) | ||
127 | ctrl0 |= CFG_DMA_ENA; | 91 | ctrl0 |= CFG_DMA_ENA; |
128 | if (drm_rect_width(&state.src) >> 16 != drm_rect_width(&state.dst)) | 92 | if (drm_rect_width(&state->src) >> 16 != drm_rect_width(&state->dst)) |
129 | ctrl0 |= CFG_DMA_HSMOOTH; | 93 | ctrl0 |= CFG_DMA_HSMOOTH; |
130 | 94 | ||
131 | /* | 95 | /* |
132 | * Shifting a YUV packed format image by one pixel causes the U/V | 96 | * Shifting a YUV packed format image by one pixel causes the U/V |
133 | * planes to swap. Compensate for it by also toggling the UV swap. | 97 | * planes to swap. Compensate for it by also toggling the UV swap. |
134 | */ | 98 | */ |
135 | format = fb->format; | 99 | format = dfb->fb.format; |
136 | if (format->num_planes == 1 && state.src.x1 >> 16 & (format->hsub - 1)) | 100 | if (format->num_planes == 1 && state->src.x1 >> 16 & (format->hsub - 1)) |
137 | ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); | 101 | ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV); |
138 | 102 | ||
139 | if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) { | 103 | if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) { |
140 | /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ | 104 | /* Power up the Y/U/V FIFOs on ENA 0->1 transitions */ |
141 | armada_reg_queue_mod(work->regs, idx, | 105 | armada_reg_queue_mod(regs, idx, |
142 | 0, CFG_PDWN16x66 | CFG_PDWN32x66, | 106 | 0, CFG_PDWN16x66 | CFG_PDWN32x66, |
143 | LCD_SPU_SRAM_PARA1); | 107 | LCD_SPU_SRAM_PARA1); |
144 | } | 108 | } |
145 | 109 | ||
146 | fb_changed = plane->fb != fb || | 110 | fb_changed = dplane->base.base.fb != &dfb->fb || |
147 | dplane->base.state.src_x != state.src.x1 >> 16 || | 111 | dplane->base.state.src_x != state->src.x1 >> 16 || |
148 | dplane->base.state.src_y != state.src.y1 >> 16; | 112 | dplane->base.state.src_y != state->src.y1 >> 16; |
113 | |||
114 | dplane->base.state.vsync_update = fb_changed; | ||
149 | 115 | ||
150 | /* FIXME: overlay on an interlaced display */ | 116 | /* FIXME: overlay on an interlaced display */ |
151 | if (fb_changed) { | 117 | if (fb_changed) { |
152 | u32 addrs[3]; | 118 | u32 addrs[3]; |
153 | 119 | ||
154 | /* | 120 | dplane->base.state.src_y = src_y = state->src.y1 >> 16; |
155 | * Take a reference on the new framebuffer - we want to | 121 | dplane->base.state.src_x = src_x = state->src.x1 >> 16; |
156 | * hold on to it while the hardware is displaying it. | ||
157 | */ | ||
158 | drm_framebuffer_get(fb); | ||
159 | |||
160 | work->old_fb = plane->fb; | ||
161 | 122 | ||
162 | dplane->base.state.src_y = src_y = state.src.y1 >> 16; | 123 | armada_drm_plane_calc_addrs(addrs, &dfb->fb, src_x, src_y); |
163 | dplane->base.state.src_x = src_x = state.src.x1 >> 16; | ||
164 | 124 | ||
165 | armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y); | 125 | armada_reg_queue_set(regs, idx, addrs[0], |
166 | |||
167 | armada_reg_queue_set(work->regs, idx, addrs[0], | ||
168 | LCD_SPU_DMA_START_ADDR_Y0); | 126 | LCD_SPU_DMA_START_ADDR_Y0); |
169 | armada_reg_queue_set(work->regs, idx, addrs[1], | 127 | armada_reg_queue_set(regs, idx, addrs[1], |
170 | LCD_SPU_DMA_START_ADDR_U0); | 128 | LCD_SPU_DMA_START_ADDR_U0); |
171 | armada_reg_queue_set(work->regs, idx, addrs[2], | 129 | armada_reg_queue_set(regs, idx, addrs[2], |
172 | LCD_SPU_DMA_START_ADDR_V0); | 130 | LCD_SPU_DMA_START_ADDR_V0); |
173 | armada_reg_queue_set(work->regs, idx, addrs[0], | 131 | armada_reg_queue_set(regs, idx, addrs[0], |
174 | LCD_SPU_DMA_START_ADDR_Y1); | 132 | LCD_SPU_DMA_START_ADDR_Y1); |
175 | armada_reg_queue_set(work->regs, idx, addrs[1], | 133 | armada_reg_queue_set(regs, idx, addrs[1], |
176 | LCD_SPU_DMA_START_ADDR_U1); | 134 | LCD_SPU_DMA_START_ADDR_U1); |
177 | armada_reg_queue_set(work->regs, idx, addrs[2], | 135 | armada_reg_queue_set(regs, idx, addrs[2], |
178 | LCD_SPU_DMA_START_ADDR_V1); | 136 | LCD_SPU_DMA_START_ADDR_V1); |
179 | 137 | ||
180 | val = fb->pitches[0] << 16 | fb->pitches[0]; | 138 | val = dfb->fb.pitches[0] << 16 | dfb->fb.pitches[0]; |
181 | armada_reg_queue_set(work->regs, idx, val, | 139 | armada_reg_queue_set(regs, idx, val, |
182 | LCD_SPU_DMA_PITCH_YC); | 140 | LCD_SPU_DMA_PITCH_YC); |
183 | val = fb->pitches[1] << 16 | fb->pitches[2]; | 141 | val = dfb->fb.pitches[1] << 16 | dfb->fb.pitches[2]; |
184 | armada_reg_queue_set(work->regs, idx, val, | 142 | armada_reg_queue_set(regs, idx, val, |
185 | LCD_SPU_DMA_PITCH_UV); | 143 | LCD_SPU_DMA_PITCH_UV); |
186 | } else { | ||
187 | work->old_fb = NULL; | ||
188 | } | 144 | } |
189 | 145 | ||
190 | val = (drm_rect_height(&state.src) & 0xffff0000) | | 146 | val = (drm_rect_height(&state->src) & 0xffff0000) | |
191 | drm_rect_width(&state.src) >> 16; | 147 | drm_rect_width(&state->src) >> 16; |
192 | if (dplane->base.state.src_hw != val) { | 148 | if (dplane->base.state.src_hw != val) { |
193 | dplane->base.state.src_hw = val; | 149 | dplane->base.state.src_hw = val; |
194 | armada_reg_queue_set(work->regs, idx, val, | 150 | armada_reg_queue_set(regs, idx, val, |
195 | LCD_SPU_DMA_HPXL_VLN); | 151 | LCD_SPU_DMA_HPXL_VLN); |
196 | } | 152 | } |
197 | 153 | ||
198 | val = drm_rect_height(&state.dst) << 16 | drm_rect_width(&state.dst); | 154 | val = drm_rect_height(&state->dst) << 16 | drm_rect_width(&state->dst); |
199 | if (dplane->base.state.dst_hw != val) { | 155 | if (dplane->base.state.dst_hw != val) { |
200 | dplane->base.state.dst_hw = val; | 156 | dplane->base.state.dst_hw = val; |
201 | armada_reg_queue_set(work->regs, idx, val, | 157 | armada_reg_queue_set(regs, idx, val, |
202 | LCD_SPU_DZM_HPXL_VLN); | 158 | LCD_SPU_DZM_HPXL_VLN); |
203 | } | 159 | } |
204 | 160 | ||
205 | val = state.dst.y1 << 16 | state.dst.x1; | 161 | val = state->dst.y1 << 16 | state->dst.x1; |
206 | if (dplane->base.state.dst_yx != val) { | 162 | if (dplane->base.state.dst_yx != val) { |
207 | dplane->base.state.dst_yx = val; | 163 | dplane->base.state.dst_yx = val; |
208 | armada_reg_queue_set(work->regs, idx, val, | 164 | armada_reg_queue_set(regs, idx, val, |
209 | LCD_SPU_DMA_OVSA_HPXL_VLN); | 165 | LCD_SPU_DMA_OVSA_HPXL_VLN); |
210 | } | 166 | } |
211 | 167 | ||
212 | if (dplane->base.state.ctrl0 != ctrl0) { | 168 | if (dplane->base.state.ctrl0 != ctrl0) { |
213 | dplane->base.state.ctrl0 = ctrl0; | 169 | dplane->base.state.ctrl0 = ctrl0; |
214 | armada_reg_queue_mod(work->regs, idx, ctrl0, | 170 | armada_reg_queue_mod(regs, idx, ctrl0, |
215 | CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | | 171 | CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE | |
216 | CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | | 172 | CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE | |
217 | CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | | 173 | CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU | |
218 | CFG_YUV2RGB) | CFG_DMA_ENA, | 174 | CFG_YUV2RGB) | CFG_DMA_ENA, |
219 | LCD_SPU_DMA_CTRL0); | 175 | LCD_SPU_DMA_CTRL0); |
176 | dplane->base.state.vsync_update = true; | ||
220 | } | 177 | } |
221 | 178 | ||
179 | dplane->base.state.changed = idx != 0; | ||
180 | |||
181 | armada_reg_queue_end(regs, idx); | ||
182 | } | ||
183 | |||
184 | static int | ||
185 | armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | ||
186 | struct drm_framebuffer *fb, | ||
187 | int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h, | ||
188 | uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h, | ||
189 | struct drm_modeset_acquire_ctx *ctx) | ||
190 | { | ||
191 | struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane); | ||
192 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | ||
193 | struct armada_plane_work *work; | ||
194 | struct drm_plane_state state = { | ||
195 | .plane = plane, | ||
196 | .crtc = crtc, | ||
197 | .fb = fb, | ||
198 | .src_x = src_x, | ||
199 | .src_y = src_y, | ||
200 | .src_w = src_w, | ||
201 | .src_h = src_h, | ||
202 | .crtc_x = crtc_x, | ||
203 | .crtc_y = crtc_y, | ||
204 | .crtc_w = crtc_w, | ||
205 | .crtc_h = crtc_h, | ||
206 | .rotation = DRM_MODE_ROTATE_0, | ||
207 | }; | ||
208 | const struct drm_rect clip = { | ||
209 | .x2 = crtc->mode.hdisplay, | ||
210 | .y2 = crtc->mode.vdisplay, | ||
211 | }; | ||
212 | int ret; | ||
213 | |||
214 | trace_armada_ovl_plane_update(plane, crtc, fb, | ||
215 | crtc_x, crtc_y, crtc_w, crtc_h, | ||
216 | src_x, src_y, src_w, src_h); | ||
217 | |||
218 | ret = drm_plane_helper_check_state(&state, &clip, 0, INT_MAX, true, | ||
219 | false); | ||
220 | if (ret) | ||
221 | return ret; | ||
222 | |||
223 | work = &dplane->base.works[dplane->base.next_work]; | ||
224 | |||
225 | if (plane->fb != fb) { | ||
226 | /* | ||
227 | * Take a reference on the new framebuffer - we want to | ||
228 | * hold on to it while the hardware is displaying it. | ||
229 | */ | ||
230 | drm_framebuffer_reference(fb); | ||
231 | |||
232 | work->old_fb = plane->fb; | ||
233 | } else { | ||
234 | work->old_fb = NULL; | ||
235 | } | ||
236 | |||
237 | armada_ovl_plane_update_state(&state, work->regs); | ||
238 | |||
239 | if (!dplane->base.state.changed) | ||
240 | return 0; | ||
241 | |||
222 | /* Just updating the position/size? */ | 242 | /* Just updating the position/size? */ |
223 | if (!fb_changed && dplane->base.state.ctrl0 == ctrl0) { | 243 | if (!dplane->base.state.vsync_update) { |
224 | armada_reg_queue_end(work->regs, idx); | ||
225 | armada_ovl_plane_work(dcrtc, work); | 244 | armada_ovl_plane_work(dcrtc, work); |
226 | return 0; | 245 | return 0; |
227 | } | 246 | } |
@@ -235,15 +254,13 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
235 | armada_ovl_update_attr(&dplane->prop, dcrtc); | 254 | armada_ovl_update_attr(&dplane->prop, dcrtc); |
236 | } | 255 | } |
237 | 256 | ||
238 | if (idx) { | 257 | /* Queue it for update on the next interrupt if we are enabled */ |
239 | armada_reg_queue_end(work->regs, idx); | 258 | ret = armada_drm_plane_work_queue(dcrtc, work); |
240 | /* Queue it for update on the next interrupt if we are enabled */ | 259 | if (ret) |
241 | ret = armada_drm_plane_work_queue(dcrtc, work); | 260 | DRM_ERROR("failed to queue plane work: %d\n", ret); |
242 | if (ret) | 261 | |
243 | DRM_ERROR("failed to queue plane work: %d\n", ret); | 262 | dplane->base.next_work = !dplane->base.next_work; |
244 | 263 | ||
245 | dplane->base.next_work = !dplane->base.next_work; | ||
246 | } | ||
247 | return 0; | 264 | return 0; |
248 | } | 265 | } |
249 | 266 | ||