drm/exynos/decon5433: handle vblank in vblank interrupt
authorAndrzej Hajda <a.hajda@samsung.com>
Wed, 29 Jun 2016 08:00:02 +0000 (10:00 +0200)
committerInki Dae <inki.dae@samsung.com>
Fri, 8 Jul 2016 09:39:33 +0000 (18:39 +0900)
vblank should be signaled to userspace as soon as possible after sending
frame. INTFRMDONEPEND irq looks to be the best moment.
Handling it in TE interrupt looks wrong - TE triggers reading framebuffers
so it is the worst moment, it could result in delayed frame update.
Other benefit of moving vblank handiling to vblank interrupt is possibility
to eliminate TE irq handler in case of HWTRIGGER.

Change-Id: I1f9b1830c3328a935d05fc9d859c9baf4df33533
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
drivers/gpu/drm/exynos/exynos5433_drm_decon.c

index 3709556b3a42a308e6aef75badd9f31b5f0ce3a6..873481e4a5abed0b104a75304aada1d24da17878 100644 (file)
@@ -600,29 +600,13 @@ void decon_te_irq_handler(struct exynos_drm_crtc *crtc)
 {
        struct decon_context *ctx = crtc->ctx;
        enum exynos_drm_trigger_type trg_type = ctx->drv_data->trg_type;
-       u32 val;
 
-       if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
+       if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled) ||
+           (trg_type == EXYNOS_DISPLAY_HW_TRIGGER))
                return;
 
-       if (trg_type == EXYNOS_DISPLAY_HW_TRIGGER)
-               goto out;
-
-       if (atomic_add_unless(&ctx->win_updated, -1, 0)) {
-               /* trigger */
-               val = readl(ctx->addr + DECON_TRIGCON);
-               val |= TRIGCON_SWTRIGCMD;
-               writel(val, ctx->addr + DECON_TRIGCON);
-       }
-
-out:
-       /* Wakes up vsync event queue */
-       if (atomic_read(&ctx->wait_vsync_event)) {
-               atomic_set(&ctx->wait_vsync_event, 0);
-               wake_up(&ctx->wait_vsync_queue);
-       }
-
-       drm_handle_vblank(ctx->drm_dev, ctx->pipe);
+       if (atomic_add_unless(&ctx->win_updated, -1, 0))
+               decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0);
 }
 
 static struct exynos_drm_crtc_ops decon_crtc_ops = {
@@ -783,14 +767,17 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, void *dev_id)
 
        val = readl(ctx->addr + DECON_VIDINTCON1);
        if (val & VIDINTCON1_INTFRMDONEPEND) {
+               drm_handle_vblank(ctx->drm_dev, ctx->pipe);
                exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
-
-               /* clear */
-               writel(VIDINTCON1_INTFRMDONEPEND,
-                               ctx->addr + DECON_VIDINTCON1);
+               writel(VIDINTCON1_INTFRMDONEPEND, ctx->addr + DECON_VIDINTCON1);
        }
 
 out:
+       if (atomic_read(&ctx->wait_vsync_event)) {
+               atomic_set(&ctx->wait_vsync_event, 0);
+               wake_up(&ctx->wait_vsync_queue);
+       }
+
        return IRQ_HANDLED;
 }