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

Reply via email to