Commit 772933b3 authored by Matt Roper's avatar Matt Roper Committed by Radhakrishna Sripada

drm/i915/xe2hpd: Add max memory bandwidth algorithm

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: default avatarMatt Roper <matthew.d.roper@intel.com>
Signed-off-by: default avatarBalasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Reviewed-by: default avatarRadhakrishna Sripada <radhakrishna.sripada@intel.com>
Signed-off-by: default avatarRadhakrishna Sripada <radhakrishna.sripada@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240430172850.1881525-12-radhakrishna.sripada@intel.com
parent 0dffea1e
...@@ -22,6 +22,8 @@ struct intel_qgv_point { ...@@ -22,6 +22,8 @@ struct intel_qgv_point {
u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd; u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
}; };
#define DEPROGBWPCLIMIT 60
struct intel_psf_gv_point { struct intel_psf_gv_point {
u8 clk; /* clock in multiples of 16.6666 MHz */ 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, ...@@ -241,6 +243,9 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
qi->channel_width = 16; qi->channel_width = 16;
qi->deinterleave = 4; qi->deinterleave = 4;
break; break;
case INTEL_DRAM_GDDR:
qi->channel_width = 32;
break;
default: default:
MISSING_CASE(dram_info->type); MISSING_CASE(dram_info->type);
return -EINVAL; return -EINVAL;
...@@ -387,6 +392,12 @@ static const struct intel_sa_info mtl_sa_info = { ...@@ -387,6 +392,12 @@ static const struct intel_sa_info mtl_sa_info = {
.derating = 10, .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) static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa)
{ {
struct intel_qgv_info qi = {}; struct intel_qgv_info qi = {};
...@@ -493,7 +504,7 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel ...@@ -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); dclk_max = icl_sagv_max_dclk(&qi);
peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max; 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); ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
/* /*
...@@ -598,6 +609,54 @@ static void dg2_get_bw_info(struct drm_i915_private *i915) ...@@ -598,6 +609,54 @@ static void dg2_get_bw_info(struct drm_i915_private *i915)
i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; 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, static unsigned int icl_max_bw_index(struct drm_i915_private *dev_priv,
int num_planes, int qgv_point) int num_planes, int qgv_point)
{ {
...@@ -684,7 +743,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv) ...@@ -684,7 +743,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv)) if (!HAS_DISPLAY(dev_priv))
return; 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); tgl_get_bw_info(dev_priv, &mtl_sa_info);
else if (IS_DG2(dev_priv)) else if (IS_DG2(dev_priv))
dg2_get_bw_info(dev_priv); dg2_get_bw_info(dev_priv);
......
...@@ -305,6 +305,7 @@ struct drm_i915_private { ...@@ -305,6 +305,7 @@ struct drm_i915_private {
INTEL_DRAM_LPDDR4, INTEL_DRAM_LPDDR4,
INTEL_DRAM_DDR5, INTEL_DRAM_DDR5,
INTEL_DRAM_LPDDR5, INTEL_DRAM_LPDDR5,
INTEL_DRAM_GDDR,
} type; } type;
u8 num_qgv_points; u8 num_qgv_points;
u8 num_psf_gv_points; u8 num_psf_gv_points;
......
...@@ -640,6 +640,10 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915) ...@@ -640,6 +640,10 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915)
case 5: case 5:
dram_info->type = INTEL_DRAM_LPDDR3; dram_info->type = INTEL_DRAM_LPDDR3;
break; break;
case 8:
drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
dram_info->type = INTEL_DRAM_GDDR;
break;
default: default:
MISSING_CASE(val); MISSING_CASE(val);
return -EINVAL; return -EINVAL;
......
...@@ -484,6 +484,7 @@ struct xe_device { ...@@ -484,6 +484,7 @@ struct xe_device {
INTEL_DRAM_LPDDR4, INTEL_DRAM_LPDDR4,
INTEL_DRAM_DDR5, INTEL_DRAM_DDR5,
INTEL_DRAM_LPDDR5, INTEL_DRAM_LPDDR5,
INTEL_DRAM_GDDR,
} type; } type;
u8 num_qgv_points; u8 num_qgv_points;
u8 num_psf_gv_points; u8 num_psf_gv_points;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment