aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos
diff options
context:
space:
mode:
authorPrathyush K <prathyush.k@samsung.com>2012-12-06 09:46:06 -0500
committerInki Dae <daeinki@gmail.com>2012-12-13 09:05:45 -0500
commitdb7e55ae527ccbca300eb5b15f5428b83325328d (patch)
treeced5ab584cade4068e94703fbaec6f952c45bd93 /drivers/gpu/drm/exynos
parentdb43fd1624ed502beed604cd8e77aa921f9e555f (diff)
drm/exynos: clear windows in fimd dpms off
Changelog v2: Added details of original patch in chromium kernel Changelog v1: 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. This patch is based on the following two patches: http://git.chromium.org/gitweb/?p=chromiumos/third_party/kernel.git;a=commitdiff;h=341e973c967304976a762211b6465b0074de62ef http://git.chromium.org/gitweb/?p=chromiumos/third_party/kernel.git;a=commitdiff;h=cfa22e49b7408547c73532c4bb03de47cc034a05 These two patches are rebased onto the current kernel with additional changes like removing 'fimd_win_commit' call from the resume function since this is taken care by encoder dpms, and the modification of resume flag in win_disable. Signed-off-by: Prathyush K <prathyush.k@samsung.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Stephane Marchesin <marcheu@chromium.org> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c40
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 1517d15d5fa6..7e660322feaf 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 {
83 unsigned int buf_offsize; 83 unsigned int buf_offsize;
84 unsigned int line_size; /* bytes */ 84 unsigned int line_size; /* bytes */
85 bool enabled; 85 bool enabled;
86 bool resume;
86}; 87};
87 88
88struct fimd_context { 89struct fimd_context {
@@ -596,6 +597,12 @@ static void fimd_win_disable(struct device *dev, int zpos)
596 597
597 win_data = &ctx->win_data[win]; 598 win_data = &ctx->win_data[win];
598 599
600 if (ctx->suspended) {
601 /* do not resume this window*/
602 win_data->resume = false;
603 return;
604 }
605
599 /* protect windows */ 606 /* protect windows */
600 val = readl(ctx->regs + SHADOWCON); 607 val = readl(ctx->regs + SHADOWCON);
601 val |= SHADOWCON_WINx_PROTECT(win); 608 val |= SHADOWCON_WINx_PROTECT(win);
@@ -809,11 +816,38 @@ static int fimd_clock(struct fimd_context *ctx, bool enable)
809 return 0; 816 return 0;
810} 817}
811 818
819static void fimd_window_suspend(struct device *dev)
820{
821 struct fimd_context *ctx = get_fimd_context(dev);
822 struct fimd_win_data *win_data;
823 int i;
824
825 for (i = 0; i < WINDOWS_NR; i++) {
826 win_data = &ctx->win_data[i];
827 win_data->resume = win_data->enabled;
828 fimd_win_disable(dev, i);
829 }
830 fimd_wait_for_vblank(dev);
831}
832
833static void fimd_window_resume(struct device *dev)
834{
835 struct fimd_context *ctx = get_fimd_context(dev);
836 struct fimd_win_data *win_data;
837 int i;
838
839 for (i = 0; i < WINDOWS_NR; i++) {
840 win_data = &ctx->win_data[i];
841 win_data->enabled = win_data->resume;
842 win_data->resume = false;
843 }
844}
845
812static int fimd_activate(struct fimd_context *ctx, bool enable) 846static int fimd_activate(struct fimd_context *ctx, bool enable)
813{ 847{
848 struct device *dev = ctx->subdrv.dev;
814 if (enable) { 849 if (enable) {
815 int ret; 850 int ret;
816 struct device *dev = ctx->subdrv.dev;
817 851
818 ret = fimd_clock(ctx, true); 852 ret = fimd_clock(ctx, true);
819 if (ret < 0) 853 if (ret < 0)
@@ -824,7 +858,11 @@ static int fimd_activate(struct fimd_context *ctx, bool enable)
824 /* if vblank was enabled status, enable it again. */ 858 /* if vblank was enabled status, enable it again. */
825 if (test_and_clear_bit(0, &ctx->irq_flags)) 859 if (test_and_clear_bit(0, &ctx->irq_flags))
826 fimd_enable_vblank(dev); 860 fimd_enable_vblank(dev);
861
862 fimd_window_resume(dev);
827 } else { 863 } else {
864 fimd_window_suspend(dev);
865
828 fimd_clock(ctx, false); 866 fimd_clock(ctx, false);
829 ctx->suspended = true; 867 ctx->suspended = true;
830 } 868 }