aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2014-01-30 16:19:26 -0500
committerInki Dae <daeinki@gmail.com>2014-03-23 11:36:35 -0400
commita43b933bcbbd6c7e2660b672a311345cea9524c1 (patch)
tree7bad2880e8473b3c9706206745e378c37573d21d
parent12f5ad6c89b1716f010d5de3042560b2887ca1bc (diff)
drm/exynos: Clean up FIMD power on/off routines
This patch separates the fimd_activate function into poweron/poweroff functions to be more consistent with the other drivers in exynos drm. It also properly cleans up after failures in poweron. The functions have also been shuffled around such that they are all in the same spot in the file and poweron/poweroff can be called from the dpms function. Signed-off-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c245
1 files changed, 134 insertions, 111 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 6eb0008e0b62..1efdcac4510d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -519,6 +519,12 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
519 519
520 win_data = &ctx->win_data[win]; 520 win_data = &ctx->win_data[win];
521 521
522 /* If suspended, enable this on resume */
523 if (ctx->suspended) {
524 win_data->resume = true;
525 return;
526 }
527
522 /* 528 /*
523 * SHADOWCON/PRTCON register is used for enabling timing. 529 * SHADOWCON/PRTCON register is used for enabling timing.
524 * 530 *
@@ -660,6 +666,129 @@ static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
660 win_data->enabled = false; 666 win_data->enabled = false;
661} 667}
662 668
669static void fimd_clear_win(struct fimd_context *ctx, int win)
670{
671 writel(0, ctx->regs + WINCON(win));
672 writel(0, ctx->regs + VIDOSD_A(win));
673 writel(0, ctx->regs + VIDOSD_B(win));
674 writel(0, ctx->regs + VIDOSD_C(win));
675
676 if (win == 1 || win == 2)
677 writel(0, ctx->regs + VIDOSD_D(win));
678
679 fimd_shadow_protect_win(ctx, win, false);
680}
681
682static void fimd_window_suspend(struct exynos_drm_manager *mgr)
683{
684 struct fimd_context *ctx = mgr->ctx;
685 struct fimd_win_data *win_data;
686 int i;
687
688 for (i = 0; i < WINDOWS_NR; i++) {
689 win_data = &ctx->win_data[i];
690 win_data->resume = win_data->enabled;
691 if (win_data->enabled)
692 fimd_win_disable(mgr, i);
693 }
694 fimd_wait_for_vblank(mgr);
695}
696
697static void fimd_window_resume(struct exynos_drm_manager *mgr)
698{
699 struct fimd_context *ctx = mgr->ctx;
700 struct fimd_win_data *win_data;
701 int i;
702
703 for (i = 0; i < WINDOWS_NR; i++) {
704 win_data = &ctx->win_data[i];
705 win_data->enabled = win_data->resume;
706 win_data->resume = false;
707 }
708}
709
710static void fimd_apply(struct exynos_drm_manager *mgr)
711{
712 struct fimd_context *ctx = mgr->ctx;
713 struct fimd_win_data *win_data;
714 int i;
715
716 for (i = 0; i < WINDOWS_NR; i++) {
717 win_data = &ctx->win_data[i];
718 if (win_data->enabled)
719 fimd_win_commit(mgr, i);
720 }
721
722 fimd_commit(mgr);
723}
724
725static int fimd_poweron(struct exynos_drm_manager *mgr)
726{
727 struct fimd_context *ctx = mgr->ctx;
728 int ret;
729
730 if (!ctx->suspended)
731 return 0;
732
733 ctx->suspended = false;
734
735 ret = clk_prepare_enable(ctx->bus_clk);
736 if (ret < 0) {
737 DRM_ERROR("Failed to prepare_enable the bus clk [%d]\n", ret);
738 goto bus_clk_err;
739 }
740
741 ret = clk_prepare_enable(ctx->lcd_clk);
742 if (ret < 0) {
743 DRM_ERROR("Failed to prepare_enable the lcd clk [%d]\n", ret);
744 goto lcd_clk_err;
745 }
746
747 /* if vblank was enabled status, enable it again. */
748 if (test_and_clear_bit(0, &ctx->irq_flags)) {
749 ret = fimd_enable_vblank(mgr);
750 if (ret) {
751 DRM_ERROR("Failed to re-enable vblank [%d]\n", ret);
752 goto enable_vblank_err;
753 }
754 }
755
756 fimd_window_resume(mgr);
757
758 fimd_apply(mgr);
759
760 return 0;
761
762enable_vblank_err:
763 clk_disable_unprepare(ctx->lcd_clk);
764lcd_clk_err:
765 clk_disable_unprepare(ctx->bus_clk);
766bus_clk_err:
767 ctx->suspended = true;
768 return ret;
769}
770
771static int fimd_poweroff(struct exynos_drm_manager *mgr)
772{
773 struct fimd_context *ctx = mgr->ctx;
774
775 if (ctx->suspended)
776 return 0;
777
778 /*
779 * We need to make sure that all windows are disabled before we
780 * suspend that connector. Otherwise we might try to scan from
781 * a destroyed buffer later.
782 */
783 fimd_window_suspend(mgr);
784
785 clk_disable_unprepare(ctx->lcd_clk);
786 clk_disable_unprepare(ctx->bus_clk);
787
788 ctx->suspended = true;
789 return 0;
790}
791
663static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) 792static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
664{ 793{
665 struct fimd_context *ctx = mgr->ctx; 794 struct fimd_context *ctx = mgr->ctx;
@@ -736,113 +865,6 @@ out:
736 return IRQ_HANDLED; 865 return IRQ_HANDLED;
737} 866}
738 867
739static void fimd_clear_win(struct fimd_context *ctx, int win)
740{
741 writel(0, ctx->regs + WINCON(win));
742 writel(0, ctx->regs + VIDOSD_A(win));
743 writel(0, ctx->regs + VIDOSD_B(win));
744 writel(0, ctx->regs + VIDOSD_C(win));
745
746 if (win == 1 || win == 2)
747 writel(0, ctx->regs + VIDOSD_D(win));
748
749 fimd_shadow_protect_win(ctx, win, false);
750}
751
752static int fimd_clock(struct fimd_context *ctx, bool enable)
753{
754 if (enable) {
755 int ret;
756
757 ret = clk_prepare_enable(ctx->bus_clk);
758 if (ret < 0)
759 return ret;
760
761 ret = clk_prepare_enable(ctx->lcd_clk);
762 if (ret < 0) {
763 clk_disable_unprepare(ctx->bus_clk);
764 return ret;
765 }
766 } else {
767 clk_disable_unprepare(ctx->lcd_clk);
768 clk_disable_unprepare(ctx->bus_clk);
769 }
770
771 return 0;
772}
773
774static void fimd_window_suspend(struct exynos_drm_manager *mgr)
775{
776 struct fimd_context *ctx = mgr->ctx;
777 struct fimd_win_data *win_data;
778 int i;
779
780 for (i = 0; i < WINDOWS_NR; i++) {
781 win_data = &ctx->win_data[i];
782 win_data->resume = win_data->enabled;
783 fimd_win_disable(mgr, i);
784 }
785 fimd_wait_for_vblank(mgr);
786}
787
788static void fimd_window_resume(struct exynos_drm_manager *mgr)
789{
790 struct fimd_context *ctx = mgr->ctx;
791 struct fimd_win_data *win_data;
792 int i;
793
794 for (i = 0; i < WINDOWS_NR; i++) {
795 win_data = &ctx->win_data[i];
796 win_data->enabled = win_data->resume;
797 win_data->resume = false;
798 }
799}
800
801static void fimd_apply(struct exynos_drm_manager *mgr)
802{
803 struct fimd_context *ctx = mgr->ctx;
804 struct fimd_win_data *win_data;
805 int i;
806
807 for (i = 0; i < WINDOWS_NR; i++) {
808 win_data = &ctx->win_data[i];
809 if (win_data->enabled)
810 fimd_win_commit(mgr, i);
811 }
812
813 fimd_commit(mgr);
814}
815
816static int fimd_activate(struct exynos_drm_manager *mgr, bool enable)
817{
818 struct fimd_context *ctx = mgr->ctx;
819
820 if (enable) {
821 int ret;
822
823 ret = fimd_clock(ctx, true);
824 if (ret < 0)
825 return ret;
826
827 ctx->suspended = false;
828
829 /* if vblank was enabled status, enable it again. */
830 if (test_and_clear_bit(0, &ctx->irq_flags))
831 fimd_enable_vblank(mgr);
832
833 fimd_window_resume(mgr);
834
835 fimd_apply(mgr);
836 } else {
837 fimd_window_suspend(mgr);
838
839 fimd_clock(ctx, false);
840 ctx->suspended = true;
841 }
842
843 return 0;
844}
845
846static int fimd_probe(struct platform_device *pdev) 868static int fimd_probe(struct platform_device *pdev)
847{ 869{
848 struct device *dev = &pdev->dev; 870 struct device *dev = &pdev->dev;
@@ -859,6 +881,7 @@ static int fimd_probe(struct platform_device *pdev)
859 return -ENOMEM; 881 return -ENOMEM;
860 882
861 ctx->dev = dev; 883 ctx->dev = dev;
884 ctx->suspended = true;
862 885
863 if (of_property_read_bool(dev->of_node, "samsung,invert-vden")) 886 if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
864 ctx->vidcon1 |= VIDCON1_INV_VDEN; 887 ctx->vidcon1 |= VIDCON1_INV_VDEN;
@@ -945,7 +968,7 @@ static int fimd_suspend(struct device *dev)
945 * because the usage_count of pm runtime is more than 1. 968 * because the usage_count of pm runtime is more than 1.
946 */ 969 */
947 if (!pm_runtime_suspended(dev)) 970 if (!pm_runtime_suspended(dev))
948 return fimd_activate(mgr, false); 971 return fimd_poweroff(mgr);
949 972
950 return 0; 973 return 0;
951} 974}
@@ -962,7 +985,7 @@ static int fimd_resume(struct device *dev)
962 if (pm_runtime_suspended(dev)) 985 if (pm_runtime_suspended(dev))
963 return 0; 986 return 0;
964 987
965 return fimd_activate(mgr, true); 988 return fimd_poweron(mgr);
966} 989}
967#endif 990#endif
968 991
@@ -971,14 +994,14 @@ static int fimd_runtime_suspend(struct device *dev)
971{ 994{
972 struct exynos_drm_manager *mgr = get_fimd_manager(dev); 995 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
973 996
974 return fimd_activate(mgr, false); 997 return fimd_poweroff(mgr);
975} 998}
976 999
977static int fimd_runtime_resume(struct device *dev) 1000static int fimd_runtime_resume(struct device *dev)
978{ 1001{
979 struct exynos_drm_manager *mgr = get_fimd_manager(dev); 1002 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
980 1003
981 return fimd_activate(mgr, true); 1004 return fimd_poweron(mgr);
982} 1005}
983#endif 1006#endif
984 1007