From: Andrzej Hajda Date: Wed, 29 Jun 2016 08:00:02 +0000 (+0200) Subject: drm/exynos/decon5433: handle vblank in vblank interrupt X-Git-Tag: submit/tizen/20160810.050017~59 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=439fb03b4fdba14b00168c6fc259cfc47fe4cb99;p=platform%2Fkernel%2Flinux-exynos.git drm/exynos/decon5433: handle vblank in vblank interrupt 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 --- diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 3709556b3a42..873481e4a5ab 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -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; }