<br><br><div class="gmail_quote">2012/12/6 Prathyush K <span dir="ltr"><<a href="mailto:prathyush.k@samsung.com" target="_blank">prathyush.k@samsung.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
When fimd is turned off, we disable the clocks which will stop<br>
the dma. Now if we remove the current framebuffer, we cannot<br>
disable the overlay but the current framebuffer will still be freed.<br>
When fimd resumes, the dma will continue from where it left off<br>
and will throw a PAGE FAULT since the memory was freed.<br>
<br>
This patch fixes the above problem by disabling the fimd windows<br>
before disabling the fimd clocks. It also keeps track of which<br>
windows were currently active by setting the 'resume' flag. When<br>
fimd resumes, the window with a resume flag set is enabled again.<br>
<br>
Now if a current fb is removed when fimd is off, fimd_win_disable<br>
will set the 'resume' flag of that window to zero and return.<br>
So when fimd resumes, that window will not be resumed.<br>
<br>
Signed-off-by: Prathyush K <<a href="mailto:prathyush.k@samsung.com">prathyush.k@samsung.com</a>><br>
---<br>
 drivers/gpu/drm/exynos/exynos_drm_fimd.c |   40 +++++++++++++++++++++++++++++-<br>
 1 files changed, 39 insertions(+), 1 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 1517d15..7e66032 100644<br>
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c<br>
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c<br>
@@ -83,6 +83,7 @@ struct fimd_win_data {<br>
        unsigned int            buf_offsize;<br>
        unsigned int            line_size;      /* bytes */<br>
        bool                    enabled;<br>
+       bool                    resume;<br>
 };<br>
<br>
 struct fimd_context {<br>
@@ -596,6 +597,12 @@ static void fimd_win_disable(struct device *dev, int zpos)<br>
<br>
        win_data = &ctx->win_data[win];<br>
 </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       if (ctx->suspended) {<br></blockquote><div><br>Ok, add the below comment,<br>"if disabling hw overlay is tried when fimd was disabled already then do not access the hardware."<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+               /* do not resume this window*/<br>
+               win_data->resume = false;<br>
+               return;<br>
+       }<br>
+<br>
        /* protect windows */<br>
        val = readl(ctx->regs + SHADOWCON);<br>
        val |= SHADOWCON_WINx_PROTECT(win);<br>
@@ -809,11 +816,38 @@ static int fimd_clock(struct fimd_context *ctx, bool enable)<br>
        return 0;<br>
 }<br>
<br>
+static void fimd_window_suspend(struct device *dev)<br>
+{<br>
+       struct fimd_context *ctx = get_fimd_context(dev);<br>
+       struct fimd_win_data *win_data;<br>
+       int i;<br>
+<br>
+       for (i = 0; i < WINDOWS_NR; i++) {<br>
+               win_data = &ctx->win_data[i];<br>
+               win_data->resume = win_data->enabled;<br>
+               fimd_win_disable(dev, i);<br>
+       }<br>
+       fimd_wait_for_vblank(dev);<br>
+}<br>
+<br>
+static void fimd_window_resume(struct device *dev)<br>
+{<br>
+       struct fimd_context *ctx = get_fimd_context(dev);<br>
+       struct fimd_win_data *win_data;<br>
+       int i;<br>
+<br>
+       for (i = 0; i < WINDOWS_NR; i++) {<br>
+               win_data = &ctx->win_data[i];<br>
+               win_data->enabled = win_data->resume;<br>
+               win_data->resume = false;<br></blockquote><div><br>shouldn't the below code be added?<br>fimd_win_enable(dev, i);<br><br>you backed up overlay status before suspended but this patch doesn't enable the overlays again. you supposed that the registers would be restored by SoC specific pm framework?<br>
<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       }<br>
+}<br>
+<br>
 static int fimd_activate(struct fimd_context *ctx, bool enable)<br>
 {<br>
+       struct device *dev = ctx->subdrv.dev;<br>
        if (enable) {<br>
                int ret;<br>
-               struct device *dev = ctx->subdrv.dev;<br>
<br>
                ret = fimd_clock(ctx, true);<br>
                if (ret < 0)<br>
@@ -824,7 +858,11 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)<br>
                /* if vblank was enabled status, enable it again. */<br>
                if (test_and_clear_bit(0, &ctx->irq_flags))<br>
                        fimd_enable_vblank(dev);<br>
+<br>
+               fimd_window_resume(dev);<br>
        } else {<br>
+               fimd_window_suspend(dev);<br>
+<br>
                fimd_clock(ctx, false);<br>
                ctx->suspended = true;<br>
        }<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.0.4<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>