The wait_for_vblank interface is modified to the complete_scanout
function in fimd. This patch adds the fimd_complete_scanout function

Inside fimd_complete_scanout, we read the shadow register for each
window and compare it with the dma address of the framebuffer. If
the dma_address is in the shadow register, then the function waits
for the next vblank and returns.

Signed-off-by: Prathyush K <prathyush.k at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 32 +++++++++++++++++++++++++++++++-
 include/video/samsung_fimd.h             |  1 +
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 3aeedf5..190ffde9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -46,6 +46,7 @@
 #define VIDOSD_D(win)          (VIDOSD_BASE + 0x0C + (win) * 16)

 #define VIDWx_BUF_START(win, buf)      (VIDW_BUF_START(buf) + (win) * 8)
+#define VIDWx_BUF_START_S(win, buf)    (VIDW_BUF_START_S(buf) + (win) * 8)
 #define VIDWx_BUF_END(win, buf)                (VIDW_BUF_END(buf) + (win) * 8)
 #define VIDWx_BUF_SIZE(win, buf)       (VIDW_BUF_SIZE(buf) + (win) * 4)

@@ -363,13 +364,42 @@ static void fimd_wait_for_vblank(struct device *dev)
                fimd_disable_vblank(dev);
 }

+static void fimd_complete_scanout(struct device *dev, dma_addr_t dma_addr,
+                                       unsigned long size)
+{
+       struct fimd_context *ctx = get_fimd_context(dev);
+       int win;
+       bool in_use = false;
+
+       if (ctx->suspended)
+               return;
+
+       for (win = 0; win < WINDOWS_NR; win++) {
+               dma_addr_t dma_addr_in_use;
+
+               if (!ctx->win_data[win].enabled)
+                       continue;
+
+               dma_addr_in_use = readl(ctx->regs + VIDWx_BUF_START_S(win, 0));
+               if (dma_addr_in_use >= dma_addr &&
+                       dma_addr_in_use < (dma_addr + size)) {
+                               in_use = true;
+                               break;
+               }
+       }
+
+       if (in_use)
+               fimd_wait_for_vblank(dev);
+       return;
+}
+
 static struct exynos_drm_manager_ops fimd_manager_ops = {
        .dpms = fimd_dpms,
        .apply = fimd_apply,
        .commit = fimd_commit,
        .enable_vblank = fimd_enable_vblank,
        .disable_vblank = fimd_disable_vblank,
-       .wait_for_vblank = fimd_wait_for_vblank,
+       .complete_scanout = fimd_complete_scanout,
 };

 static void fimd_win_mode_set(struct device *dev,
diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
index 7ae6c07..382eaec 100644
--- a/include/video/samsung_fimd.h
+++ b/include/video/samsung_fimd.h
@@ -274,6 +274,7 @@

 /* Video buffer addresses */
 #define VIDW_BUF_START(_buff)                  (0xA0 + ((_buff) * 8))
+#define VIDW_BUF_START_S(_buff)                        (0x40A0 + ((_buff) * 8))
 #define VIDW_BUF_START1(_buff)                 (0xA4 + ((_buff) * 8))
 #define VIDW_BUF_END(_buff)                    (0xD0 + ((_buff) * 8))
 #define VIDW_BUF_END1(_buff)                   (0xD4 + ((_buff) * 8))
-- 
1.8.0

Reply via email to