From patchwork Thu Dec 6 14:46:05 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prathyush K X-Patchwork-Id: 1845011 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 6B9CEDF2F9 for ; Thu, 6 Dec 2012 14:36:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 419E9E6694 for ; Thu, 6 Dec 2012 06:36:32 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by gabe.freedesktop.org (Postfix) with ESMTP id C00DAE677B for ; Thu, 6 Dec 2012 06:25:53 -0800 (PST) Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MEM005EW5F4UPH0@mailout4.samsung.com> for dri-devel@lists.freedesktop.org; Thu, 06 Dec 2012 23:25:52 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.122]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id CE.6A.12699.0FAA0C05; Thu, 06 Dec 2012 23:25:52 +0900 (KST) X-AuditID: cbfee61b-b7f616d00000319b-b9-50c0aaf07a69 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id AE.6A.12699.0FAA0C05; Thu, 06 Dec 2012 23:25:52 +0900 (KST) Received: from localhost.localdomain ([107.108.73.106]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MEM009QO5AHQGB0@mmp2.samsung.com> for dri-devel@lists.freedesktop.org; Thu, 06 Dec 2012 23:25:52 +0900 (KST) From: Prathyush K To: dri-devel@lists.freedesktop.org Subject: [PATCH 6/7] drm/exynos: clear windows in mixer dpms off Date: Thu, 06 Dec 2012 20:16:05 +0530 Message-id: <1354805166-29365-7-git-send-email-prathyush.k@samsung.com> X-Mailer: git-send-email 1.7.0.4 In-reply-to: <1354805166-29365-1-git-send-email-prathyush.k@samsung.com> References: <1354805166-29365-1-git-send-email-prathyush.k@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrFLMWRmVeSWpSXmKPExsWyRsSkSvfDqgMBBk3rjC2ufH3P5sDocb/7 OFMAYxSXTUpqTmZZapG+XQJXxoljR9kLZptVvFp/n6mB8ZFOFyMnh4SAiUTnph5GCFtM4sK9 9WxdjFwcQgJLGSUu7joE5HCAFf15kQNSIyQwnVHi0mcHiJrVTBLvN95lB0mwCWhL/JpzlxXE FhFQlvg7cRXYUGYBCYkj7WfZQGxhAQeJ1X1TmUBsFgFVibZXDcwgNq+Au8TKtr+sEEcoSLQu O8QOspdTwENi3f9MiL3uErv+tLNCtApIfJt8iAXiNFmJTQeYQc6RELjOJrHr6UKoMZISB1fc YJnAKLyAkWEVo2hqQXJBcVJ6rpFecWJucWleul5yfu4mRmAAnv73THoH46oGi0OMAhyMSjy8 FtX7A4RYE8uKK3MPMUpwMCuJ8MZ0HAgQ4k1JrKxKLcqPLyrNSS0+xOgDdMlEZinR5HxgdOSV xBsam5ibGptaGhmZmZriEFYS5232SAkQEkhPLEnNTk0tSC2CGcfEwSnVwBi+bsOWnvmdnBxF 899N3RVYd32P35NbZ7t+Hv64/6r3T28ngVh9zRhz58sHhJhld+7RCd7qv3eax8cbObcT9B6v NvsfvpvpXXh0/iZFJfmzL/nXq+YIZR5fJN19doJ8/uW/zj+sjiTyzmYNXrh73ZePP3xnzVCx 6WOO5AgUbV7g93O192oBzV4lluKMREMt5qLiRACvdXZYbQIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupkkeLIzCtJLcpLzFFi42I5/e+xoO6HVQcCDNoOaFlc+fqezYHR4373 caYAxqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wc oLFKCmWJOaVAoYDE4mIlfTtME0JD3HQtYBojdH1DguB6jAzQQMIaxowTx46yF8w2q3i1/j5T A+MjnS5GDg4JAROJPy9yuhg5gUwxiQv31rOB2EIC0xklLn126GLkArJXM0m833iXHSTBJqAt 8WvOXVYQW0RAWeLvxFWMIDazgITEkfazYM3CAg4Sq/umMoHYLAKqEm2vGphBbF4Bd4mVbX9Z IZYpSLQuO8QOcgOngIfEuv+ZEHvdJXb9aWedwMi7gJFhFaNoakFyQXFSeq6RXnFibnFpXrpe cn7uJkZweD+T3sG4qsHiEKMAB6MSD69F9f4AIdbEsuLK3EOMEhzMSiK8MR0HAoR4UxIrq1KL 8uOLSnNSiw8x+gAdNZFZSjQ5Hxh7eSXxhsYm5qbGppYmFiZmljiElcR5mz1SAoQE0hNLUrNT UwtSi2DGMXFwSjUwTqvac+Los2/v4lcada99s//NQ/VXlzubNknHWDyXEZv4Rnn16ajOw/LT dn3z1HzMa31NQsfdK/TTB7b3H74s3nnqnO26l/N+c7MYzfB692pCS4mA4fHNhjeO7OnUK37z RMhuUv583oY0PpPYL/z3TgYJdU/LYuWcIs6hXLSmLcy3fP13l8OTU5VYijMSDbWYi4oTAUmS zH6cAgAA X-CFilter-Loop: Reflected X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org When mixer 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 mixer 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 mixer windows before disabling the mixer clocks. It also keeps track of which windows were currently active by setting the 'resume' flag. When mixer resumes, the window with a resume flag set is enabled again. Now if a current fb is removed when mixer is off, mixer_win_disable will set the 'resume' flag of that window to zero and return. So when mixer resumes, that window will not be resumed. Signed-off-by: Prathyush K --- drivers/gpu/drm/exynos/exynos_mixer.c | 193 ++++++++++++++++++++------------- 1 files changed, 118 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b20c063..6c2c499 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -60,6 +60,8 @@ struct hdmi_win_data { unsigned int mode_width; unsigned int mode_height; unsigned int scan_flags; + bool enabled; + bool resume; }; struct mixer_resources { @@ -688,60 +690,6 @@ static int mixer_iommu_on(void *ctx, bool enable) return 0; } -static void mixer_poweron(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mutex_lock(&ctx->mixer_mutex); - if (ctx->powered) { - mutex_unlock(&ctx->mixer_mutex); - return; - } - ctx->powered = true; - mutex_unlock(&ctx->mixer_mutex); - - pm_runtime_get_sync(ctx->dev); - - clk_enable(res->mixer); - if (ctx->vp_enabled) { - clk_enable(res->vp); - clk_enable(res->sclk_mixer); - } - - mixer_reg_write(res, MXR_INT_EN, ctx->int_en); - mixer_win_reset(ctx); -} - -static void mixer_poweroff(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - mutex_lock(&ctx->mixer_mutex); - if (!ctx->powered) - goto out; - mutex_unlock(&ctx->mixer_mutex); - - ctx->int_en = mixer_reg_read(res, MXR_INT_EN); - - clk_disable(res->mixer); - if (ctx->vp_enabled) { - clk_disable(res->vp); - clk_disable(res->sclk_mixer); - } - - pm_runtime_put_sync(ctx->dev); - - mutex_lock(&ctx->mixer_mutex); - ctx->powered = false; - -out: - mutex_unlock(&ctx->mixer_mutex); -} - static int mixer_enable_vblank(void *ctx, int pipe) { struct mixer_context *mixer_ctx = ctx; @@ -769,27 +717,6 @@ static void mixer_disable_vblank(void *ctx) mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); } -static void mixer_dpms(void *ctx, int mode) -{ - struct mixer_context *mixer_ctx = ctx; - - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - - switch (mode) { - case DRM_MODE_DPMS_ON: - mixer_poweron(mixer_ctx); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - mixer_poweroff(mixer_ctx); - break; - default: - DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); - break; - } -} - static void mixer_win_mode_set(void *ctx, struct exynos_drm_overlay *overlay) { @@ -856,6 +783,8 @@ static void mixer_win_commit(void *ctx, int win) vp_video_buffer(mixer_ctx, win); else mixer_graph_buffer(mixer_ctx, win); + + mixer_ctx->win_data[win].enabled = true; } static void mixer_win_disable(void *ctx, int win) @@ -866,6 +795,14 @@ static void mixer_win_disable(void *ctx, int win) DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); + mutex_lock(&mixer_ctx->mixer_mutex); + if (!mixer_ctx->powered) { + mutex_unlock(&mixer_ctx->mixer_mutex); + mixer_ctx->win_data[win].resume = false; + return; + } + mutex_unlock(&mixer_ctx->mixer_mutex); + spin_lock_irqsave(&res->reg_slock, flags); mixer_vsync_set_update(mixer_ctx, false); @@ -873,6 +810,8 @@ static void mixer_win_disable(void *ctx, int win) mixer_vsync_set_update(mixer_ctx, true); spin_unlock_irqrestore(&res->reg_slock, flags); + + mixer_ctx->win_data[win].enabled = false; } static void mixer_wait_for_vblank(void *ctx) @@ -898,6 +837,110 @@ static void mixer_wait_for_vblank(void *ctx) DRM_DEBUG_KMS("vblank wait timed out.\n"); } +static void mixer_window_suspend(struct mixer_context *ctx) +{ + struct hdmi_win_data *win_data; + int i; + + for (i = 0; i < MIXER_WIN_NR; i++) { + win_data = &ctx->win_data[i]; + win_data->resume = win_data->enabled; + mixer_win_disable(ctx, i); + } + mixer_wait_for_vblank(ctx); +} + +static void mixer_window_resume(struct mixer_context *ctx) +{ + struct hdmi_win_data *win_data; + int i; + + for (i = 0; i < MIXER_WIN_NR; i++) { + win_data = &ctx->win_data[i]; + win_data->enabled = win_data->resume; + win_data->resume = false; + } +} + +static void mixer_poweron(struct mixer_context *ctx) +{ + struct mixer_resources *res = &ctx->mixer_res; + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + mutex_lock(&ctx->mixer_mutex); + if (ctx->powered) { + mutex_unlock(&ctx->mixer_mutex); + return; + } + ctx->powered = true; + mutex_unlock(&ctx->mixer_mutex); + + pm_runtime_get_sync(ctx->dev); + + clk_enable(res->mixer); + if (ctx->vp_enabled) { + clk_enable(res->vp); + clk_enable(res->sclk_mixer); + } + + mixer_reg_write(res, MXR_INT_EN, ctx->int_en); + mixer_win_reset(ctx); + + mixer_window_resume(ctx); +} + +static void mixer_poweroff(struct mixer_context *ctx) +{ + struct mixer_resources *res = &ctx->mixer_res; + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + mutex_lock(&ctx->mixer_mutex); + if (!ctx->powered) + goto out; + mutex_unlock(&ctx->mixer_mutex); + + mixer_window_suspend(ctx); + + ctx->int_en = mixer_reg_read(res, MXR_INT_EN); + + clk_disable(res->mixer); + if (ctx->vp_enabled) { + clk_disable(res->vp); + clk_disable(res->sclk_mixer); + } + + pm_runtime_put_sync(ctx->dev); + + mutex_lock(&ctx->mixer_mutex); + ctx->powered = false; + +out: + mutex_unlock(&ctx->mixer_mutex); +} + +static void mixer_dpms(void *ctx, int mode) +{ + struct mixer_context *mixer_ctx = ctx; + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + switch (mode) { + case DRM_MODE_DPMS_ON: + mixer_poweron(mixer_ctx); + break; + case DRM_MODE_DPMS_STANDBY: + case DRM_MODE_DPMS_SUSPEND: + case DRM_MODE_DPMS_OFF: + mixer_poweroff(mixer_ctx); + break; + default: + DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); + break; + } +} + static struct exynos_mixer_ops mixer_ops = { /* manager */ .iommu_on = mixer_iommu_on,