<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Apr 29, 2014 at 9:38 AM, Inki Dae <span dir="ltr"><<a href="mailto:inki.dae@samsung.com" target="_blank">inki.dae@samsung.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">From: Akshu Agrawal <<a href="mailto:akshu.a@samsung.com">akshu.a@samsung.com</a>><br>


<br>
If any fimd channel was already active, initializing iommu will result<br>
in a PAGE FAULT (e.e. u-boot could have turned on the display and<br>
not disabled it before the kernel starts). This patch checks if any<br>
channel is active before initializing iommu and disables it.<br>
<br>
Changelog v2:<br>
- consider SoC without SHADOWCON register<br>
<br>
Signed-off-by: Akshu Agrawal <<a href="mailto:akshu.a@samsung.com">akshu.a@samsung.com</a>><br>
Signed-off-by: Prathyush K <<a href="mailto:prathyush.k@samsung.com">prathyush.k@samsung.com</a>><br>
Signed-off-by: Inki Dae <<a href="mailto:inki.dae@samsung.com">inki.dae@samsung.com</a>><br>
---<br>
 drivers/gpu/drm/exynos/exynos_drm_fimd.c |   70 +++++++++++++++++++++---------<br>
 1 file changed, 50 insertions(+), 20 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c<br>
index 40fd6cc..ef21ce4 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c<br>
@@ -143,6 +143,48 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(<br>
        return (struct fimd_driver_data *)of_id->data;<br>
 }<br>
<br>
+static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)<br>
+{<br>
+       struct fimd_context *ctx = mgr->ctx;<br>
+<br>
+       if (ctx->suspended)<br>
+               return;<br>
+<br></blockquote><div><br></div><div>Hi Inki,</div><div><br></div><div>I think you need this to guarantee that the irq is actually enabled:</div><div><br></div><div><div><span class="" style="white-space:pre">      </span>drm_vblank_get(ctx->drm_dev, ctx->pipe);</div>

</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+       atomic_set(&ctx->wait_vsync_event, 1);<br>
+<br>
+       /*<br>
+        * wait for FIMD to signal VSYNC interrupt or return after<br>
+        * timeout which is set to 50ms (refresh rate of 20).<br>
+        */<br>
+       if (!wait_event_timeout(ctx->wait_vsync_queue,<br>
+                               !atomic_read(&ctx->wait_vsync_event),<br>
+                               HZ/20))<br>
+               DRM_DEBUG_KMS("vblank wait timed out.\n");<br>
</blockquote><div><br></div><div><span class="" style="white-space:pre">        </span>drm_vblank_put(ctx->drm_dev, ctx->pipe);</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

+}<br>
+<br>
+<br>
+static void fimd_clear_channel(struct exynos_drm_manager *mgr)<br>
+{<br>
+       struct fimd_context *ctx = mgr->ctx;<br>
+       int win, ch_enabled = 0;<br>
+<br>
+       DRM_DEBUG_KMS("%s\n", __FILE__);<br>
+<br>
+       /* Check if any channel is enabled. */<br>
+       for (win = 0; win < WINDOWS_NR; win++) {<br>
+               u32 val = readl(ctx->regs + SHADOWCON);<br>
+               if (val & SHADOWCON_CHx_ENABLE(win)) {<br>
+                       val &= ~SHADOWCON_CHx_ENABLE(win);<br>
+                       writel(val, ctx->regs + SHADOWCON);<br>
+                       ch_enabled = 1;<br>
+               }<br>
+       }<br>
+<br>
+       /* Wait for vsync, as disable channel takes effect at next vsync */<br>
+       if (ch_enabled)<br>
+               fimd_wait_for_vblank(mgr);<br>
+}<br>
+<br>
 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,<br>
                        struct drm_device *drm_dev, int pipe)<br>
 {<br>
@@ -169,8 +211,15 @@ static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,<br>
        drm_dev->vblank_disable_allowed = true;<br>
<br>
        /* attach this sub driver to iommu mapping if supported. */<br>
-       if (is_drm_iommu_supported(ctx->drm_dev))<br>
+       if (is_drm_iommu_supported(ctx->drm_dev)) {<br>
+               /*<br>
+                * If any channel is already active, iommu will throw<br>
+                * a PAGE FAULT when enabled. So clear any channel if enabled.<br>
+                */<br>
+               if (ctx->driver_data->has_shadowcon)<br>
+                       fimd_clear_channel(mgr);<br></blockquote><div><br></div><div>We already disable all overlays at the end of fimd_probe() by calling fimd_clear_win().<br></div><div>Perhaps all that was missing was just waiting until the next vblank to ensure that these clears have all completed?</div>

<div><br></div><div>Best Regards,</div><div>-Daniel</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


                drm_iommu_attach_device(ctx->drm_dev, ctx->dev);<br>
+       }<br>
<br>
        return 0;<br>
 }<br>
@@ -324,25 +373,6 @@ static void fimd_disable_vblank(struct exynos_drm_manager *mgr)<br>
        }<br>
 }<br>
<br>
-static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)<br>
-{<br>
-       struct fimd_context *ctx = mgr->ctx;<br>
-<br>
-       if (ctx->suspended)<br>
-               return;<br>
-<br>
-       atomic_set(&ctx->wait_vsync_event, 1);<br>
-<br>
-       /*<br>
-        * wait for FIMD to signal VSYNC interrupt or return after<br>
-        * timeout which is set to 50ms (refresh rate of 20).<br>
-        */<br>
-       if (!wait_event_timeout(ctx->wait_vsync_queue,<br>
-                               !atomic_read(&ctx->wait_vsync_event),<br>
-                               HZ/20))<br>
-               DRM_DEBUG_KMS("vblank wait timed out.\n");<br>
-}<br>
-<br>
 static void fimd_win_mode_set(struct exynos_drm_manager *mgr,<br>
                        struct exynos_drm_overlay *overlay)<br>
 {<br>
<span class=""><font color="#888888">--<br>
1.7.9.5<br>
<br>
_______________________________________________<br>
dri-devel mailing list<br>
<a href="mailto:dri-devel@lists.freedesktop.org">dri-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/dri-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br>
</font></span></blockquote></div><br></div></div>