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,
 
        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,