drm/armada: convert overlay plane vbl worker to a armada plane worker
authorRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 7 Aug 2015 08:33:05 +0000 (09:33 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 1 Oct 2015 13:33:28 +0000 (14:33 +0100)
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>
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_crtc.h
drivers/gpu/drm/armada/armada_overlay.c

index 0c1a1524f5d515bd9e1891133fb58155e189d307..418dbfad4271cde95c411c9bbbe9e9c1214f6afc 100644 (file)
@@ -226,44 +226,15 @@ int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout)
        return wait_event_timeout(plane->frame_wait, !plane->work, timeout);
 }
 
-void armada_drm_vbl_event_add(struct armada_crtc *dcrtc,
-       struct armada_vbl_event *evt)
+struct armada_plane_work *armada_drm_plane_work_cancel(
+       struct armada_crtc *dcrtc, struct armada_plane *plane)
 {
-       unsigned long flags;
-       bool not_on_list;
-
-       WARN_ON(drm_vblank_get(dcrtc->crtc.dev, dcrtc->num));
-
-       spin_lock_irqsave(&dcrtc->irq_lock, flags);
-       not_on_list = list_empty(&evt->node);
-       if (not_on_list)
-               list_add_tail(&evt->node, &dcrtc->vbl_list);
-       spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
+       struct armada_plane_work *work = xchg(&plane->work, NULL);
 
-       if (!not_on_list)
+       if (work)
                drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
-}
 
-void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc,
-       struct armada_vbl_event *evt)
-{
-       spin_lock_irq(&dcrtc->irq_lock);
-       if (!list_empty(&evt->node)) {
-               list_del_init(&evt->node);
-               drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
-       }
-       spin_unlock_irq(&dcrtc->irq_lock);
-}
-
-static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc)
-{
-       struct armada_vbl_event *e, *n;
-
-       list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) {
-               list_del_init(&e->node);
-               drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
-               e->fn(dcrtc, e->data);
-       }
+       return work;
 }
 
 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,
 static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 {
        void __iomem *base = dcrtc->base;
+       struct drm_plane *ovl_plane;
 
        if (stat & DMA_FF_UNDERFLOW)
                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)
                drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num);
 
        spin_lock(&dcrtc->irq_lock);
-       armada_drm_vbl_event_run(dcrtc);
+       ovl_plane = dcrtc->plane;
+       if (ovl_plane) {
+               struct armada_plane *plane = drm_to_armada_plane(ovl_plane);
+               armada_drm_plane_work_run(dcrtc, plane);
+               wake_up(&plane->frame_wait);
+       }
 
        if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
                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,
        dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
        spin_lock_init(&dcrtc->irq_lock);
        dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR;
-       INIT_LIST_HEAD(&dcrtc->vbl_list);
 
        /* Initialize some registers which we don't otherwise set */
        writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV);
index aaad5ab7867378f8b162eb127ed27242519152dd..04fdd22d483bd8e56787b95bbfcfc8b490f52e91 100644 (file)
@@ -52,6 +52,8 @@ int armada_drm_plane_init(struct armada_plane *plane);
 int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
        struct armada_plane *plane, struct armada_plane_work *work);
 int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
+struct armada_plane_work *armada_drm_plane_work_cancel(
+       struct armada_crtc *dcrtc, struct armada_plane *plane);
 
 struct armada_crtc {
        struct drm_crtc         crtc;
@@ -87,27 +89,9 @@ struct armada_crtc {
 
        spinlock_t              irq_lock;
        uint32_t                irq_ena;
-       struct list_head        vbl_list;
 };
 #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
 
-struct armada_vbl_event {
-       struct list_head        node;
-       void                    *data;
-       void                    (*fn)(struct armada_crtc *, void *);
-};
-
-void armada_drm_vbl_event_add(struct armada_crtc *,
-       struct armada_vbl_event *);
-void armada_drm_vbl_event_remove(struct armada_crtc *,
-       struct armada_vbl_event *);
-#define armada_drm_vbl_event_init(_e, _f, _d) do {     \
-       struct armada_vbl_event *__e = _e;              \
-       INIT_LIST_HEAD(&__e->node);                     \
-       __e->data = _d;                                 \
-       __e->fn = _f;                                   \
-} while (0)
-
 void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
 void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
 void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
index 9a5bab765085293d351a31b7e1e89681cddf4aaa..5c22b380f8f3e48dd9c2f6d7d1346c2bfc740b48 100644 (file)
@@ -37,7 +37,7 @@ struct armada_ovl_plane {
        uint32_t dst_yx;
        uint32_t ctrl0;
        struct {
-               struct armada_vbl_event update;
+               struct armada_plane_work work;
                struct armada_regs regs[13];
        } vbl;
        struct armada_ovl_plane_properties prop;
@@ -82,14 +82,13 @@ static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane,
 }
 
 /* === Plane support === */
-static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data)
+static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
+       struct armada_plane *plane, struct armada_plane_work *work)
 {
-       struct armada_ovl_plane *dplane = data;
+       struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base);
 
        armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
        armada_ovl_retire_fb(dplane, NULL);
-
-       wake_up(&dplane->base.frame_wait);
 }
 
 static int
@@ -162,9 +161,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
                               dcrtc->base + LCD_SPU_SRAM_PARA1);
        }
 
-       wait_event_timeout(dplane->base.frame_wait,
-                          list_empty(&dplane->vbl.update.node),
-                          HZ/25);
+       if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0)
+               armada_drm_plane_work_cancel(dcrtc, &dplane->base);
 
        if (plane->fb != fb) {
                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,
        }
        if (idx) {
                armada_reg_queue_end(dplane->vbl.regs, idx);
-               armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update);
+               armada_drm_plane_work_queue(dcrtc, &dplane->base,
+                                           &dplane->vbl.work);
        }
        return 0;
 }
@@ -270,14 +269,13 @@ static int armada_ovl_plane_disable(struct drm_plane *plane)
                return 0;
 
        dcrtc = drm_to_armada_crtc(dplane->base.base.crtc);
-       dcrtc->plane = NULL;
 
-       armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update);
+       armada_drm_plane_work_cancel(dcrtc, &dplane->base);
+       armada_drm_crtc_plane_disable(dcrtc, plane);
 
+       dcrtc->plane = NULL;
        dplane->ctrl0 = 0;
 
-       armada_drm_crtc_plane_disable(dcrtc, plane);
-
        fb = xchg(&dplane->old_fb, NULL);
        if (fb)
                drm_framebuffer_unreference(fb);
@@ -456,8 +454,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
                return ret;
        }
 
-       armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl,
-                                 dplane);
+       dplane->vbl.work.fn = armada_ovl_plane_work;
 
        ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs,
                                       &armada_ovl_plane_funcs,