[PATCH 7/7] drm/exynos: clear windows in fimd dpms off
Inki Dae
inki.dae at samsung.com
Thu Dec 6 20:42:00 PST 2012
2012/12/6 Prathyush K <prathyush.k at samsung.com>
> When fimd is turned off, we disable the clocks which will stop
> the dma. Now if we remove the current framebuffer, we cannot
> disable the overlay but the current framebuffer will still be freed.
> When fimd resumes, the dma will continue from where it left off
> and will throw a PAGE FAULT since the memory was freed.
>
> This patch fixes the above problem by disabling the fimd windows
> before disabling the fimd clocks. It also keeps track of which
> windows were currently active by setting the 'resume' flag. When
> fimd resumes, the window with a resume flag set is enabled again.
>
> Now if a current fb is removed when fimd is off, fimd_win_disable
> will set the 'resume' flag of that window to zero and return.
> So when fimd resumes, that window will not be resumed.
>
> Signed-off-by: Prathyush K <prathyush.k at samsung.com>
> ---
> drivers/gpu/drm/exynos/exynos_drm_fimd.c | 40
> +++++++++++++++++++++++++++++-
> 1 files changed, 39 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 1517d15..7e66032 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -83,6 +83,7 @@ struct fimd_win_data {
> unsigned int buf_offsize;
> unsigned int line_size; /* bytes */
> bool enabled;
> + bool resume;
> };
>
> struct fimd_context {
> @@ -596,6 +597,12 @@ static void fimd_win_disable(struct device *dev, int
> zpos)
>
> win_data = &ctx->win_data[win];
>
+ if (ctx->suspended) {
>
Ok, add the below comment,
"if disabling hw overlay is tried when fimd was disabled already then do
not access the hardware."
> + /* do not resume this window*/
> + win_data->resume = false;
> + return;
> + }
> +
> /* protect windows */
> val = readl(ctx->regs + SHADOWCON);
> val |= SHADOWCON_WINx_PROTECT(win);
> @@ -809,11 +816,38 @@ static int fimd_clock(struct fimd_context *ctx, bool
> enable)
> return 0;
> }
>
> +static void fimd_window_suspend(struct device *dev)
> +{
> + struct fimd_context *ctx = get_fimd_context(dev);
> + struct fimd_win_data *win_data;
> + int i;
> +
> + for (i = 0; i < WINDOWS_NR; i++) {
> + win_data = &ctx->win_data[i];
> + win_data->resume = win_data->enabled;
> + fimd_win_disable(dev, i);
> + }
> + fimd_wait_for_vblank(dev);
> +}
> +
> +static void fimd_window_resume(struct device *dev)
> +{
> + struct fimd_context *ctx = get_fimd_context(dev);
> + struct fimd_win_data *win_data;
> + int i;
> +
> + for (i = 0; i < WINDOWS_NR; i++) {
> + win_data = &ctx->win_data[i];
> + win_data->enabled = win_data->resume;
> + win_data->resume = false;
>
shouldn't the below code be added?
fimd_win_enable(dev, i);
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?
+ }
> +}
> +
> static int fimd_activate(struct fimd_context *ctx, bool enable)
> {
> + struct device *dev = ctx->subdrv.dev;
> if (enable) {
> int ret;
> - struct device *dev = ctx->subdrv.dev;
>
> ret = fimd_clock(ctx, true);
> if (ret < 0)
> @@ -824,7 +858,11 @@ static int fimd_activate(struct fimd_context *ctx,
> bool enable)
> /* if vblank was enabled status, enable it again. */
> if (test_and_clear_bit(0, &ctx->irq_flags))
> fimd_enable_vblank(dev);
> +
> + fimd_window_resume(dev);
> } else {
> + fimd_window_suspend(dev);
> +
> fimd_clock(ctx, false);
> ctx->suspended = true;
> }
> --
> 1.7.0.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20121207/f0333488/attachment.html>
More information about the dri-devel
mailing list