drm/exynos: check for pending fb before finish update
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>
Sat, 15 Aug 2015 16:26:14 +0000 (13:26 -0300)
committerInki Dae <daeinki@gmail.com>
Sun, 30 Aug 2015 15:27:37 +0000 (00:27 +0900)
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.padovan@collabora.co.uk>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
fixup! drm/exynos: check for pending fb before finish update

drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_mixer.c

index 484e312e0a22d58908ca1cf3a2183d7f7ce35467..8d65e45156bd09d68f2765ad0b3ff14159e9920e 100644 (file)
@@ -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,
index 07926547c94ff733090db523a2cb0be2ffa7e150..7651499aa5acf66023b2528c69db00135b6ee9c9 100644 (file)
@@ -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)) {
index 54485b76df49170da2fce12a14ccde2e98ba2ccc..582e041a9356a73e2b647fb3d6eec398a783c8e1 100644 (file)
@@ -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;
index 9e7027d6c2f6de7a2b58bd5852165063c6625547..8bedfde2084a9989757e661a584ff6be30ef3cc0 100644 (file)
@@ -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. */
index 28afecc3aefa8b005549d1cd07eb7b6141755474..81168034ce878078d4553f6058c017f34fadcca9 100644 (file)
@@ -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;
 };
 
 /*
index 005a9968af5cd405b63e7c5689bc36c5d405255c..fc26c3ef95bf643b8a6a2ac586471e9ee0989349 100644 (file)
@@ -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 */
index d9a68fd83120a5e35164fa5e5df5c03badfed7b5..fad7dfc7a7786c1588d3658eda50e1582997a3c2 100644 (file)
@@ -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);
 }
index 581af35861a6fcd5781cf207d5c1a821c0583d0d..b6d00ddb6dd6bff7b5d2b271b24dbbeae073c831 100644 (file)
@@ -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,
index e68340c77676f3f0a8f56f07467b7558d37f56f5..d7e781153cff32c609827db3d8855c8378b2c7c5 100644 (file)
@@ -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)) {