aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-08-07 04:33:05 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-10-01 09:33:28 -0400
commit4a8506d2d68724b6d326621118874c07095c6645 (patch)
tree7dbe4d69e457c52aaff05902dc5d364666b7e6f7
parent4b5dda82c20c2eee500520010c0558789592d62f (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.c48
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h20
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c27
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
229void armada_drm_vbl_event_add(struct armada_crtc *dcrtc, 229struct 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
247void 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
258static 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
269static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc, 240static 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,
429static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) 400static 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);
52int armada_drm_plane_work_queue(struct armada_crtc *dcrtc, 52int 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);
54int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout); 54int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
55struct armada_plane_work *armada_drm_plane_work_cancel(
56 struct armada_crtc *dcrtc, struct armada_plane *plane);
55 57
56struct armada_crtc { 58struct 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
94struct armada_vbl_event {
95 struct list_head node;
96 void *data;
97 void (*fn)(struct armada_crtc *, void *);
98};
99
100void armada_drm_vbl_event_add(struct armada_crtc *,
101 struct armada_vbl_event *);
102void 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
111void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); 95void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
112void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); 96void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
113void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); 97void 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 === */
85static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data) 85static 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
95static int 94static 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,