drm/i915/mtl: find the best QGV point for the SAGV configuration
authorVinod Govindapillai <vinod.govindapillai@intel.com>
Tue, 6 Jun 2023 09:35:08 +0000 (12:35 +0300)
committerRadhakrishna Sripada <radhakrishna.sripada@intel.com>
Wed, 7 Jun 2023 18:24:40 +0000 (11:24 -0700)
From MTL onwards, we need to find the best QGV point based on
the required data rate and pass the peak BW of that point to
the punit to lock the corresponding QGV point.

v1: Fix for warning from kernel test robot

v2: No need to serialize for the peakbw change as pmdemand code
    will do that (Imre)

Bspec: 64636

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/r/202305280253.Ab8bRV2w-lkp@intel.com/
Reported-by: Dan Carpenter <error27@gmail.com>
Closes: https://lore.kernel.org/r/202305280253.Ab8bRV2w-lkp@intel.com/
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230606093509.221709-7-vinod.govindapillai@intel.com
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/display/intel_bw.h

index b1cbeda..bef96db 100644 (file)
@@ -803,6 +803,77 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state)
        return to_intel_bw_state(bw_state);
 }
 
+static int mtl_find_qgv_points(struct drm_i915_private *i915,
+                              unsigned int data_rate,
+                              unsigned int num_active_planes,
+                              struct intel_bw_state *new_bw_state)
+{
+       unsigned int best_rate = UINT_MAX;
+       unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
+       unsigned int qgv_peak_bw  = 0;
+       int i;
+       int ret;
+
+       ret = intel_atomic_lock_global_state(&new_bw_state->base);
+       if (ret)
+               return ret;
+
+       /*
+        * If SAGV cannot be enabled, disable the pcode SAGV by passing all 1's
+        * for qgv peak bw in PM Demand request. So assign UINT_MAX if SAGV is
+        * not enabled. PM Demand code will clamp the value for the register
+        */
+       if (!intel_can_enable_sagv(i915, new_bw_state)) {
+               new_bw_state->qgv_point_peakbw = U16_MAX;
+               drm_dbg_kms(&i915->drm, "No SAGV, use UINT_MAX as peak bw.");
+               return 0;
+       }
+
+       /*
+        * Find the best QGV point by comparing the data_rate with max data rate
+        * offered per plane group
+        */
+       for (i = 0; i < num_qgv_points; i++) {
+               unsigned int bw_index =
+                       tgl_max_bw_index(i915, num_active_planes, i);
+               unsigned int max_data_rate;
+
+               if (bw_index >= ARRAY_SIZE(i915->display.bw.max))
+                       continue;
+
+               max_data_rate = i915->display.bw.max[bw_index].deratedbw[i];
+
+               if (max_data_rate < data_rate)
+                       continue;
+
+               if (max_data_rate - data_rate < best_rate) {
+                       best_rate = max_data_rate - data_rate;
+                       qgv_peak_bw = i915->display.bw.max[bw_index].peakbw[i];
+               }
+
+               drm_dbg_kms(&i915->drm, "QGV point %d: max bw %d required %d qgv_peak_bw: %d\n",
+                           i, max_data_rate, data_rate, qgv_peak_bw);
+       }
+
+       drm_dbg_kms(&i915->drm, "Matching peaks QGV bw: %d for required data rate: %d\n",
+                   qgv_peak_bw, data_rate);
+
+       /*
+        * The display configuration cannot be supported if no QGV point
+        * satisfying the required data rate is found
+        */
+       if (qgv_peak_bw == 0) {
+               drm_dbg_kms(&i915->drm, "No QGV points for bw %d for display configuration(%d active planes).\n",
+                           data_rate, num_active_planes);
+               return -EINVAL;
+       }
+
+       /* MTL PM DEMAND expects QGV BW parameter in multiples of 100 mbps */
+       new_bw_state->qgv_point_peakbw = DIV_ROUND_CLOSEST(qgv_peak_bw, 100);
+
+       return 0;
+}
+
 static int icl_find_qgv_points(struct drm_i915_private *i915,
                               unsigned int data_rate,
                               unsigned int num_active_planes,
@@ -928,8 +999,12 @@ static int intel_bw_check_qgv_points(struct drm_i915_private *i915,
 
        data_rate = DIV_ROUND_UP(data_rate, 1000);
 
-       return icl_find_qgv_points(i915, data_rate, num_active_planes,
-                                  old_bw_state, new_bw_state);
+       if (DISPLAY_VER(i915) >= 14)
+               return mtl_find_qgv_points(i915, data_rate, num_active_planes,
+                                          new_bw_state);
+       else
+               return icl_find_qgv_points(i915, data_rate, num_active_planes,
+                                          old_bw_state, new_bw_state);
 }
 
 static bool intel_bw_state_changed(struct drm_i915_private *i915,
index f202921..59cb4fc 100644 (file)
@@ -35,6 +35,12 @@ struct intel_bw_state {
        u8 active_pipes;
 
        /*
+        * From MTL onwards, to lock a QGV point, punit expects the peak BW of
+        * the selected QGV point as the parameter in multiples of 100MB/s
+        */
+       u16 qgv_point_peakbw;
+
+       /*
         * Current QGV points mask, which restricts
         * some particular SAGV states, not to confuse
         * with pipe_sagv_mask.