From: Gustavo Padovan <gustavo.pado...@collabora.co.uk>

The current code was ignoring the end of update for all overlay planes,
caring only for the primary plane update in case of pageflip.

This change adds a change to start to check for pending updates for all
planes through exynos_plane->pending_fb. At the start of plane update the
pending_fb is set with the fb to be shown on the screen. Then only when to
fb is already presented in the screen we set pending_fb to NULL to
signal that the update was finished.

Signed-off-by: Gustavo Padovan <gustavo.pado...@collabora.co.uk>

fixup! drm/exynos: check for pending fb before finish update
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 10 +++++++++-
 drivers/gpu/drm/exynos/exynos7_drm_decon.c    | 10 +++++++++-
 drivers/gpu/drm/exynos/exynos_drm_crtc.c      |  7 ++++---
 drivers/gpu/drm/exynos/exynos_drm_crtc.h      |  3 ++-
 drivers/gpu/drm/exynos/exynos_drm_drv.h       |  1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c      | 10 +++++++++-
 drivers/gpu/drm/exynos/exynos_drm_plane.c     |  2 ++
 drivers/gpu/drm/exynos/exynos_drm_vidi.c      | 10 +++++++++-
 drivers/gpu/drm/exynos/exynos_mixer.c         | 10 +++++++++-
 9 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 484e312..8d65e45 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -542,13 +542,21 @@ static irqreturn_t decon_lcd_sys_irq_handler(int irq, 
void *dev_id)
 {
        struct decon_context *ctx = dev_id;
        u32 val;
+       int win;
 
        if (!test_bit(BIT_CLKS_ENABLED, &ctx->enabled))
                goto out;
 
        val = readl(ctx->addr + DECON_VIDINTCON1);
        if (val & VIDINTCON1_INTFRMDONEPEND) {
-               exynos_drm_crtc_finish_pageflip(ctx->crtc);
+               for (win = 0 ; win < WINDOWS_NR ; win++) {
+                       struct exynos_drm_plane *plane = &ctx->planes[win];
+
+                       if (!plane->pending_fb)
+                               continue;
+
+                       exynos_drm_crtc_finish_update(ctx->crtc, plane);
+               }
 
                /* clear */
                writel(VIDINTCON1_INTFRMDONEPEND,
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 0792654..7651499 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -623,6 +623,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
 {
        struct decon_context *ctx = (struct decon_context *)dev_id;
        u32 val, clear_bit;
+       int win;
 
        val = readl(ctx->regs + VIDINTCON1);
 
@@ -636,7 +637,14 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)
 
        if (!ctx->i80_if) {
                drm_crtc_handle_vblank(&ctx->crtc->base);
-               exynos_drm_crtc_finish_pageflip(ctx->crtc);
+               for (win = 0 ; win < WINDOWS_NR ; win++) {
+                       struct exynos_drm_plane *plane = &ctx->planes[win];
+
+                       if (!plane->pending_fb)
+                               continue;
+
+                       exynos_drm_crtc_finish_update(ctx->crtc, plane);
+               }
 
                /* set wait vsync event to zero and wake up queue. */
                if (atomic_read(&ctx->wait_vsync_event)) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c 
b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 54485b7..582e041 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -197,18 +197,19 @@ void exynos_drm_crtc_disable_vblank(struct drm_device 
*dev, int pipe)
                exynos_crtc->ops->disable_vblank(exynos_crtc);
 }
 
-void exynos_drm_crtc_finish_pageflip(struct exynos_drm_crtc *exynos_crtc)
+void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
+                               struct exynos_drm_plane *exynos_plane)
 {
        struct drm_crtc *crtc = &exynos_crtc->base;
        unsigned long flags;
 
+       exynos_plane->pending_fb = NULL;
+
        spin_lock_irqsave(&crtc->dev->event_lock, flags);
        if (exynos_crtc->event) {
-
                drm_crtc_send_vblank_event(crtc, exynos_crtc->event);
                drm_crtc_vblank_put(crtc);
                wake_up(&exynos_crtc->pending_flip_queue);
-
        }
 
        exynos_crtc->event = NULL;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h 
b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 9e7027d..8bedfde 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -25,7 +25,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct 
drm_device *drm_dev,
                                        void *context);
 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
-void exynos_drm_crtc_finish_pageflip(struct exynos_drm_crtc *exynos_crtc);
+void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
+                                  struct exynos_drm_plane *exynos_plane);
 void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
 
 /* This function gets pipe value to crtc device matched with out_type. */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 28afecc..8116803 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -74,6 +74,7 @@ struct exynos_drm_plane {
        unsigned int v_ratio;
        dma_addr_t dma_addr[MAX_FB_BUFFER];
        unsigned int zpos;
+       struct drm_framebuffer *pending_fb;
 };
 
 /*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 005a996..fc26c3e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -896,6 +896,7 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
 {
        struct fimd_context *ctx = (struct fimd_context *)dev_id;
        u32 val, clear_bit;
+       int win;
 
        val = readl(ctx->regs + VIDINTCON1);
 
@@ -910,7 +911,14 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
        if (!ctx->i80_if)
                drm_crtc_handle_vblank(&ctx->crtc->base);
 
-       exynos_drm_crtc_finish_pageflip(ctx->crtc);
+       for (win = 0 ; win < WINDOWS_NR ; win++) {
+               struct exynos_drm_plane *plane = &ctx->planes[win];
+
+               if (!plane->pending_fb)
+                       continue;
+
+               exynos_drm_crtc_finish_update(ctx->crtc, plane);
+       }
 
        if (ctx->i80_if) {
                /* Exits triggering mode */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c 
b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index d9a68fd..fad7dfc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -168,6 +168,8 @@ static void exynos_plane_atomic_update(struct drm_plane 
*plane,
                              state->src_x >> 16, state->src_y >> 16,
                              state->src_w >> 16, state->src_h >> 16);
 
+       exynos_plane->pending_fb = state->fb;
+
        if (exynos_crtc->ops->update_plane)
                exynos_crtc->ops->update_plane(exynos_crtc, exynos_plane);
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c 
b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 581af35..b6d00dd 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -179,6 +179,7 @@ static void vidi_fake_vblank_handler(struct work_struct 
*work)
 {
        struct vidi_context *ctx = container_of(work, struct vidi_context,
                                        work);
+       int win;
 
        if (ctx->pipe < 0)
                return;
@@ -197,7 +198,14 @@ static void vidi_fake_vblank_handler(struct work_struct 
*work)
 
        mutex_unlock(&ctx->lock);
 
-       exynos_drm_crtc_finish_pageflip(ctx->crtc);
+       for (win = 0 ; win < WINDOWS_NR ; win++) {
+               struct exynos_drm_plane *plane = &ctx->planes[win];
+
+               if (!plane->pending_fb)
+                       continue;
+
+               exynos_drm_crtc_finish_update(ctx->crtc, plane);
+       }
 }
 
 static int vidi_show_connection(struct device *dev,
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c 
b/drivers/gpu/drm/exynos/exynos_mixer.c
index e68340c..d7e7811 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -716,6 +716,7 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
        struct mixer_context *ctx = arg;
        struct mixer_resources *res = &ctx->mixer_res;
        u32 val, base, shadow;
+       int win;
 
        spin_lock(&res->reg_slock);
 
@@ -742,7 +743,14 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
                }
 
                drm_crtc_handle_vblank(&ctx->crtc->base);
-               exynos_drm_crtc_finish_pageflip(ctx->crtc);
+               for (win = 0 ; win < MIXER_WIN_NR ; win++) {
+                       struct exynos_drm_plane *plane = &ctx->planes[win];
+
+                       if (!plane->pending_fb)
+                               continue;
+
+                       exynos_drm_crtc_finish_update(ctx->crtc, plane);
+               }
 
                /* set wait vsync event to zero and wake up queue. */
                if (atomic_read(&ctx->wait_vsync_event)) {
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to