@@ -803,6 +803,128 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state)
803803 return to_intel_bw_state (bw_state );
804804}
805805
806+ static int icl_find_qgv_points (struct drm_i915_private * i915 ,
807+ unsigned int data_rate ,
808+ unsigned int num_active_planes ,
809+ const struct intel_bw_state * old_bw_state ,
810+ struct intel_bw_state * new_bw_state )
811+ {
812+ unsigned int max_bw_point = 0 ;
813+ unsigned int max_bw = 0 ;
814+ unsigned int num_psf_gv_points = i915 -> display .bw .max [0 ].num_psf_gv_points ;
815+ unsigned int num_qgv_points = i915 -> display .bw .max [0 ].num_qgv_points ;
816+ u16 psf_points = 0 ;
817+ u16 qgv_points = 0 ;
818+ int i ;
819+ int ret ;
820+
821+ ret = intel_atomic_lock_global_state (& new_bw_state -> base );
822+ if (ret )
823+ return ret ;
824+
825+ for (i = 0 ; i < num_qgv_points ; i ++ ) {
826+ unsigned int max_data_rate ;
827+
828+ if (DISPLAY_VER (i915 ) > 11 )
829+ max_data_rate = tgl_max_bw (i915 , num_active_planes , i );
830+ else
831+ max_data_rate = icl_max_bw (i915 , num_active_planes , i );
832+ /*
833+ * We need to know which qgv point gives us
834+ * maximum bandwidth in order to disable SAGV
835+ * if we find that we exceed SAGV block time
836+ * with watermarks. By that moment we already
837+ * have those, as it is calculated earlier in
838+ * intel_atomic_check,
839+ */
840+ if (max_data_rate > max_bw ) {
841+ max_bw_point = i ;
842+ max_bw = max_data_rate ;
843+ }
844+ if (max_data_rate >= data_rate )
845+ qgv_points |= BIT (i );
846+
847+ drm_dbg_kms (& i915 -> drm , "QGV point %d: max bw %d required %d\n" ,
848+ i , max_data_rate , data_rate );
849+ }
850+
851+ for (i = 0 ; i < num_psf_gv_points ; i ++ ) {
852+ unsigned int max_data_rate = adl_psf_bw (i915 , i );
853+
854+ if (max_data_rate >= data_rate )
855+ psf_points |= BIT (i );
856+
857+ drm_dbg_kms (& i915 -> drm , "PSF GV point %d: max bw %d"
858+ " required %d\n" ,
859+ i , max_data_rate , data_rate );
860+ }
861+
862+ /*
863+ * BSpec states that we always should have at least one allowed point
864+ * left, so if we couldn't - simply reject the configuration for obvious
865+ * reasons.
866+ */
867+ if (qgv_points == 0 ) {
868+ drm_dbg_kms (& i915 -> drm , "No QGV points provide sufficient memory"
869+ " bandwidth %d for display configuration(%d active planes).\n" ,
870+ data_rate , num_active_planes );
871+ return - EINVAL ;
872+ }
873+
874+ if (num_psf_gv_points > 0 && psf_points == 0 ) {
875+ drm_dbg_kms (& i915 -> drm , "No PSF GV points provide sufficient memory"
876+ " bandwidth %d for display configuration(%d active planes).\n" ,
877+ data_rate , num_active_planes );
878+ return - EINVAL ;
879+ }
880+
881+ /*
882+ * Leave only single point with highest bandwidth, if
883+ * we can't enable SAGV due to the increased memory latency it may
884+ * cause.
885+ */
886+ if (!intel_can_enable_sagv (i915 , new_bw_state )) {
887+ qgv_points = BIT (max_bw_point );
888+ drm_dbg_kms (& i915 -> drm , "No SAGV, using single QGV point %d\n" ,
889+ max_bw_point );
890+ }
891+
892+ /*
893+ * We store the ones which need to be masked as that is what PCode
894+ * actually accepts as a parameter.
895+ */
896+ new_bw_state -> qgv_points_mask =
897+ ~(ICL_PCODE_REQ_QGV_PT (qgv_points ) |
898+ ADLS_PCODE_REQ_PSF_PT (psf_points )) &
899+ icl_qgv_points_mask (i915 );
900+
901+ /*
902+ * If the actual mask had changed we need to make sure that
903+ * the commits are serialized(in case this is a nomodeset, nonblocking)
904+ */
905+ if (new_bw_state -> qgv_points_mask != old_bw_state -> qgv_points_mask ) {
906+ ret = intel_atomic_serialize_global_state (& new_bw_state -> base );
907+ if (ret )
908+ return ret ;
909+ }
910+
911+ return 0 ;
912+ }
913+
914+ static int intel_bw_check_qgv_points (struct drm_i915_private * i915 ,
915+ const struct intel_bw_state * old_bw_state ,
916+ struct intel_bw_state * new_bw_state )
917+ {
918+ unsigned int data_rate = intel_bw_data_rate (i915 , new_bw_state );
919+ unsigned int num_active_planes =
920+ intel_bw_num_active_planes (i915 , new_bw_state );
921+
922+ data_rate = DIV_ROUND_UP (data_rate , 1000 );
923+
924+ return icl_find_qgv_points (i915 , data_rate , num_active_planes ,
925+ old_bw_state , new_bw_state );
926+ }
927+
806928static bool intel_bw_state_changed (struct drm_i915_private * i915 ,
807929 const struct intel_bw_state * old_bw_state ,
808930 const struct intel_bw_state * new_bw_state )
@@ -1049,20 +1171,14 @@ static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *chan
10491171
10501172int intel_bw_atomic_check (struct intel_atomic_state * state )
10511173{
1052- struct drm_i915_private * dev_priv = to_i915 (state -> base .dev );
1053- const struct intel_bw_state * old_bw_state ;
1054- struct intel_bw_state * new_bw_state ;
1055- unsigned int data_rate ;
1056- unsigned int num_active_planes ;
1057- int i , ret ;
1058- u16 qgv_points = 0 , psf_points = 0 ;
1059- unsigned int max_bw_point = 0 , max_bw = 0 ;
1060- unsigned int num_qgv_points = dev_priv -> display .bw .max [0 ].num_qgv_points ;
1061- unsigned int num_psf_gv_points = dev_priv -> display .bw .max [0 ].num_psf_gv_points ;
10621174 bool changed = false;
1175+ struct drm_i915_private * i915 = to_i915 (state -> base .dev );
1176+ struct intel_bw_state * new_bw_state ;
1177+ const struct intel_bw_state * old_bw_state ;
1178+ int ret ;
10631179
10641180 /* FIXME earlier gens need some checks too */
1065- if (DISPLAY_VER (dev_priv ) < 11 )
1181+ if (DISPLAY_VER (i915 ) < 11 )
10661182 return 0 ;
10671183
10681184 ret = intel_bw_check_data_rate (state , & changed );
@@ -1073,8 +1189,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
10731189 new_bw_state = intel_atomic_get_new_bw_state (state );
10741190
10751191 if (new_bw_state &&
1076- intel_can_enable_sagv (dev_priv , old_bw_state ) !=
1077- intel_can_enable_sagv (dev_priv , new_bw_state ))
1192+ intel_can_enable_sagv (i915 , old_bw_state ) !=
1193+ intel_can_enable_sagv (i915 , new_bw_state ))
10781194 changed = true;
10791195
10801196 /*
@@ -1084,101 +1200,10 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
10841200 if (!changed )
10851201 return 0 ;
10861202
1087- ret = intel_atomic_lock_global_state ( & new_bw_state -> base );
1203+ ret = intel_bw_check_qgv_points ( i915 , old_bw_state , new_bw_state );
10881204 if (ret )
10891205 return ret ;
10901206
1091- data_rate = intel_bw_data_rate (dev_priv , new_bw_state );
1092- data_rate = DIV_ROUND_UP (data_rate , 1000 );
1093-
1094- num_active_planes = intel_bw_num_active_planes (dev_priv , new_bw_state );
1095-
1096- for (i = 0 ; i < num_qgv_points ; i ++ ) {
1097- unsigned int max_data_rate ;
1098-
1099- if (DISPLAY_VER (dev_priv ) > 11 )
1100- max_data_rate = tgl_max_bw (dev_priv , num_active_planes , i );
1101- else
1102- max_data_rate = icl_max_bw (dev_priv , num_active_planes , i );
1103- /*
1104- * We need to know which qgv point gives us
1105- * maximum bandwidth in order to disable SAGV
1106- * if we find that we exceed SAGV block time
1107- * with watermarks. By that moment we already
1108- * have those, as it is calculated earlier in
1109- * intel_atomic_check,
1110- */
1111- if (max_data_rate > max_bw ) {
1112- max_bw_point = i ;
1113- max_bw = max_data_rate ;
1114- }
1115- if (max_data_rate >= data_rate )
1116- qgv_points |= BIT (i );
1117-
1118- drm_dbg_kms (& dev_priv -> drm , "QGV point %d: max bw %d required %d\n" ,
1119- i , max_data_rate , data_rate );
1120- }
1121-
1122- for (i = 0 ; i < num_psf_gv_points ; i ++ ) {
1123- unsigned int max_data_rate = adl_psf_bw (dev_priv , i );
1124-
1125- if (max_data_rate >= data_rate )
1126- psf_points |= BIT (i );
1127-
1128- drm_dbg_kms (& dev_priv -> drm , "PSF GV point %d: max bw %d"
1129- " required %d\n" ,
1130- i , max_data_rate , data_rate );
1131- }
1132-
1133- /*
1134- * BSpec states that we always should have at least one allowed point
1135- * left, so if we couldn't - simply reject the configuration for obvious
1136- * reasons.
1137- */
1138- if (qgv_points == 0 ) {
1139- drm_dbg_kms (& dev_priv -> drm , "No QGV points provide sufficient memory"
1140- " bandwidth %d for display configuration(%d active planes).\n" ,
1141- data_rate , num_active_planes );
1142- return - EINVAL ;
1143- }
1144-
1145- if (num_psf_gv_points > 0 && psf_points == 0 ) {
1146- drm_dbg_kms (& dev_priv -> drm , "No PSF GV points provide sufficient memory"
1147- " bandwidth %d for display configuration(%d active planes).\n" ,
1148- data_rate , num_active_planes );
1149- return - EINVAL ;
1150- }
1151-
1152- /*
1153- * Leave only single point with highest bandwidth, if
1154- * we can't enable SAGV due to the increased memory latency it may
1155- * cause.
1156- */
1157- if (!intel_can_enable_sagv (dev_priv , new_bw_state )) {
1158- qgv_points = BIT (max_bw_point );
1159- drm_dbg_kms (& dev_priv -> drm , "No SAGV, using single QGV point %d\n" ,
1160- max_bw_point );
1161- }
1162-
1163- /*
1164- * We store the ones which need to be masked as that is what PCode
1165- * actually accepts as a parameter.
1166- */
1167- new_bw_state -> qgv_points_mask =
1168- ~(ICL_PCODE_REQ_QGV_PT (qgv_points ) |
1169- ADLS_PCODE_REQ_PSF_PT (psf_points )) &
1170- icl_qgv_points_mask (dev_priv );
1171-
1172- /*
1173- * If the actual mask had changed we need to make sure that
1174- * the commits are serialized(in case this is a nomodeset, nonblocking)
1175- */
1176- if (new_bw_state -> qgv_points_mask != old_bw_state -> qgv_points_mask ) {
1177- ret = intel_atomic_serialize_global_state (& new_bw_state -> base );
1178- if (ret )
1179- return ret ;
1180- }
1181-
11821207 return 0 ;
11831208}
11841209
0 commit comments