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);
elseval |= win_bits;
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;
elseval |= win_bits;
val &= ~bits;
writel(val, ctx->regs + SHADOWCON);val &= ~win_bits;
}
@@ -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;
} else { reg = PRTCON;bits = SHADOWCON_WINx_PROTECT(win);
bits = PRTCON_PROTECT;
win_bits = PRTCON_PROTECT;
}
val = readl(ctx->regs + reg); if (protect)
val |= bits;
elseval |= win_bits;
val &= ~bits;
writel(val, ctx->regs + reg);val &= ~win_bits;
}
@@ -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)