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: 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
This commit is contained in:
committed by
Radhakrishna Sripada
parent
0dffea1e2d
commit
772933b3ab
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user