<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>