In xe3+, soc can lower the fabric frequency when the display needs less bandwidth than the minimum GV point. This threshold has been defined as 20GB/s. To enable this,
Add a new low bw info point with this peakbw threshold of 20GB/s based on the following conditions: 1. Only for xe3+ versions 2. There is at least one QGV point 3. Number QGV points is less than 8 4. Lowest peak bw across all the QGV point is less than 20 GB/s 5. And the derated bw is in the lowest peak bw qgv point is also less than this threshold of 20GB/s This will make the driver to send this new threshold of 20GB/s as the pmdemand request whenever the bw required for a usecase is less than 20GB/s. The current pcode can handle this lower peakbw value and adjust the fabric frequency accordingly. Bspec: 68880 Assisted-by: Copilot:claude-sonnet-4.6 Signed-off-by: Vinod Govindapillai <[email protected]> --- drivers/gpu/drm/i915/display/intel_bw.c | 54 +++++++++++++++++++ .../drm/i915/display/intel_display_device.h | 1 + 2 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 938c0294c251..747279075e29 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -54,6 +54,8 @@ struct intel_qgv_point { #define DEPROGBWPCLIMIT 60 +#define PEAK_BW_THRESHOLD 20000 + struct intel_psf_gv_point { u8 clk; /* clock in multiples of 16.6666 MHz */ }; @@ -589,6 +591,50 @@ static int icl_get_bw_info(struct intel_display *display, return 0; } +static bool xe3_check_lower_peakbw(struct intel_display *display, + const struct intel_qgv_info *qi, + int num_channels) +{ + unsigned int lowest_peakbw; + + if (!HAS_PEAK_BW_THRESHOLD(display)) + return false; + + if (qi->num_points >= I915_NUM_QGV_POINTS) { + drm_warn(display->drm, "Cannot insert lowest QGV point, not enough space\n"); + return false; + } + + lowest_peakbw = DIV_ROUND_CLOSEST(qi->points[0].dclk * + qi->channel_width * num_channels, 8); + if (lowest_peakbw <= PEAK_BW_THRESHOLD) { + drm_dbg_kms(display->drm, + "Lowest QGV point has peak BW %u MB/s, no need to insert lower point\n", + lowest_peakbw); + return false; + } + + return true; +} + +static void xe3_insert_lowest_qgv_point(struct intel_display *display, + struct intel_bw_info *bi) +{ + if (bi->num_qgv_points >= ARRAY_SIZE(bi->deratedbw)) + return; + + memmove(&bi->deratedbw[1], &bi->deratedbw[0], + bi->num_qgv_points * sizeof(*bi->deratedbw)); + + memmove(&bi->peakbw[1], &bi->peakbw[0], + bi->num_qgv_points * sizeof(*bi->peakbw)); + + /* Keep the derated bandwidth as the threshold*/ + bi->deratedbw[0] = PEAK_BW_THRESHOLD; + bi->peakbw[0] = PEAK_BW_THRESHOLD; + bi->num_qgv_points++; +} + static int tgl_get_bw_info(struct intel_display *display, const struct dram_info *dram_info, const struct intel_sa_info *sa) @@ -598,6 +644,7 @@ static int tgl_get_bw_info(struct intel_display *display, int num_channels = max_t(u8, 1, dram_info->num_channels); int ipqdepth, ipqdepthpch = 16; int dclk_max; + bool insert_low_peakbw; int maxdebw, peakbw; int clperchgroup; int num_groups = ARRAY_SIZE(display->bw.max); @@ -636,6 +683,10 @@ static int tgl_get_bw_info(struct intel_display *display, */ clperchgroup = 4 * DIV_ROUND_UP(8, num_channels) * qi.deinterleave; + insert_low_peakbw = xe3_check_lower_peakbw(display, &qi, num_channels); + + display->bw.max[i].num_planes = 0; + for (i = 0; i < num_groups; i++) { struct intel_bw_info *bi = &display->bw.max[i]; struct intel_bw_info *bi_next; @@ -678,6 +729,9 @@ static int tgl_get_bw_info(struct intel_display *display, qi.channel_width, 8); } + if (insert_low_peakbw) + xe3_insert_lowest_qgv_point(display, bi); + for (j = 0; j < qi.num_psf_points; j++) { const struct intel_psf_gv_point *sp = &qi.psf_points[j]; diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index 65283286771a..b31ec42c3248 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -192,6 +192,7 @@ struct intel_display_platforms { #define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14) #define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12) #define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay) +#define HAS_PEAK_BW_THRESHOLD(__display) (DISPLAY_VER(__display) >= 30) #define HAS_PIPEDMC(__display) (DISPLAY_VER(__display) >= 12) #define HAS_PIXEL_NORMALIZER(__display) (DISPLAY_VER(__display) >= 35) #define HAS_PMDEMAND(__display) (DISPLAY_VER(__display) >= 14) -- 2.43.0
