diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-08-07 04:33:05 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2015-10-01 09:33:28 -0400 |
commit | 4a8506d2d68724b6d326621118874c07095c6645 (patch) | |
tree | 7dbe4d69e457c52aaff05902dc5d364666b7e6f7 | |
parent | 4b5dda82c20c2eee500520010c0558789592d62f (diff) |
drm/armada: convert overlay plane vbl worker to a armada plane worker
Convert the overlay plane to use the generic armada plane worker
infrastructure which is shared with the primary plane.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.h | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_overlay.c | 27 |
3 files changed, 26 insertions, 69 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 0c1a1524f5d5..418dbfad4271 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
@@ -226,44 +226,15 @@ int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout) | |||
226 | return wait_event_timeout(plane->frame_wait, !plane->work, timeout); | 226 | return wait_event_timeout(plane->frame_wait, !plane->work, timeout); |
227 | } | 227 | } |
228 | 228 | ||
229 | void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, | 229 | struct armada_plane_work *armada_drm_plane_work_cancel( |
230 | struct armada_vbl_event *evt) | 230 | struct armada_crtc *dcrtc, struct armada_plane *plane) |
231 | { | 231 | { |
232 | unsigned long flags; | 232 | struct armada_plane_work *work = xchg(&plane->work, NULL); |
233 | bool not_on_list; | ||
234 | |||
235 | WARN_ON(drm_vblank_get(dcrtc->crtc.dev, dcrtc->num)); | ||
236 | |||
237 | spin_lock_irqsave(&dcrtc->irq_lock, flags); | ||
238 | not_on_list = list_empty(&evt->node); | ||
239 | if (not_on_list) | ||
240 | list_add_tail(&evt->node, &dcrtc->vbl_list); | ||
241 | spin_unlock_irqrestore(&dcrtc->irq_lock, flags); | ||
242 | 233 | ||
243 | if (!not_on_list) | 234 | if (work) |
244 | drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); | 235 | drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); |
245 | } | ||
246 | 236 | ||
247 | void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc, | 237 | return work; |
248 | struct armada_vbl_event *evt) | ||
249 | { | ||
250 | spin_lock_irq(&dcrtc->irq_lock); | ||
251 | if (!list_empty(&evt->node)) { | ||
252 | list_del_init(&evt->node); | ||
253 | drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); | ||
254 | } | ||
255 | spin_unlock_irq(&dcrtc->irq_lock); | ||
256 | } | ||
257 | |||
258 | static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc) | ||
259 | { | ||
260 | struct armada_vbl_event *e, *n; | ||
261 | |||
262 | list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) { | ||
263 | list_del_init(&e->node); | ||
264 | drm_vblank_put(dcrtc->crtc.dev, dcrtc->num); | ||
265 | e->fn(dcrtc, e->data); | ||
266 | } | ||
267 | } | 238 | } |
268 | 239 | ||
269 | static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, | 240 | static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, |
@@ -429,6 +400,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc, | |||
429 | static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) | 400 | static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) |
430 | { | 401 | { |
431 | void __iomem *base = dcrtc->base; | 402 | void __iomem *base = dcrtc->base; |
403 | struct drm_plane *ovl_plane; | ||
432 | 404 | ||
433 | if (stat & DMA_FF_UNDERFLOW) | 405 | if (stat & DMA_FF_UNDERFLOW) |
434 | DRM_ERROR("video underflow on crtc %u\n", dcrtc->num); | 406 | DRM_ERROR("video underflow on crtc %u\n", dcrtc->num); |
@@ -439,7 +411,12 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) | |||
439 | drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num); | 411 | drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num); |
440 | 412 | ||
441 | spin_lock(&dcrtc->irq_lock); | 413 | spin_lock(&dcrtc->irq_lock); |
442 | armada_drm_vbl_event_run(dcrtc); | 414 | ovl_plane = dcrtc->plane; |
415 | if (ovl_plane) { | ||
416 | struct armada_plane *plane = drm_to_armada_plane(ovl_plane); | ||
417 | armada_drm_plane_work_run(dcrtc, plane); | ||
418 | wake_up(&plane->frame_wait); | ||
419 | } | ||
443 | 420 | ||
444 | if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { | 421 | if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) { |
445 | int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; | 422 | int i = stat & GRA_FRAME_IRQ0 ? 0 : 1; |
@@ -1188,7 +1165,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, | |||
1188 | dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24; | 1165 | dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24; |
1189 | spin_lock_init(&dcrtc->irq_lock); | 1166 | spin_lock_init(&dcrtc->irq_lock); |
1190 | dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR; | 1167 | dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR; |
1191 | INIT_LIST_HEAD(&dcrtc->vbl_list); | ||
1192 | 1168 | ||
1193 | /* Initialize some registers which we don't otherwise set */ | 1169 | /* Initialize some registers which we don't otherwise set */ |
1194 | writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV); | 1170 | writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV); |
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index aaad5ab78673..04fdd22d483b 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h | |||
@@ -52,6 +52,8 @@ int armada_drm_plane_init(struct armada_plane *plane); | |||
52 | int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, | 52 | int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, |
53 | struct armada_plane *plane, struct armada_plane_work *work); | 53 | struct armada_plane *plane, struct armada_plane_work *work); |
54 | int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); | 54 | int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); |
55 | struct armada_plane_work *armada_drm_plane_work_cancel( | ||
56 | struct armada_crtc *dcrtc, struct armada_plane *plane); | ||
55 | 57 | ||
56 | struct armada_crtc { | 58 | struct armada_crtc { |
57 | struct drm_crtc crtc; | 59 | struct drm_crtc crtc; |
@@ -87,27 +89,9 @@ struct armada_crtc { | |||
87 | 89 | ||
88 | spinlock_t irq_lock; | 90 | spinlock_t irq_lock; |
89 | uint32_t irq_ena; | 91 | uint32_t irq_ena; |
90 | struct list_head vbl_list; | ||
91 | }; | 92 | }; |
92 | #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) | 93 | #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) |
93 | 94 | ||
94 | struct armada_vbl_event { | ||
95 | struct list_head node; | ||
96 | void *data; | ||
97 | void (*fn)(struct armada_crtc *, void *); | ||
98 | }; | ||
99 | |||
100 | void armada_drm_vbl_event_add(struct armada_crtc *, | ||
101 | struct armada_vbl_event *); | ||
102 | void armada_drm_vbl_event_remove(struct armada_crtc *, | ||
103 | struct armada_vbl_event *); | ||
104 | #define armada_drm_vbl_event_init(_e, _f, _d) do { \ | ||
105 | struct armada_vbl_event *__e = _e; \ | ||
106 | INIT_LIST_HEAD(&__e->node); \ | ||
107 | __e->data = _d; \ | ||
108 | __e->fn = _f; \ | ||
109 | } while (0) | ||
110 | |||
111 | void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); | 95 | void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); |
112 | void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); | 96 | void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); |
113 | void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); | 97 | void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); |
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 9a5bab765085..5c22b380f8f3 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c | |||
@@ -37,7 +37,7 @@ struct armada_ovl_plane { | |||
37 | uint32_t dst_yx; | 37 | uint32_t dst_yx; |
38 | uint32_t ctrl0; | 38 | uint32_t ctrl0; |
39 | struct { | 39 | struct { |
40 | struct armada_vbl_event update; | 40 | struct armada_plane_work work; |
41 | struct armada_regs regs[13]; | 41 | struct armada_regs regs[13]; |
42 | } vbl; | 42 | } vbl; |
43 | struct armada_ovl_plane_properties prop; | 43 | struct armada_ovl_plane_properties prop; |
@@ -82,14 +82,13 @@ static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane, | |||
82 | } | 82 | } |
83 | 83 | ||
84 | /* === Plane support === */ | 84 | /* === Plane support === */ |
85 | static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) | 85 | static void armada_ovl_plane_work(struct armada_crtc *dcrtc, |
86 | struct armada_plane *plane, struct armada_plane_work *work) | ||
86 | { | 87 | { |
87 | struct armada_ovl_plane *dplane = data; | 88 | struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base); |
88 | 89 | ||
89 | armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); | 90 | armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs); |
90 | armada_ovl_retire_fb(dplane, NULL); | 91 | armada_ovl_retire_fb(dplane, NULL); |
91 | |||
92 | wake_up(&dplane->base.frame_wait); | ||
93 | } | 92 | } |
94 | 93 | ||
95 | static int | 94 | static int |
@@ -162,9 +161,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
162 | dcrtc->base + LCD_SPU_SRAM_PARA1); | 161 | dcrtc->base + LCD_SPU_SRAM_PARA1); |
163 | } | 162 | } |
164 | 163 | ||
165 | wait_event_timeout(dplane->base.frame_wait, | 164 | if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0) |
166 | list_empty(&dplane->vbl.update.node), | 165 | armada_drm_plane_work_cancel(dcrtc, &dplane->base); |
167 | HZ/25); | ||
168 | 166 | ||
169 | if (plane->fb != fb) { | 167 | if (plane->fb != fb) { |
170 | struct armada_gem_object *obj = drm_fb_obj(fb); | 168 | struct armada_gem_object *obj = drm_fb_obj(fb); |
@@ -255,7 +253,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
255 | } | 253 | } |
256 | if (idx) { | 254 | if (idx) { |
257 | armada_reg_queue_end(dplane->vbl.regs, idx); | 255 | armada_reg_queue_end(dplane->vbl.regs, idx); |
258 | armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update); | 256 | armada_drm_plane_work_queue(dcrtc, &dplane->base, |
257 | &dplane->vbl.work); | ||
259 | } | 258 | } |
260 | return 0; | 259 | return 0; |
261 | } | 260 | } |
@@ -270,14 +269,13 @@ static int armada_ovl_plane_disable(struct drm_plane *plane) | |||
270 | return 0; | 269 | return 0; |
271 | 270 | ||
272 | dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); | 271 | dcrtc = drm_to_armada_crtc(dplane->base.base.crtc); |
273 | dcrtc->plane = NULL; | ||
274 | 272 | ||
275 | armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update); | 273 | armada_drm_plane_work_cancel(dcrtc, &dplane->base); |
274 | armada_drm_crtc_plane_disable(dcrtc, plane); | ||
276 | 275 | ||
276 | dcrtc->plane = NULL; | ||
277 | dplane->ctrl0 = 0; | 277 | dplane->ctrl0 = 0; |
278 | 278 | ||
279 | armada_drm_crtc_plane_disable(dcrtc, plane); | ||
280 | |||
281 | fb = xchg(&dplane->old_fb, NULL); | 279 | fb = xchg(&dplane->old_fb, NULL); |
282 | if (fb) | 280 | if (fb) |
283 | drm_framebuffer_unreference(fb); | 281 | drm_framebuffer_unreference(fb); |
@@ -456,8 +454,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) | |||
456 | return ret; | 454 | return ret; |
457 | } | 455 | } |
458 | 456 | ||
459 | armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl, | 457 | dplane->vbl.work.fn = armada_ovl_plane_work; |
460 | dplane); | ||
461 | 458 | ||
462 | ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, | 459 | ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs, |
463 | &armada_ovl_plane_funcs, | 460 | &armada_ovl_plane_funcs, |