From: Sean Paul <seanp...@chromium.org>

We should not finish a pageflip or set wait_for_vblank to zero
if a layer update is pending. This might result in a page fault or corruption
on screen. This patch adds a check in the irq handler to exit if a layer
update is pending. Also, calls layer_update only once per layer per vsync.

Signed-off-by: Sean Paul <seanp...@chromium.org>
Signed-off-by: Prathyush K <prathyus...@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_mixer.c | 35 ++++++++++++++++++++++++++++++-----
 drivers/gpu/drm/exynos/regs-mixer.h   |  1 +
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c 
b/drivers/gpu/drm/exynos/exynos_mixer.c
index 2506567..3369d57 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -58,6 +58,7 @@ struct hdmi_win_data {
        unsigned int            mode_width;
        unsigned int            mode_height;
        unsigned int            scan_flags;
+       bool                    updated;
        bool                    enabled;
        bool                    resume;
 };
@@ -486,16 +487,21 @@ static void vp_video_buffer(struct mixer_context *ctx, 
int win)
        vp_regs_dump(ctx);
 }
 
-static void mixer_layer_update(struct mixer_context *ctx)
+static int mixer_get_layer_update_count(struct mixer_context *ctx)
 {
        struct mixer_resources *res = &ctx->mixer_res;
        u32 val;
 
        val = mixer_reg_read(res, MXR_CFG);
 
-       /* allow one update per vsync only */
-       if (!(val & MXR_CFG_LAYER_UPDATE_COUNT_MASK))
-               mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
+       return (val & MXR_CFG_LAYER_UPDATE_COUNT_MASK) >>
+                       MXR_CFG_LAYER_UPDATE_COUNT0;
+}
+
+static void mixer_layer_update(struct mixer_context *ctx)
+{
+       struct mixer_resources *res = &ctx->mixer_res;
+       mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE);
 }
 
 static void mixer_graph_buffer(struct mixer_context *ctx, int win)
@@ -547,6 +553,11 @@ static void mixer_graph_buffer(struct mixer_context *ctx, 
int win)
                ctx->interlace = false;
 
        spin_lock_irqsave(&res->reg_slock, flags);
+
+       /* Only allow one update per vsync */
+       if (ctx->mxr_ver == MXR_VER_16_0_33_0 && win_data->updated)
+               goto end;
+
        mixer_vsync_set_update(ctx, false);
 
        /* setup format */
@@ -580,12 +591,15 @@ static void mixer_graph_buffer(struct mixer_context *ctx, 
int win)
        mixer_cfg_layer(ctx, win, true);
 
        /* layer update mandatory for mixer 16.0.33.0 */
-       if (ctx->mxr_ver == MXR_VER_16_0_33_0)
+       if (ctx->mxr_ver == MXR_VER_16_0_33_0) {
                mixer_layer_update(ctx);
+               win_data->updated = true;
+       }
 
        mixer_run(ctx);
 
        mixer_vsync_set_update(ctx, true);
+end:
        spin_unlock_irqrestore(&res->reg_slock, flags);
 }
 
@@ -1000,6 +1014,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
        struct mixer_context *ctx = drm_hdmi_ctx->ctx;
        struct mixer_resources *res = &ctx->mixer_res;
        u32 val, base, shadow;
+       int i;
 
        spin_lock(&res->reg_slock);
 
@@ -1022,6 +1037,16 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
                }
 
                drm_handle_vblank(drm_hdmi_ctx->drm_dev, ctx->pipe);
+
+               if (ctx->mxr_ver == MXR_VER_16_0_33_0) {
+                       /* Bail out if a layer update is pending */
+                       if (mixer_get_layer_update_count(ctx))
+                               goto out;
+
+                       for (i = 0; i < MIXER_WIN_NR; i++)
+                               ctx->win_data[i].updated = false;
+               }
+
                mixer_finish_pageflip(drm_hdmi_ctx->drm_dev, ctx->pipe);
 
                /* set wait vsync event to zero and wake up queue. */
diff --git a/drivers/gpu/drm/exynos/regs-mixer.h 
b/drivers/gpu/drm/exynos/regs-mixer.h
index 5d8dbc0..bad2b99 100644
--- a/drivers/gpu/drm/exynos/regs-mixer.h
+++ b/drivers/gpu/drm/exynos/regs-mixer.h
@@ -79,6 +79,7 @@
 
 /* bits for MXR_CFG */
 #define MXR_CFG_LAYER_UPDATE           (1 << 31)
+#define MXR_CFG_LAYER_UPDATE_COUNT0    29
 #define MXR_CFG_LAYER_UPDATE_COUNT_MASK (3 << 29)
 #define MXR_CFG_RGB601_0_255           (0 << 9)
 #define MXR_CFG_RGB601_16_235          (1 << 9)
-- 
1.8.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to