Message ID | 20240415081423.495834-14-balasubramani.vivekanandan@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Enable display support for Battlemage | expand |
LGTM, Reviewed-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com> > -----Original Message----- > From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of > Balasubramani Vivekanandan > Sent: Monday, April 15, 2024 1:14 AM > To: intel-xe@lists.freedesktop.org; intel-gfx@lists.freedesktop.org > Cc: De Marchi, Lucas <lucas.demarchi@intel.com>; Roper, Matthew D > <matthew.d.roper@intel.com>; Jani Nikula <jani.nikula@linux.intel.com>; > Vivekanandan, Balasubramani <balasubramani.vivekanandan@intel.com> > Subject: [PATCH v3 13/21] drm/i915/xe2hpd: Add max memory bandwidth > algorithm > > From: Matt Roper <matthew.d.roper@intel.com> > > 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> > --- > drivers/gpu/drm/i915/display/intel_bw.c | 65 ++++++++++++++++++++++++- > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/soc/intel_dram.c | 4 ++ > drivers/gpu/drm/xe/xe_device_types.h | 1 + > 4 files changed, 69 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_bw.c > b/drivers/gpu/drm/i915/display/intel_bw.c > index 7f2a50b4f494..dc9ac4831065 100644 > --- a/drivers/gpu/drm/i915/display/intel_bw.c > +++ b/drivers/gpu/drm/i915/display/intel_bw.c > @@ -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 */ > }; > @@ -239,6 +241,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; > @@ -383,6 +388,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 = {}; > @@ -489,7 +500,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); > /* > @@ -594,6 +605,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) > { > @@ -664,7 +723,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); > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 481ddce038b2..d1d21d433766 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -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; > diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c > b/drivers/gpu/drm/i915/soc/intel_dram.c > index 15492b69f698..99b541babb31 100644 > --- a/drivers/gpu/drm/i915/soc/intel_dram.c > +++ b/drivers/gpu/drm/i915/soc/intel_dram.c > @@ -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; > diff --git a/drivers/gpu/drm/xe/xe_device_types.h > b/drivers/gpu/drm/xe/xe_device_types.h > index 60ced5f90c2b..d1aef541d1c7 100644 > --- a/drivers/gpu/drm/xe/xe_device_types.h > +++ b/drivers/gpu/drm/xe/xe_device_types.h > @@ -487,6 +487,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; > -- > 2.25.1
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 7f2a50b4f494..dc9ac4831065 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -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 */ }; @@ -239,6 +241,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; @@ -383,6 +388,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 = {}; @@ -489,7 +500,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); /* @@ -594,6 +605,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) { @@ -664,7 +723,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); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 481ddce038b2..d1d21d433766 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -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; diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 15492b69f698..99b541babb31 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -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; diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 60ced5f90c2b..d1aef541d1c7 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -487,6 +487,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;