drm/i915: Keep sagv status updated on icl+
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 31 Jan 2023 00:21:26 +0000 (02:21 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 1 Feb 2023 20:07:03 +0000 (22:07 +0200)
On icl+ SAGV is controlled by masking of the QGV points.
Reduce the QGV point mask to the same kind of enabled vs.
disable information that we had on previous platforms.
Will be useful in answering the question whether SAGV is
actually enabled or not.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230131002127.29305-3-ville.syrjala@linux.intel.com
Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
drivers/gpu/drm/i915/display/intel_bw.c

index 1c236f0..202321f 100644 (file)
@@ -119,6 +119,32 @@ static int adls_pcode_read_psf_gv_point_info(struct drm_i915_private *dev_priv,
        return 0;
 }
 
+static u16 icl_qgv_points_mask(struct drm_i915_private *i915)
+{
+       unsigned int num_psf_gv_points = i915->display.bw.max[0].num_psf_gv_points;
+       unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
+       u16 qgv_points = 0, psf_points = 0;
+
+       /*
+        * We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects
+        * it with failure if we try masking any unadvertised points.
+        * So need to operate only with those returned from PCode.
+        */
+       if (num_qgv_points > 0)
+               qgv_points = GENMASK(num_qgv_points - 1, 0);
+
+       if (num_psf_gv_points > 0)
+               psf_points = GENMASK(num_psf_gv_points - 1, 0);
+
+       return ICL_PCODE_REQ_QGV_PT(qgv_points) | ADLS_PCODE_REQ_PSF_PT(psf_points);
+}
+
+static bool is_sagv_enabled(struct drm_i915_private *i915, u16 points_mask)
+{
+       return !is_power_of_2(~points_mask & icl_qgv_points_mask(i915) &
+                             ICL_PCODE_REQ_QGV_PT_MASK);
+}
+
 int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
                                  u32 points_mask)
 {
@@ -136,6 +162,9 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
                return ret;
        }
 
+       dev_priv->display.sagv.status = is_sagv_enabled(dev_priv, points_mask) ?
+               I915_SAGV_ENABLED : I915_SAGV_DISABLED;
+
        return 0;
 }
 
@@ -965,26 +994,6 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
        return 0;
 }
 
-static u16 icl_qgv_points_mask(struct drm_i915_private *i915)
-{
-       unsigned int num_psf_gv_points = i915->display.bw.max[0].num_psf_gv_points;
-       unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
-       u16 qgv_points = 0, psf_points = 0;
-
-       /*
-        * We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects
-        * it with failure if we try masking any unadvertised points.
-        * So need to operate only with those returned from PCode.
-        */
-       if (num_qgv_points > 0)
-               qgv_points = GENMASK(num_qgv_points - 1, 0);
-
-       if (num_psf_gv_points > 0)
-               psf_points = GENMASK(num_psf_gv_points - 1, 0);
-
-       return ICL_PCODE_REQ_QGV_PT(qgv_points) | ADLS_PCODE_REQ_PSF_PT(psf_points);
-}
-
 static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *changed)
 {
        struct drm_i915_private *i915 = to_i915(state->base.dev);