aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorPrathyush K <prathyush.k@samsung.com>2012-12-06 09:46:05 -0500
committerInki Dae <daeinki@gmail.com>2012-12-13 09:05:44 -0500
commitdb43fd1624ed502beed604cd8e77aa921f9e555f (patch)
tree441bd93a69938d2ef1aa6474d4e019be330f298c /drivers/gpu
parent01ce113ca5b18aea4c97dea62287394ca4f8ad7f (diff)
drm/exynos: clear windows in mixer dpms off
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 <prathyush.k@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c193
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 b20c063d0b08..6c2c49912f13 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 {
60 unsigned int mode_width; 60 unsigned int mode_width;
61 unsigned int mode_height; 61 unsigned int mode_height;
62 unsigned int scan_flags; 62 unsigned int scan_flags;
63 bool enabled;
64 bool resume;
63}; 65};
64 66
65struct mixer_resources { 67struct mixer_resources {
@@ -688,60 +690,6 @@ static int mixer_iommu_on(void *ctx, bool enable)
688 return 0; 690 return 0;
689} 691}
690 692
691static void mixer_poweron(struct mixer_context *ctx)
692{
693 struct mixer_resources *res = &ctx->mixer_res;
694
695 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
696
697 mutex_lock(&ctx->mixer_mutex);
698 if (ctx->powered) {
699 mutex_unlock(&ctx->mixer_mutex);
700 return;
701 }
702 ctx->powered = true;
703 mutex_unlock(&ctx->mixer_mutex);
704
705 pm_runtime_get_sync(ctx->dev);
706
707 clk_enable(res->mixer);
708 if (ctx->vp_enabled) {
709 clk_enable(res->vp);
710 clk_enable(res->sclk_mixer);
711 }
712
713 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
714 mixer_win_reset(ctx);
715}
716
717static void mixer_poweroff(struct mixer_context *ctx)
718{
719 struct mixer_resources *res = &ctx->mixer_res;
720
721 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
722
723 mutex_lock(&ctx->mixer_mutex);
724 if (!ctx->powered)
725 goto out;
726 mutex_unlock(&ctx->mixer_mutex);
727
728 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
729
730 clk_disable(res->mixer);
731 if (ctx->vp_enabled) {
732 clk_disable(res->vp);
733 clk_disable(res->sclk_mixer);
734 }
735
736 pm_runtime_put_sync(ctx->dev);
737
738 mutex_lock(&ctx->mixer_mutex);
739 ctx->powered = false;
740
741out:
742 mutex_unlock(&ctx->mixer_mutex);
743}
744
745static int mixer_enable_vblank(void *ctx, int pipe) 693static int mixer_enable_vblank(void *ctx, int pipe)
746{ 694{
747 struct mixer_context *mixer_ctx = ctx; 695 struct mixer_context *mixer_ctx = ctx;
@@ -769,27 +717,6 @@ static void mixer_disable_vblank(void *ctx)
769 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 717 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
770} 718}
771 719
772static void mixer_dpms(void *ctx, int mode)
773{
774 struct mixer_context *mixer_ctx = ctx;
775
776 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
777
778 switch (mode) {
779 case DRM_MODE_DPMS_ON:
780 mixer_poweron(mixer_ctx);
781 break;
782 case DRM_MODE_DPMS_STANDBY:
783 case DRM_MODE_DPMS_SUSPEND:
784 case DRM_MODE_DPMS_OFF:
785 mixer_poweroff(mixer_ctx);
786 break;
787 default:
788 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
789 break;
790 }
791}
792
793static void mixer_win_mode_set(void *ctx, 720static void mixer_win_mode_set(void *ctx,
794 struct exynos_drm_overlay *overlay) 721 struct exynos_drm_overlay *overlay)
795{ 722{
@@ -856,6 +783,8 @@ static void mixer_win_commit(void *ctx, int win)
856 vp_video_buffer(mixer_ctx, win); 783 vp_video_buffer(mixer_ctx, win);
857 else 784 else
858 mixer_graph_buffer(mixer_ctx, win); 785 mixer_graph_buffer(mixer_ctx, win);
786
787 mixer_ctx->win_data[win].enabled = true;
859} 788}
860 789
861static void mixer_win_disable(void *ctx, int win) 790static void mixer_win_disable(void *ctx, int win)
@@ -866,6 +795,14 @@ static void mixer_win_disable(void *ctx, int win)
866 795
867 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); 796 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
868 797
798 mutex_lock(&mixer_ctx->mixer_mutex);
799 if (!mixer_ctx->powered) {
800 mutex_unlock(&mixer_ctx->mixer_mutex);
801 mixer_ctx->win_data[win].resume = false;
802 return;
803 }
804 mutex_unlock(&mixer_ctx->mixer_mutex);
805
869 spin_lock_irqsave(&res->reg_slock, flags); 806 spin_lock_irqsave(&res->reg_slock, flags);
870 mixer_vsync_set_update(mixer_ctx, false); 807 mixer_vsync_set_update(mixer_ctx, false);
871 808
@@ -873,6 +810,8 @@ static void mixer_win_disable(void *ctx, int win)
873 810
874 mixer_vsync_set_update(mixer_ctx, true); 811 mixer_vsync_set_update(mixer_ctx, true);
875 spin_unlock_irqrestore(&res->reg_slock, flags); 812 spin_unlock_irqrestore(&res->reg_slock, flags);
813
814 mixer_ctx->win_data[win].enabled = false;
876} 815}
877 816
878static void mixer_wait_for_vblank(void *ctx) 817static void mixer_wait_for_vblank(void *ctx)
@@ -898,6 +837,110 @@ static void mixer_wait_for_vblank(void *ctx)
898 DRM_DEBUG_KMS("vblank wait timed out.\n"); 837 DRM_DEBUG_KMS("vblank wait timed out.\n");
899} 838}
900 839
840static void mixer_window_suspend(struct mixer_context *ctx)
841{
842 struct hdmi_win_data *win_data;
843 int i;
844
845 for (i = 0; i < MIXER_WIN_NR; i++) {
846 win_data = &ctx->win_data[i];
847 win_data->resume = win_data->enabled;
848 mixer_win_disable(ctx, i);
849 }
850 mixer_wait_for_vblank(ctx);
851}
852
853static void mixer_window_resume(struct mixer_context *ctx)
854{
855 struct hdmi_win_data *win_data;
856 int i;
857
858 for (i = 0; i < MIXER_WIN_NR; i++) {
859 win_data = &ctx->win_data[i];
860 win_data->enabled = win_data->resume;
861 win_data->resume = false;
862 }
863}
864
865static void mixer_poweron(struct mixer_context *ctx)
866{
867 struct mixer_resources *res = &ctx->mixer_res;
868
869 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
870
871 mutex_lock(&ctx->mixer_mutex);
872 if (ctx->powered) {
873 mutex_unlock(&ctx->mixer_mutex);
874 return;
875 }
876 ctx->powered = true;
877 mutex_unlock(&ctx->mixer_mutex);
878
879 pm_runtime_get_sync(ctx->dev);
880
881 clk_enable(res->mixer);
882 if (ctx->vp_enabled) {
883 clk_enable(res->vp);
884 clk_enable(res->sclk_mixer);
885 }
886
887 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
888 mixer_win_reset(ctx);
889
890 mixer_window_resume(ctx);
891}
892
893static void mixer_poweroff(struct mixer_context *ctx)
894{
895 struct mixer_resources *res = &ctx->mixer_res;
896
897 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
898
899 mutex_lock(&ctx->mixer_mutex);
900 if (!ctx->powered)
901 goto out;
902 mutex_unlock(&ctx->mixer_mutex);
903
904 mixer_window_suspend(ctx);
905
906 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
907
908 clk_disable(res->mixer);
909 if (ctx->vp_enabled) {
910 clk_disable(res->vp);
911 clk_disable(res->sclk_mixer);
912 }
913
914 pm_runtime_put_sync(ctx->dev);
915
916 mutex_lock(&ctx->mixer_mutex);
917 ctx->powered = false;
918
919out:
920 mutex_unlock(&ctx->mixer_mutex);
921}
922
923static void mixer_dpms(void *ctx, int mode)
924{
925 struct mixer_context *mixer_ctx = ctx;
926
927 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
928
929 switch (mode) {
930 case DRM_MODE_DPMS_ON:
931 mixer_poweron(mixer_ctx);
932 break;
933 case DRM_MODE_DPMS_STANDBY:
934 case DRM_MODE_DPMS_SUSPEND:
935 case DRM_MODE_DPMS_OFF:
936 mixer_poweroff(mixer_ctx);
937 break;
938 default:
939 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
940 break;
941 }
942}
943
901static struct exynos_mixer_ops mixer_ops = { 944static struct exynos_mixer_ops mixer_ops = {
902 /* manager */ 945 /* manager */
903 .iommu_on = mixer_iommu_on, 946 .iommu_on = mixer_iommu_on,