diff options
-rw-r--r-- | 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 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 | ||
88 | struct fimd_context { | 89 | struct 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 | ||
819 | static 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 | |||
833 | static 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 | |||
812 | static int fimd_activate(struct fimd_context *ctx, bool enable) | 846 | static 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 | } |