[PATCH 12/14] drm/i915/dp: Clamp PCON DSC bpp to the FRL link bandwidth

Ankit Nautiyal <[email protected]> Thu, 30 Jul 2026 16:22:24 +0530
Newsgroups org.freedesktop.lists.intel-gfx,org.freedesktop.lists.intel-xe
Message-ID <[email protected]>
While configuring the PCON DSC encoder, intel_hdmi_dsc_get_bpp() picks
the highest compressed bpp that fits the sink's per-scanline chunk-bytes
limit. However it does not account for the FRL link bandwidth, so the
selected bpp can end up exceeding what the trained PCON/sink FRL link can
actually carry.

Compute the maximum compressed bpp that the FRL bandwidth can carry and
pass it down to intel_hdmi_dsc_get_bpp() as an upper bound, so the chosen
DSC bpp stays within both the sink's chunk-bytes limit and the FRL link
budget. The mode_valid/compute phase already guarantees the lowest
compressed bpp fits the FRL bandwidth, so this cap never falls below the
minimum allowed bpp.

Signed-off-by: Ankit Nautiyal <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_dp.c   | 9 ++++++++-
 drivers/gpu/drm/i915/display/intel_hdmi.c | 8 +++++++-
 drivers/gpu/drm/i915/display/intel_hdmi.h | 3 ++-
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ff74a3dd3524..c316ff40d22d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4430,10 +4430,17 @@ intel_dp_pcon_dsc_enc_bpp(struct intel_dp *intel_dp,
 	int hdmi_max_chunk_bytes =
 		info->hdmi.dsc_cap.total_chunk_kbytes * 1024;
 	int bpc = crtc_state->pipe_bpp / 3;
+	int clock = crtc_state->hw.adjusted_mode.clock;
+	int max_frl_bw, max_frl_bpp;
+
+	max_frl_bw = min(intel_dp->dfp.pcon_max_frl_bw,
+			 intel_dp_hdmi_sink_max_frl(intel_dp)) * 1000000;
+
+	max_frl_bpp = clock ? max_frl_bw / clock : 0;
 
 	return intel_hdmi_dsc_get_bpp(pcon_fractional_bpp, slice_width,
 				      num_slices, output_format, bpc, hdmi_all_bpp,
-				      hdmi_max_chunk_bytes);
+				      hdmi_max_chunk_bytes, max_frl_bpp);
 }
 
 void
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index c26a3d0b2d2e..95393ec5d561 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -3452,13 +3452,15 @@ get_dsc_compressed_bpp(int num_slices, int slice_width, int hdmi_max_chunk_bytes
  * @bpc: bits per color
  * @hdmi_all_bpp: sink supports decoding of 1/16th bpp setting
  * @hdmi_max_chunk_bytes: max bytes in a line of chunks supported by sink
+ * @max_link_dsc_bpp: max compressed bpp the link bandwidth can carry, or 0 if not limited
  *
  * @return: compressed bits_per_pixel in step of 1/16 of bits_per_pixel
  */
 int
 intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width, int num_slices,
 		       enum intel_output_format output_format, int bpc,
-		       bool hdmi_all_bpp, int hdmi_max_chunk_bytes)
+		       bool hdmi_all_bpp, int hdmi_max_chunk_bytes,
+		       int max_link_dsc_bpp)
 {
 	int max_dsc_bpp, min_dsc_bpp;
 	int dsc_bpp_x16;
@@ -3466,6 +3468,10 @@ intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width, int num_slices,
 	intel_hdmi_dsc_get_min_max_bpp(output_format, bpc, hdmi_all_bpp,
 				       &min_dsc_bpp, &max_dsc_bpp);
 
+	/* Limit the bpp to what the link bandwidth can carry */
+	if (max_link_dsc_bpp)
+		max_dsc_bpp = min(max_dsc_bpp, max_link_dsc_bpp);
+
 	dsc_bpp_x16 = get_dsc_compressed_bpp(num_slices, slice_width,
 					     hdmi_max_chunk_bytes,
 					     src_fractional_bpp,
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index e7d0cd5bc293..072c8d228697 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -56,7 +56,8 @@ bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,
 int intel_hdmi_tmds_clock(int clock, int bpc, enum intel_output_format sink_format);
 int intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width,
 			   int num_slices, enum intel_output_format output_format,
-			   int bpc, bool hdmi_all_bpp, int hdmi_max_chunk_bytes);
+			   int bpc, bool hdmi_all_bpp, int hdmi_max_chunk_bytes,
+			   int max_link_dsc_bpp);
 void intel_hdmi_dsc_get_min_max_bpp(enum intel_output_format output_format, u8 bpc,
 				    bool hdmi_all_bpp, int *min_dsc_bpp, int *max_dsc_bpp);
 bool intel_hdmi_dsc_bpp_fits_chunk_bytes(int bpp, int num_slices, int slice_width,
-- 
2.50.1