@@ -806,6 +806,55 @@ static void vlv_write_wm_values(struct intel_crtc *crtc,
806
806
(wm -> ddl [pipe ].sprite [0 ] << DDL_SPRITE_SHIFT (0 )) |
807
807
(wm -> ddl [pipe ].primary << DDL_PLANE_SHIFT ));
808
808
809
+ I915_WRITE (DSPFW1 ,
810
+ ((wm -> sr .plane << DSPFW_SR_SHIFT ) & DSPFW_SR_MASK ) |
811
+ ((wm -> pipe [PIPE_B ].cursor << DSPFW_CURSORB_SHIFT ) & DSPFW_CURSORB_MASK ) |
812
+ ((wm -> pipe [PIPE_B ].primary << DSPFW_PLANEB_SHIFT ) & DSPFW_PLANEB_MASK_VLV ) |
813
+ ((wm -> pipe [PIPE_A ].primary << DSPFW_PLANEA_SHIFT ) & DSPFW_PLANEA_MASK_VLV ));
814
+ I915_WRITE (DSPFW2 ,
815
+ ((wm -> pipe [PIPE_A ].sprite [1 ] << DSPFW_SPRITEB_SHIFT ) & DSPFW_SPRITEB_MASK_VLV ) |
816
+ ((wm -> pipe [PIPE_A ].cursor << DSPFW_CURSORA_SHIFT ) & DSPFW_CURSORA_MASK ) |
817
+ ((wm -> pipe [PIPE_A ].sprite [0 ] << DSPFW_SPRITEA_SHIFT ) & DSPFW_SPRITEA_MASK_VLV ));
818
+ I915_WRITE (DSPFW3 ,
819
+ ((wm -> sr .cursor << DSPFW_CURSOR_SR_SHIFT ) & DSPFW_CURSOR_SR_MASK ));
820
+
821
+ if (IS_CHERRYVIEW (dev_priv )) {
822
+ I915_WRITE (DSPFW7_CHV ,
823
+ ((wm -> pipe [PIPE_B ].sprite [1 ] << DSPFW_SPRITED_SHIFT ) & DSPFW_SPRITED_MASK ) |
824
+ ((wm -> pipe [PIPE_B ].sprite [0 ] << DSPFW_SPRITEC_SHIFT ) & DSPFW_SPRITEC_MASK ));
825
+ I915_WRITE (DSPFW8_CHV ,
826
+ ((wm -> pipe [PIPE_C ].sprite [1 ] << DSPFW_SPRITEF_SHIFT ) & DSPFW_SPRITEF_MASK ) |
827
+ ((wm -> pipe [PIPE_C ].sprite [0 ] << DSPFW_SPRITEE_SHIFT ) & DSPFW_SPRITEE_MASK ));
828
+ I915_WRITE (DSPFW9_CHV ,
829
+ ((wm -> pipe [PIPE_C ].primary << DSPFW_PLANEC_SHIFT ) & DSPFW_PLANEC_MASK ) |
830
+ ((wm -> pipe [PIPE_C ].cursor << DSPFW_CURSORC_SHIFT ) & DSPFW_CURSORC_MASK ));
831
+ I915_WRITE (DSPHOWM ,
832
+ (((wm -> sr .plane >> 9 ) << DSPFW_SR_HI_SHIFT ) & DSPFW_SR_HI_MASK ) |
833
+ (((wm -> pipe [PIPE_C ].sprite [1 ] >> 8 ) << DSPFW_SPRITEF_HI_SHIFT ) & DSPFW_SPRITEF_HI_MASK ) |
834
+ (((wm -> pipe [PIPE_C ].sprite [0 ] >> 8 ) << DSPFW_SPRITEE_HI_SHIFT ) & DSPFW_SPRITEE_HI_MASK ) |
835
+ (((wm -> pipe [PIPE_C ].primary >> 8 ) << DSPFW_PLANEC_HI_SHIFT ) & DSPFW_PLANEC_HI_MASK ) |
836
+ (((wm -> pipe [PIPE_B ].sprite [1 ] >> 8 ) << DSPFW_SPRITED_HI_SHIFT ) & DSPFW_SPRITED_HI_MASK ) |
837
+ (((wm -> pipe [PIPE_B ].sprite [0 ] >> 8 ) << DSPFW_SPRITEC_HI_SHIFT ) & DSPFW_SPRITEC_HI_MASK ) |
838
+ (((wm -> pipe [PIPE_B ].primary >> 8 ) << DSPFW_PLANEB_HI_SHIFT ) & DSPFW_PLANEB_HI_MASK ) |
839
+ (((wm -> pipe [PIPE_A ].sprite [1 ] >> 8 ) << DSPFW_SPRITEB_HI_SHIFT ) & DSPFW_SPRITEB_HI_MASK ) |
840
+ (((wm -> pipe [PIPE_A ].sprite [0 ] >> 8 ) << DSPFW_SPRITEA_HI_SHIFT ) & DSPFW_SPRITEA_HI_MASK ) |
841
+ (((wm -> pipe [PIPE_A ].primary >> 8 ) << DSPFW_PLANEA_HI_SHIFT ) & DSPFW_PLANEA_HI_MASK ));
842
+ } else {
843
+ I915_WRITE (DSPFW7 ,
844
+ ((wm -> pipe [PIPE_B ].sprite [1 ] << DSPFW_SPRITED_SHIFT ) & DSPFW_SPRITED_MASK ) |
845
+ ((wm -> pipe [PIPE_B ].sprite [0 ] << DSPFW_SPRITEC_SHIFT ) & DSPFW_SPRITEC_MASK ));
846
+ I915_WRITE (DSPHOWM ,
847
+ (((wm -> sr .plane >> 9 ) << DSPFW_SR_HI_SHIFT ) & DSPFW_SR_HI_MASK ) |
848
+ (((wm -> pipe [PIPE_B ].sprite [1 ] >> 8 ) << DSPFW_SPRITED_HI_SHIFT ) & DSPFW_SPRITED_HI_MASK ) |
849
+ (((wm -> pipe [PIPE_B ].sprite [0 ] >> 8 ) << DSPFW_SPRITEC_HI_SHIFT ) & DSPFW_SPRITEC_HI_MASK ) |
850
+ (((wm -> pipe [PIPE_B ].primary >> 8 ) << DSPFW_PLANEB_HI_SHIFT ) & DSPFW_PLANEB_HI_MASK ) |
851
+ (((wm -> pipe [PIPE_A ].sprite [1 ] >> 8 ) << DSPFW_SPRITEB_HI_SHIFT ) & DSPFW_SPRITEB_HI_MASK ) |
852
+ (((wm -> pipe [PIPE_A ].sprite [0 ] >> 8 ) << DSPFW_SPRITEA_HI_SHIFT ) & DSPFW_SPRITEA_HI_MASK ) |
853
+ (((wm -> pipe [PIPE_A ].primary >> 8 ) << DSPFW_PLANEA_HI_SHIFT ) & DSPFW_PLANEA_HI_MASK ));
854
+ }
855
+
856
+ POSTING_READ (DSPFW1 );
857
+
809
858
dev_priv -> wm .vlv = * wm ;
810
859
}
811
860
@@ -850,169 +899,113 @@ static uint8_t vlv_compute_drain_latency(struct drm_crtc *crtc,
850
899
DDL_PRECISION_HIGH : DDL_PRECISION_LOW );
851
900
}
852
901
853
- /*
854
- * Update drain latency registers of memory arbiter
855
- *
856
- * Valleyview SoC has a new memory arbiter and needs drain latency registers
857
- * to be programmed. Each plane has a drain latency multiplier and a drain
858
- * latency value.
859
- */
860
-
861
- static void vlv_update_drain_latency (struct drm_crtc * crtc )
902
+ static int vlv_compute_wm (struct intel_crtc * crtc ,
903
+ struct intel_plane * plane ,
904
+ int fifo_size )
862
905
{
863
- struct drm_device * dev = crtc -> dev ;
864
- struct drm_i915_private * dev_priv = dev -> dev_private ;
865
- struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
866
- enum pipe pipe = intel_crtc -> pipe ;
867
- struct vlv_wm_values wm = dev_priv -> wm .vlv ;
906
+ int clock , entries , pixel_size ;
868
907
869
- wm .ddl [pipe ].primary = vlv_compute_drain_latency (crtc , crtc -> primary );
870
- wm .ddl [pipe ].cursor = vlv_compute_drain_latency (crtc , crtc -> cursor );
908
+ /*
909
+ * FIXME the plane might have an fb
910
+ * but be invisible (eg. due to clipping)
911
+ */
912
+ if (!crtc -> active || !plane -> base .state -> fb )
913
+ return 0 ;
871
914
872
- vlv_write_wm_values ( intel_crtc , & wm );
873
- }
915
+ pixel_size = drm_format_plane_cpp ( plane -> base . state -> fb -> pixel_format , 0 );
916
+ clock = crtc -> config -> base . adjusted_mode . crtc_clock ;
874
917
875
- #define single_plane_enabled ( mask ) is_power_of_2(mask)
918
+ entries = DIV_ROUND_UP ( clock , 1000 ) * pixel_size ;
876
919
877
- static void valleyview_update_wm (struct drm_crtc * crtc )
920
+ /*
921
+ * Set up the watermark such that we don't start issuing memory
922
+ * requests until we are within PND's max deadline value (256us).
923
+ * Idea being to be idle as long as possible while still taking
924
+ * advatange of PND's deadline scheduling. The limit of 8
925
+ * cachelines (used when the FIFO will anyway drain in less time
926
+ * than 256us) should match what we would be done if trickle
927
+ * feed were enabled.
928
+ */
929
+ return fifo_size - clamp (DIV_ROUND_UP (256 * entries , 64 ), 0 , fifo_size - 8 );
930
+ }
931
+
932
+ static bool vlv_compute_sr_wm (struct drm_device * dev ,
933
+ struct vlv_wm_values * wm )
878
934
{
879
- struct drm_device * dev = crtc -> dev ;
880
- static const int sr_latency_ns = 12000 ;
881
- struct drm_i915_private * dev_priv = dev -> dev_private ;
882
- int planea_wm , planeb_wm , cursora_wm , cursorb_wm ;
883
- int plane_sr , cursor_sr ;
884
- int ignore_plane_sr , ignore_cursor_sr ;
885
- unsigned int enabled = 0 ;
886
- bool cxsr_enabled ;
935
+ struct drm_i915_private * dev_priv = to_i915 (dev );
936
+ struct drm_crtc * crtc ;
937
+ enum pipe pipe = INVALID_PIPE ;
938
+ int num_planes = 0 ;
939
+ int fifo_size = 0 ;
940
+ struct intel_plane * plane ;
887
941
888
- vlv_update_drain_latency ( crtc ) ;
942
+ wm -> sr . cursor = wm -> sr . plane = 0 ;
889
943
890
- if (g4x_compute_wm0 (dev , PIPE_A ,
891
- & valleyview_wm_info , pessimal_latency_ns ,
892
- & valleyview_cursor_wm_info , pessimal_latency_ns ,
893
- & planea_wm , & cursora_wm ))
894
- enabled |= 1 << PIPE_A ;
944
+ crtc = single_enabled_crtc (dev );
945
+ /* maxfifo not supported on pipe C */
946
+ if (crtc && to_intel_crtc (crtc )-> pipe != PIPE_C ) {
947
+ pipe = to_intel_crtc (crtc )-> pipe ;
948
+ num_planes = !!wm -> pipe [pipe ].primary +
949
+ !!wm -> pipe [pipe ].sprite [0 ] +
950
+ !!wm -> pipe [pipe ].sprite [1 ];
951
+ fifo_size = INTEL_INFO (dev_priv )-> num_pipes * 512 - 1 ;
952
+ }
895
953
896
- if (g4x_compute_wm0 (dev , PIPE_B ,
897
- & valleyview_wm_info , pessimal_latency_ns ,
898
- & valleyview_cursor_wm_info , pessimal_latency_ns ,
899
- & planeb_wm , & cursorb_wm ))
900
- enabled |= 1 << PIPE_B ;
954
+ if (fifo_size == 0 || num_planes > 1 )
955
+ return false;
901
956
902
- if (single_plane_enabled (enabled ) &&
903
- g4x_compute_srwm (dev , ffs (enabled ) - 1 ,
904
- sr_latency_ns ,
905
- & valleyview_wm_info ,
906
- & valleyview_cursor_wm_info ,
907
- & plane_sr , & ignore_cursor_sr ) &&
908
- g4x_compute_srwm (dev , ffs (enabled ) - 1 ,
909
- 2 * sr_latency_ns ,
910
- & valleyview_wm_info ,
911
- & valleyview_cursor_wm_info ,
912
- & ignore_plane_sr , & cursor_sr )) {
913
- cxsr_enabled = true;
914
- } else {
915
- cxsr_enabled = false;
916
- intel_set_memory_cxsr (dev_priv , false);
917
- plane_sr = cursor_sr = 0 ;
918
- }
957
+ wm -> sr .cursor = vlv_compute_wm (to_intel_crtc (crtc ),
958
+ to_intel_plane (crtc -> cursor ), 0x3f );
919
959
920
- DRM_DEBUG_KMS ("Setting FIFO watermarks - A: plane=%d, cursor=%d, "
921
- "B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n" ,
922
- planea_wm , cursora_wm ,
923
- planeb_wm , cursorb_wm ,
924
- plane_sr , cursor_sr );
960
+ list_for_each_entry (plane , & dev -> mode_config .plane_list , base .head ) {
961
+ if (plane -> base .type == DRM_PLANE_TYPE_CURSOR )
962
+ continue ;
925
963
926
- I915_WRITE (DSPFW1 ,
927
- (plane_sr << DSPFW_SR_SHIFT ) |
928
- (cursorb_wm << DSPFW_CURSORB_SHIFT ) |
929
- (planeb_wm << DSPFW_PLANEB_SHIFT ) |
930
- (planea_wm << DSPFW_PLANEA_SHIFT ));
931
- I915_WRITE (DSPFW2 ,
932
- (I915_READ (DSPFW2 ) & ~DSPFW_CURSORA_MASK ) |
933
- (cursora_wm << DSPFW_CURSORA_SHIFT ));
934
- I915_WRITE (DSPFW3 ,
935
- (I915_READ (DSPFW3 ) & ~DSPFW_CURSOR_SR_MASK ) |
936
- (cursor_sr << DSPFW_CURSOR_SR_SHIFT ));
964
+ if (plane -> pipe != pipe )
965
+ continue ;
937
966
938
- if (cxsr_enabled )
939
- intel_set_memory_cxsr (dev_priv , true);
967
+ wm -> sr .plane = vlv_compute_wm (to_intel_crtc (crtc ),
968
+ plane , fifo_size );
969
+ if (wm -> sr .plane != 0 )
970
+ break ;
971
+ }
972
+
973
+ return true;
940
974
}
941
975
942
- static void cherryview_update_wm (struct drm_crtc * crtc )
976
+ static void valleyview_update_wm (struct drm_crtc * crtc )
943
977
{
944
978
struct drm_device * dev = crtc -> dev ;
945
- static const int sr_latency_ns = 12000 ;
946
979
struct drm_i915_private * dev_priv = dev -> dev_private ;
947
- int planea_wm , planeb_wm , planec_wm ;
948
- int cursora_wm , cursorb_wm , cursorc_wm ;
949
- int plane_sr , cursor_sr ;
950
- int ignore_plane_sr , ignore_cursor_sr ;
951
- unsigned int enabled = 0 ;
980
+ struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
981
+ enum pipe pipe = intel_crtc -> pipe ;
952
982
bool cxsr_enabled ;
983
+ struct vlv_wm_values wm = dev_priv -> wm .vlv ;
953
984
954
- vlv_update_drain_latency (crtc );
985
+ wm .ddl [pipe ].primary = vlv_compute_drain_latency (crtc , crtc -> primary );
986
+ wm .pipe [pipe ].primary = vlv_compute_wm (intel_crtc ,
987
+ to_intel_plane (crtc -> primary ),
988
+ vlv_get_fifo_size (dev , pipe , 0 ));
955
989
956
- if (g4x_compute_wm0 (dev , PIPE_A ,
957
- & valleyview_wm_info , pessimal_latency_ns ,
958
- & valleyview_cursor_wm_info , pessimal_latency_ns ,
959
- & planea_wm , & cursora_wm ))
960
- enabled |= 1 << PIPE_A ;
990
+ wm .ddl [pipe ].cursor = vlv_compute_drain_latency (crtc , crtc -> cursor );
991
+ wm .pipe [pipe ].cursor = vlv_compute_wm (intel_crtc ,
992
+ to_intel_plane (crtc -> cursor ),
993
+ 0x3f );
961
994
962
- if (g4x_compute_wm0 (dev , PIPE_B ,
963
- & valleyview_wm_info , pessimal_latency_ns ,
964
- & valleyview_cursor_wm_info , pessimal_latency_ns ,
965
- & planeb_wm , & cursorb_wm ))
966
- enabled |= 1 << PIPE_B ;
995
+ cxsr_enabled = vlv_compute_sr_wm (dev , & wm );
967
996
968
- if (g4x_compute_wm0 (dev , PIPE_C ,
969
- & valleyview_wm_info , pessimal_latency_ns ,
970
- & valleyview_cursor_wm_info , pessimal_latency_ns ,
971
- & planec_wm , & cursorc_wm ))
972
- enabled |= 1 << PIPE_C ;
997
+ if (memcmp (& wm , & dev_priv -> wm .vlv , sizeof (wm )) == 0 )
998
+ return ;
973
999
974
- if (single_plane_enabled (enabled ) &&
975
- g4x_compute_srwm (dev , ffs (enabled ) - 1 ,
976
- sr_latency_ns ,
977
- & valleyview_wm_info ,
978
- & valleyview_cursor_wm_info ,
979
- & plane_sr , & ignore_cursor_sr ) &&
980
- g4x_compute_srwm (dev , ffs (enabled ) - 1 ,
981
- 2 * sr_latency_ns ,
982
- & valleyview_wm_info ,
983
- & valleyview_cursor_wm_info ,
984
- & ignore_plane_sr , & cursor_sr )) {
985
- cxsr_enabled = true;
986
- } else {
987
- cxsr_enabled = false;
988
- intel_set_memory_cxsr (dev_priv , false);
989
- plane_sr = cursor_sr = 0 ;
990
- }
1000
+ DRM_DEBUG_KMS ("Setting FIFO watermarks - %c: plane=%d, cursor=%d, "
1001
+ "SR: plane=%d, cursor=%d\n" , pipe_name (pipe ),
1002
+ wm .pipe [pipe ].primary , wm .pipe [pipe ].cursor ,
1003
+ wm .sr .plane , wm .sr .cursor );
991
1004
992
- DRM_DEBUG_KMS ("Setting FIFO watermarks - A: plane=%d, cursor=%d, "
993
- "B: plane=%d, cursor=%d, C: plane=%d, cursor=%d, "
994
- "SR: plane=%d, cursor=%d\n" ,
995
- planea_wm , cursora_wm ,
996
- planeb_wm , cursorb_wm ,
997
- planec_wm , cursorc_wm ,
998
- plane_sr , cursor_sr );
1005
+ if (!cxsr_enabled )
1006
+ intel_set_memory_cxsr (dev_priv , false);
999
1007
1000
- I915_WRITE (DSPFW1 ,
1001
- (plane_sr << DSPFW_SR_SHIFT ) |
1002
- (cursorb_wm << DSPFW_CURSORB_SHIFT ) |
1003
- (planeb_wm << DSPFW_PLANEB_SHIFT ) |
1004
- (planea_wm << DSPFW_PLANEA_SHIFT ));
1005
- I915_WRITE (DSPFW2 ,
1006
- (I915_READ (DSPFW2 ) & ~DSPFW_CURSORA_MASK ) |
1007
- (cursora_wm << DSPFW_CURSORA_SHIFT ));
1008
- I915_WRITE (DSPFW3 ,
1009
- (I915_READ (DSPFW3 ) & ~DSPFW_CURSOR_SR_MASK ) |
1010
- (cursor_sr << DSPFW_CURSOR_SR_SHIFT ));
1011
- I915_WRITE (DSPFW9_CHV ,
1012
- (I915_READ (DSPFW9_CHV ) & ~(DSPFW_PLANEC_MASK |
1013
- DSPFW_CURSORC_MASK )) |
1014
- (planec_wm << DSPFW_PLANEC_SHIFT ) |
1015
- (cursorc_wm << DSPFW_CURSORC_SHIFT ));
1008
+ vlv_write_wm_values (intel_crtc , & wm );
1016
1009
1017
1010
if (cxsr_enabled )
1018
1011
intel_set_memory_cxsr (dev_priv , true);
@@ -1030,17 +1023,44 @@ static void valleyview_update_sprite_wm(struct drm_plane *plane,
1030
1023
struct intel_crtc * intel_crtc = to_intel_crtc (crtc );
1031
1024
enum pipe pipe = intel_crtc -> pipe ;
1032
1025
int sprite = to_intel_plane (plane )-> plane ;
1026
+ bool cxsr_enabled ;
1033
1027
struct vlv_wm_values wm = dev_priv -> wm .vlv ;
1034
1028
1035
- if (enabled )
1029
+ if (enabled ) {
1036
1030
wm .ddl [pipe ].sprite [sprite ] =
1037
1031
vlv_compute_drain_latency (crtc , plane );
1038
- else
1032
+
1033
+ wm .pipe [pipe ].sprite [sprite ] =
1034
+ vlv_compute_wm (intel_crtc ,
1035
+ to_intel_plane (plane ),
1036
+ vlv_get_fifo_size (dev , pipe , sprite + 1 ));
1037
+ } else {
1039
1038
wm .ddl [pipe ].sprite [sprite ] = 0 ;
1039
+ wm .pipe [pipe ].sprite [sprite ] = 0 ;
1040
+ }
1041
+
1042
+ cxsr_enabled = vlv_compute_sr_wm (dev , & wm );
1043
+
1044
+ if (memcmp (& wm , & dev_priv -> wm .vlv , sizeof (wm )) == 0 )
1045
+ return ;
1046
+
1047
+ DRM_DEBUG_KMS ("Setting FIFO watermarks - %c: sprite %c=%d, "
1048
+ "SR: plane=%d, cursor=%d\n" , pipe_name (pipe ),
1049
+ sprite_name (pipe , sprite ),
1050
+ wm .pipe [pipe ].sprite [sprite ],
1051
+ wm .sr .plane , wm .sr .cursor );
1052
+
1053
+ if (!cxsr_enabled )
1054
+ intel_set_memory_cxsr (dev_priv , false);
1040
1055
1041
1056
vlv_write_wm_values (intel_crtc , & wm );
1057
+
1058
+ if (cxsr_enabled )
1059
+ intel_set_memory_cxsr (dev_priv , true);
1042
1060
}
1043
1061
1062
+ #define single_plane_enabled (mask ) is_power_of_2(mask)
1063
+
1044
1064
static void g4x_update_wm (struct drm_crtc * crtc )
1045
1065
{
1046
1066
struct drm_device * dev = crtc -> dev ;
@@ -6430,7 +6450,7 @@ void intel_init_pm(struct drm_device *dev)
6430
6450
else if (INTEL_INFO (dev )-> gen == 8 )
6431
6451
dev_priv -> display .init_clock_gating = broadwell_init_clock_gating ;
6432
6452
} else if (IS_CHERRYVIEW (dev )) {
6433
- dev_priv -> display .update_wm = cherryview_update_wm ;
6453
+ dev_priv -> display .update_wm = valleyview_update_wm ;
6434
6454
dev_priv -> display .update_sprite_wm = valleyview_update_sprite_wm ;
6435
6455
dev_priv -> display .init_clock_gating =
6436
6456
cherryview_init_clock_gating ;
0 commit comments