aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-07-08 05:22:33 -0400
committerRussell King <rmk+kernel@armlinux.org.uk>2017-12-08 07:21:53 -0500
commit65843e9af759eb0d1a0f0ee6dc64b3162793132c (patch)
treeb141cdf2a83d241f46359e695c98bcfb26add661
parentd19f6ee5051be073939b6a013455355711708215 (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.h2
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c203
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
57struct armada_plane { 59struct 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
78static int 78static void armada_ovl_plane_update_state(struct drm_plane_state *state,
79armada_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
184static int
185armada_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