Message ID | 1440038007-32192-2-git-send-email-human.hwang@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 2015? 08? 20? 11:33, Hyungwon Hwang wrote: > 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. Hyungwon, Gustavo already posted atomic_begin/flush support. However, he didn't consider decon drivers. Can you post only atomic_begin/flush support for decon drivers? Thanks, Inki Dae > > Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com> > --- > 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) >
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)
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@samsung.com> --- 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(-)