Each CRTC's atomic_{begin/flush} must stop/start the update of shadow registers to active register in the functions. This patch achieves these purpose by moving the setting of protection bits to those functions from {fimd/decon}_update_plane. Signed-off-by: Hyungwon Hwang <human.hwang@xxxxxxxxxxx> --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 47 +++++++++++++++++------- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 47 ++++++++++++++++-------- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 51 ++++++++++++++++++--------- 3 files changed, 103 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 484e312..fef0333 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -31,6 +31,7 @@ struct decon_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; + unsigned int updated_plane; void __iomem *addr; struct clk *clks[6]; unsigned int default_win; @@ -204,17 +205,17 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, writel(val, ctx->addr + DECON_WINCONx(win)); } -static void decon_shadow_protect_win(struct decon_context *ctx, int win, - bool protect) +static void decon_shadow_protect_win(struct decon_context *ctx, + unsigned int win_bits, bool protect) { u32 val; val = readl(ctx->addr + DECON_SHADOWCON); if (protect) - val |= SHADOWCON_Wx_PROTECT(win); + val |= win_bits; else - val &= ~SHADOWCON_Wx_PROTECT(win); + val &= ~win_bits; writel(val, ctx->addr + DECON_SHADOWCON); } @@ -232,8 +233,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, if (ctx->suspended) return; - decon_shadow_protect_win(ctx, win, true); - val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y); writel(val, ctx->addr + DECON_VIDOSDxA(win)); @@ -265,15 +264,12 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, val |= WINCONx_ENWIN_F; writel(val, ctx->addr + DECON_WINCONx(win)); - decon_shadow_protect_win(ctx, win, false); - /* standalone update */ val = readl(ctx->addr + DECON_UPDATE); val |= STANDALONE_UPDATE_F; writel(val, ctx->addr + DECON_UPDATE); - if (ctx->i80_if) - atomic_set(&ctx->win_updated, 1); + ctx->updated_plane |= SHADOWCON_Wx_PROTECT(win); } static void decon_disable_plane(struct exynos_drm_crtc *crtc, @@ -286,14 +282,14 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, if (ctx->suspended) return; - decon_shadow_protect_win(ctx, win, true); + decon_shadow_protect_win(ctx, SHADOWCON_Wx_PROTECT(win), true); /* window disable */ val = readl(ctx->addr + DECON_WINCONx(win)); val &= ~WINCONx_ENWIN_F; writel(val, ctx->addr + DECON_WINCONx(win)); - decon_shadow_protect_win(ctx, win, false); + decon_shadow_protect_win(ctx, SHADOWCON_Wx_PROTECT(win), false); /* standalone update */ val = readl(ctx->addr + DECON_UPDATE); @@ -405,6 +401,31 @@ void decon_te_irq_handler(struct exynos_drm_crtc *crtc) drm_crtc_handle_vblank(&ctx->crtc->base); } +static void decon_begin(struct exynos_drm_crtc *crtc) +{ + struct decon_context *ctx = crtc->ctx; + int i; + unsigned int val = 0; + + for (i = 0; i < WINDOWS_NR; i++) + val |= SHADOWCON_Wx_PROTECT(i); + + /* protect windows */ + decon_shadow_protect_win(ctx, val, true); +} + +static void decon_flush(struct exynos_drm_crtc *crtc) +{ + struct decon_context *ctx = crtc->ctx; + + if (ctx->updated_plane) { + decon_shadow_protect_win(ctx, ctx->updated_plane, false); + + if (ctx->i80_if) + atomic_set(&ctx->win_updated, 1); + } +} + static void decon_clear_channels(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; @@ -458,6 +479,8 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = { .update_plane = decon_update_plane, .disable_plane = decon_disable_plane, .te_handler = decon_te_irq_handler, + .atomic_begin = decon_begin, + .atomic_flush = decon_flush, }; static int decon_bind(struct device *dev, struct device *master, void *data) diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 0792654..c81de86 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -47,6 +47,7 @@ struct decon_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; + unsigned int updated_plane; struct clk *pclk; struct clk *aclk; struct clk *eclk; @@ -369,17 +370,15 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win) * @protect: 1 to protect (disable updates) */ static void decon_shadow_protect_win(struct decon_context *ctx, - unsigned int win, bool protect) + unsigned int win_bits, bool protect) { - u32 bits, val; - - bits = SHADOWCON_WINx_PROTECT(win); + u32 val; val = readl(ctx->regs + SHADOWCON); if (protect) - val |= bits; + val |= win_bits; else - val &= ~bits; + val &= ~win_bits; writel(val, ctx->regs + SHADOWCON); } @@ -410,9 +409,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, * is set. */ - /* protect windows */ - decon_shadow_protect_win(ctx, win, true); - /* buffer start address */ val = (unsigned long)plane->dma_addr[0]; writel(val, ctx->regs + VIDW_BUF_START(win)); @@ -484,12 +480,11 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, val |= WINCONx_ENWIN; writel(val, ctx->regs + WINCON(win)); - /* Enable DMA channel and unprotect windows */ - decon_shadow_protect_win(ctx, win, false); - val = readl(ctx->regs + DECON_UPDATE); val |= DECON_UPDATE_STANDALONE_F; writel(val, ctx->regs + DECON_UPDATE); + + ctx->updated_plane |= SHADOWCON_WINx_PROTECT(win); } static void decon_disable_plane(struct exynos_drm_crtc *crtc, @@ -503,7 +498,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, return; /* protect windows */ - decon_shadow_protect_win(ctx, win, true); + decon_shadow_protect_win(ctx, SHADOWCON_WINx_PROTECT(win), true); /* wincon */ val = readl(ctx->regs + WINCON(win)); @@ -511,7 +506,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->regs + WINCON(win)); /* unprotect windows */ - decon_shadow_protect_win(ctx, win, false); + decon_shadow_protect_win(ctx, SHADOWCON_WINx_PROTECT(win), false); val = readl(ctx->regs + DECON_UPDATE); val |= DECON_UPDATE_STANDALONE_F; @@ -606,6 +601,28 @@ static void decon_disable(struct exynos_drm_crtc *crtc) ctx->suspended = true; } +static void decon_begin(struct exynos_drm_crtc *crtc) +{ + struct decon_context *ctx = crtc->ctx; + int i; + unsigned int val = 0; + + for (i = 0; i < WINDOWS_NR; i++) + val |= SHADOWCON_WINx_PROTECT(i); + + /* protect windows */ + decon_shadow_protect_win(ctx, val, true); +} + +static void decon_flush(struct exynos_drm_crtc *crtc) +{ + struct decon_context *ctx = crtc->ctx; + + if (ctx->updated_plane) + decon_shadow_protect_win(ctx, ctx->updated_plane, false); +} + + static const struct exynos_drm_crtc_ops decon_crtc_ops = { .enable = decon_enable, .disable = decon_disable, @@ -616,6 +633,8 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = { .wait_for_vblank = decon_wait_for_vblank, .update_plane = decon_update_plane, .disable_plane = decon_disable_plane, + .atomic_begin = decon_begin, + .atomic_flush = decon_flush, }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 5def6bc..0b41bb2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -149,6 +149,7 @@ struct fimd_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; + unsigned int updated_plane; struct clk *bus_clk; struct clk *lcd_clk; void __iomem *regs; @@ -587,23 +588,22 @@ static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win) * @protect: 1 to protect (disable updates) */ static void fimd_shadow_protect_win(struct fimd_context *ctx, - unsigned int win, bool protect) + unsigned int win_bits, bool protect) { - u32 reg, bits, val; + u32 reg, val; if (ctx->driver_data->has_shadowcon) { reg = SHADOWCON; - bits = SHADOWCON_WINx_PROTECT(win); } else { reg = PRTCON; - bits = PRTCON_PROTECT; + win_bits = PRTCON_PROTECT; } val = readl(ctx->regs + reg); if (protect) - val |= bits; + val |= win_bits; else - val &= ~bits; + val &= ~win_bits; writel(val, ctx->regs + reg); } @@ -632,10 +632,6 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, * is set. */ - /* protect windows */ - fimd_shadow_protect_win(ctx, win, true); - - offset = plane->src_x * bpp; offset += plane->src_y * pitch; @@ -707,11 +703,32 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, if (ctx->driver_data->has_shadowcon) fimd_enable_shadow_channel_path(ctx, win, true); - /* Enable DMA channel and unprotect windows */ - fimd_shadow_protect_win(ctx, win, false); + ctx->updated_plane |= SHADOWCON_WINx_PROTECT(win); +} + +static void fimd_begin(struct exynos_drm_crtc *crtc) +{ + struct fimd_context *ctx = crtc->ctx; + int i; + unsigned int val = 0; + + for (i = 0; i < WINDOWS_NR; i++) + val |= SHADOWCON_WINx_PROTECT(i); - if (ctx->i80_if) - atomic_set(&ctx->win_updated, 1); + /* protect windows */ + fimd_shadow_protect_win(ctx, val, true); +} + +static void fimd_flush(struct exynos_drm_crtc *crtc) +{ + struct fimd_context *ctx = crtc->ctx; + + if (ctx->updated_plane) { + fimd_shadow_protect_win(ctx, ctx->updated_plane, false); + + if (ctx->i80_if) + atomic_set(&ctx->win_updated, 1); + } } static void fimd_disable_plane(struct exynos_drm_crtc *crtc, @@ -724,7 +741,7 @@ static void fimd_disable_plane(struct exynos_drm_crtc *crtc, return; /* protect windows */ - fimd_shadow_protect_win(ctx, win, true); + fimd_shadow_protect_win(ctx, SHADOWCON_WINx_PROTECT(win), true); fimd_enable_video_output(ctx, win, false); @@ -732,7 +749,7 @@ static void fimd_disable_plane(struct exynos_drm_crtc *crtc, fimd_enable_shadow_channel_path(ctx, win, false); /* unprotect windows */ - fimd_shadow_protect_win(ctx, win, false); + fimd_shadow_protect_win(ctx, SHADOWCON_WINx_PROTECT(win), false); } static void fimd_enable(struct exynos_drm_crtc *crtc) @@ -879,6 +896,8 @@ static const struct exynos_drm_crtc_ops fimd_crtc_ops = { .disable_plane = fimd_disable_plane, .te_handler = fimd_te_handler, .clock_enable = fimd_dp_clock_enable, + .atomic_begin = fimd_begin, + .atomic_flush = fimd_flush, }; static irqreturn_t fimd_irq_handler(int irq, void *dev_id) -- 2.4.3 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel