]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/i915/xe2hpd: Add max memory bandwidth algorithm
authorMatt Roper <matthew.d.roper@intel.com>
Tue, 30 Apr 2024 17:28:42 +0000 (10:28 -0700)
committerRadhakrishna Sripada <radhakrishna.sripada@intel.com>
Fri, 3 May 2024 20:15:13 +0000 (13:15 -0700)
Unlike DG2, Xe2_HPD does support multiple GV points with different
maximum memory bandwidths, but uses a much simpler algorithm than igpu
platforms use.

Bspec: 64631
CC: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Reviewed-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Signed-off-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240430172850.1881525-12-radhakrishna.sripada@intel.com
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/soc/intel_dram.c
drivers/gpu/drm/xe/xe_device_types.h

index 972ea887e23252b816dc87fe3195948fe798a79b..47036d4abb331c8a6e3ed5d4942d2b51a57e0cd8 100644 (file)
@@ -22,6 +22,8 @@ struct intel_qgv_point {
        u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
 };
 
+#define DEPROGBWPCLIMIT                60
+
 struct intel_psf_gv_point {
        u8 clk; /* clock in multiples of 16.6666 MHz */
 };
@@ -241,6 +243,9 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
                        qi->channel_width = 16;
                        qi->deinterleave = 4;
                        break;
+               case INTEL_DRAM_GDDR:
+                       qi->channel_width = 32;
+                       break;
                default:
                        MISSING_CASE(dram_info->type);
                        return -EINVAL;
@@ -387,6 +392,12 @@ static const struct intel_sa_info mtl_sa_info = {
        .derating = 10,
 };
 
+static const struct intel_sa_info xe2_hpd_sa_info = {
+       .derating = 30,
+       .deprogbwlimit = 53,
+       /* Other values not used by simplified algorithm */
+};
+
 static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa)
 {
        struct intel_qgv_info qi = {};
@@ -493,7 +504,7 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
        dclk_max = icl_sagv_max_dclk(&qi);
 
        peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max;
-       maxdebw = min(sa->deprogbwlimit * 1000, peakbw * 6 / 10); /* 60% */
+       maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100);
 
        ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
        /*
@@ -598,6 +609,54 @@ static void dg2_get_bw_info(struct drm_i915_private *i915)
        i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED;
 }
 
+static int xe2_hpd_get_bw_info(struct drm_i915_private *i915,
+                              const struct intel_sa_info *sa)
+{
+       struct intel_qgv_info qi = {};
+       int num_channels = i915->dram_info.num_channels;
+       int peakbw, maxdebw;
+       int ret, i;
+
+       ret = icl_get_qgv_points(i915, &qi, true);
+       if (ret) {
+               drm_dbg_kms(&i915->drm,
+                           "Failed to get memory subsystem information, ignoring bandwidth limits");
+               return ret;
+       }
+
+       peakbw = num_channels * qi.channel_width / 8 * icl_sagv_max_dclk(&qi);
+       maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 10);
+
+       for (i = 0; i < qi.num_points; i++) {
+               const struct intel_qgv_point *point = &qi.points[i];
+               int bw = num_channels * (qi.channel_width / 8) * point->dclk;
+
+               i915->display.bw.max[0].deratedbw[i] =
+                       min(maxdebw, (100 - sa->derating) * bw / 100);
+               i915->display.bw.max[0].peakbw[i] = bw;
+
+               drm_dbg_kms(&i915->drm, "QGV %d: deratedbw=%u peakbw: %u\n",
+                           i, i915->display.bw.max[0].deratedbw[i],
+                           i915->display.bw.max[0].peakbw[i]);
+       }
+
+       /* Bandwidth does not depend on # of planes; set all groups the same */
+       i915->display.bw.max[0].num_planes = 1;
+       i915->display.bw.max[0].num_qgv_points = qi.num_points;
+       for (i = 1; i < ARRAY_SIZE(i915->display.bw.max); i++)
+               memcpy(&i915->display.bw.max[i], &i915->display.bw.max[0],
+                      sizeof(i915->display.bw.max[0]));
+
+       /*
+        * Xe2_HPD should always have exactly two QGV points representing
+        * battery and plugged-in operation.
+        */
+       drm_WARN_ON(&i915->drm, qi.num_points != 2);
+       i915->display.sagv.status = I915_SAGV_ENABLED;
+
+       return 0;
+}
+
 static unsigned int icl_max_bw_index(struct drm_i915_private *dev_priv,
                                     int num_planes, int qgv_point)
 {
@@ -684,7 +743,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
        if (!HAS_DISPLAY(dev_priv))
                return;
 
-       if (DISPLAY_VER(dev_priv) >= 14)
+       if (DISPLAY_VER_FULL(dev_priv) >= IP_VER(14, 1) && IS_DGFX(dev_priv))
+               xe2_hpd_get_bw_info(dev_priv, &xe2_hpd_sa_info);
+       else if (DISPLAY_VER(dev_priv) >= 14)
                tgl_get_bw_info(dev_priv, &mtl_sa_info);
        else if (IS_DG2(dev_priv))
                dg2_get_bw_info(dev_priv);
index 481ddce038b2d670b4e382def64af29eb28caf8d..d1d21d433766402d76c4f0c1a64ab4d84449f2db 100644 (file)
@@ -305,6 +305,7 @@ struct drm_i915_private {
                        INTEL_DRAM_LPDDR4,
                        INTEL_DRAM_DDR5,
                        INTEL_DRAM_LPDDR5,
+                       INTEL_DRAM_GDDR,
                } type;
                u8 num_qgv_points;
                u8 num_psf_gv_points;
index e3287f1de7741dc42af9d80ba5df3b32c2f92f0e..18a879e98f03d1a3f4b3ff6b5882bba21c5e0b8b 100644 (file)
@@ -640,6 +640,10 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915)
        case 5:
                dram_info->type = INTEL_DRAM_LPDDR3;
                break;
+       case 8:
+               drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
+               dram_info->type = INTEL_DRAM_GDDR;
+               break;
        default:
                MISSING_CASE(val);
                return -EINVAL;
index 2e62450d86e1852316ef2969a58d4198f22bccb1..14144a3814fcc087570de49844cd6ae4aa4b6b15 100644 (file)
@@ -484,6 +484,7 @@ struct xe_device {
                        INTEL_DRAM_LPDDR4,
                        INTEL_DRAM_DDR5,
                        INTEL_DRAM_LPDDR5,
+                       INTEL_DRAM_GDDR,
                } type;
                u8 num_qgv_points;
                u8 num_psf_gv_points;