@@ -519,6 +519,12 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
519
519
520
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
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
666
win_data -> enabled = false;
661
667
}
662
668
669
+ static 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
+
682
+ static 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
+
697
+ static 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
+
710
+ static 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
+
725
+ static 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
+
762
+ enable_vblank_err :
763
+ clk_disable_unprepare (ctx -> lcd_clk );
764
+ lcd_clk_err :
765
+ clk_disable_unprepare (ctx -> bus_clk );
766
+ bus_clk_err :
767
+ ctx -> suspended = true;
768
+ return ret ;
769
+ }
770
+
771
+ static 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
+
663
792
static void fimd_dpms (struct exynos_drm_manager * mgr , int mode )
664
793
{
665
794
struct fimd_context * ctx = mgr -> ctx ;
@@ -736,113 +865,6 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
736
865
return IRQ_HANDLED ;
737
866
}
738
867
739
- static 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
-
752
- static 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
-
774
- static 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
-
788
- static 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
-
801
- static 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
-
816
- static 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
-
846
868
static int fimd_probe (struct platform_device * pdev )
847
869
{
848
870
struct device * dev = & pdev -> dev ;
@@ -859,6 +881,7 @@ static int fimd_probe(struct platform_device *pdev)
859
881
return - ENOMEM ;
860
882
861
883
ctx -> dev = dev ;
884
+ ctx -> suspended = true;
862
885
863
886
if (of_property_read_bool (dev -> of_node , "samsung,invert-vden" ))
864
887
ctx -> vidcon1 |= VIDCON1_INV_VDEN ;
@@ -945,7 +968,7 @@ static int fimd_suspend(struct device *dev)
945
968
* because the usage_count of pm runtime is more than 1.
946
969
*/
947
970
if (!pm_runtime_suspended (dev ))
948
- return fimd_activate (mgr , false );
971
+ return fimd_poweroff (mgr );
949
972
950
973
return 0 ;
951
974
}
@@ -962,7 +985,7 @@ static int fimd_resume(struct device *dev)
962
985
if (pm_runtime_suspended (dev ))
963
986
return 0 ;
964
987
965
- return fimd_activate (mgr , true );
988
+ return fimd_poweron (mgr );
966
989
}
967
990
#endif
968
991
@@ -971,14 +994,14 @@ static int fimd_runtime_suspend(struct device *dev)
971
994
{
972
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
977
1000
static int fimd_runtime_resume (struct device * dev )
978
1001
{
979
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
1006
#endif
984
1007
0 commit comments