On Thu, 2025-11-27 at 19:50 +0200, Imre Deak wrote:
> Atm, a DP DSC video mode's required BW vs. the available BW is
> determined by calculating the maximum compressed BPP value allowed by
> the available BW. Doing that using a closed-form formula as it's done
> atm (vs. an iterative way) is problematic, since the overhead of the
> required BW itself depends on the BPP value being calculated. Instead
> of
> that calculate the required BW for the minimum compressed BPP value
> supported both by the source and the sink and check this BW against
> the
> available BW. This change also aligns the BW calculation during mode
> validation with how this is done during state computation,
> calculating
> the required effective data rate with the corresponding BW overhead.
> 
> Signed-off-by: Imre Deak <[email protected]>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 137 ++++------------------
> --
>  drivers/gpu/drm/i915/display/intel_dp.h |   8 --
>  2 files changed, 18 insertions(+), 127 deletions(-)
> 

Reviewed-by: Vinod Govindapillai <[email protected]>

> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index b40edf4febcb7..8b601994bb138 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -895,49 +895,6 @@ static int align_max_vesa_compressed_bpp_x16(int
> max_link_bpp_x16)
>       return 0;
>  }
>  
> -static u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display
> *display, u32 bpp, u32 pipe_bpp)
> -{
> -     u32 bits_per_pixel = bpp;
> -
> -     /* Error out if the max bpp is less than smallest allowed
> valid bpp */
> -     if (bits_per_pixel < valid_dsc_bpp[0]) {
> -             drm_dbg_kms(display->drm, "Unsupported BPP %u, min
> %u\n",
> -                         bits_per_pixel, valid_dsc_bpp[0]);
> -             return 0;
> -     }
> -
> -     /* From XE_LPD onwards we support from bpc upto uncompressed
> bpp-1 BPPs */
> -     if (DISPLAY_VER(display) >= 13) {
> -             bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
> -
> -             /*
> -              * According to BSpec, 27 is the max DSC output bpp,
> -              * 8 is the min DSC output bpp.
> -              * While we can still clamp higher bpp values to 27,
> saving bandwidth,
> -              * if it is required to oompress up to bpp < 8,
> means we can't do
> -              * that and probably means we can't fit the required
> mode, even with
> -              * DSC enabled.
> -              */
> -             if (bits_per_pixel < 8) {
> -                     drm_dbg_kms(display->drm,
> -                                 "Unsupported BPP %u, min 8\n",
> -                                 bits_per_pixel);
> -                     return 0;
> -             }
> -             bits_per_pixel = min_t(u32, bits_per_pixel, 27);
> -     } else {
> -             int link_bpp_x16 = fxp_q4_from_int(bits_per_pixel);
> -
> -             /* Find the nearest match in the array of known BPPs
> from VESA */
> -             link_bpp_x16 =
> align_max_vesa_compressed_bpp_x16(link_bpp_x16);
> -
> -             drm_WARN_ON(display->drm,
> fxp_q4_to_frac(link_bpp_x16));
> -             bits_per_pixel = fxp_q4_to_int(link_bpp_x16);
> -     }
> -
> -     return bits_per_pixel;
> -}
> -
>  static int bigjoiner_interface_bits(struct intel_display *display)
>  {
>       return DISPLAY_VER(display) >= 14 ? 36 : 24;
> @@ -1001,64 +958,6 @@ u32 get_max_compressed_bpp_with_joiner(struct
> intel_display *display,
>       return max_bpp;
>  }
>  
> -/* TODO: return a bpp_x16 value */
> -u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display
> *display,
> -                                     u32 link_clock, u32
> lane_count,
> -                                     u32 mode_clock, u32
> mode_hdisplay,
> -                                     int num_joined_pipes,
> -                                     enum intel_output_format
> output_format,
> -                                     u32 pipe_bpp,
> -                                     u32 timeslots)
> -{
> -     u32 bits_per_pixel, joiner_max_bpp;
> -
> -     /*
> -      * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
> -      * (LinkSymbolClock)* 8 * (TimeSlots / 64)
> -      * for SST -> TimeSlots is 64(i.e all TimeSlots that are
> available)
> -      * for MST -> TimeSlots has to be calculated, based on mode
> requirements
> -      *
> -      * Due to FEC overhead, the available bw is reduced to
> 97.2261%.
> -      * To support the given mode:
> -      * Bandwidth required should be <= Available link Bandwidth
> * FEC Overhead
> -      * =>ModeClock * bits_per_pixel <= Available Link Bandwidth
> * FEC Overhead
> -      * =>bits_per_pixel <= Available link Bandwidth * FEC
> Overhead / ModeClock
> -      * =>bits_per_pixel <= (NumberOfLanes * LinkSymbolClock) * 8
> (TimeSlots / 64) /
> -      *                     (ModeClock / FEC Overhead)
> -      * =>bits_per_pixel <= (NumberOfLanes * LinkSymbolClock *
> TimeSlots) /
> -      *                     (ModeClock / FEC Overhead * 8)
> -      */
> -     bits_per_pixel = ((link_clock * lane_count) * timeslots) /
> -                      (intel_dp_mode_to_fec_clock(mode_clock) *
> 8);
> -
> -     /* Bandwidth required for 420 is half, that of 444 format */
> -     if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
> -             bits_per_pixel *= 2;
> -
> -     /*
> -      * According to DSC 1.2a Section 4.1.1 Table 4.1 the maximum
> -      * supported PPS value can be 63.9375 and with the further
> -      * mention that for 420, 422 formats, bpp should be
> programmed double
> -      * the target bpp restricting our target bpp to be 31.9375
> at max.
> -      */
> -     if (output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
> -             bits_per_pixel = min_t(u32, bits_per_pixel, 31);
> -
> -     drm_dbg_kms(display->drm, "Max link bpp is %u for %u
> timeslots "
> -                             "total bw %u pixel clock %u\n",
> -                             bits_per_pixel, timeslots,
> -                             (link_clock * lane_count * 8),
> -
>                               intel_dp_mode_to_fec_clock(mode_clock));
> -
> -     joiner_max_bpp = get_max_compressed_bpp_with_joiner(display,
> mode_clock,
> -                                                        
> mode_hdisplay, num_joined_pipes);
> -     bits_per_pixel = min(bits_per_pixel, joiner_max_bpp);
> -
> -     bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(display,
> bits_per_pixel, pipe_bpp);
> -
> -     return bits_per_pixel;
> -}
> -
>  u8 intel_dp_dsc_get_slice_count(const struct intel_connector
> *connector,
>                               int mode_clock, int mode_hdisplay,
>                               int num_joined_pipes)
> @@ -2707,26 +2606,26 @@ bool intel_dp_mode_valid_with_dsc(struct
> intel_connector *connector,
>                                 enum intel_output_format
> output_format,
>                                 int pipe_bpp, unsigned long
> bw_overhead_flags)
>  {
> -     struct intel_display *display = to_intel_display(connector);
> -     int dsc_max_compressed_bpp;
> -     int dsc_slice_count;
> +     struct intel_dp *intel_dp = intel_attached_dp(connector);
> +     int min_bpp_x16 = compute_min_compressed_bpp_x16(connector,
> output_format);
> +     int max_bpp_x16 = compute_max_compressed_bpp_x16(connector,
> +                                                      mode_clock,
> mode_hdisplay,
> +                                                     
> num_joined_pipes,
> +                                                     
> output_format,
> +                                                      pipe_bpp,
> INT_MAX);
> +     int dsc_slice_count =
> intel_dp_dsc_get_slice_count(connector,
> +                                                       
> mode_clock,
> +                                                       
> mode_hdisplay,
> +                                                       
> num_joined_pipes);
>  
> -     dsc_max_compressed_bpp =
> -             intel_dp_dsc_get_max_compressed_bpp(display,
> -                                                 link_clock,
> -                                                 lane_count,
> -                                                 mode_clock,
> -                                                 mode_hdisplay,
> -                                                
> num_joined_pipes,
> -                                                 output_format,
> -                                                 pipe_bpp, 64);
> -     dsc_slice_count =
> -             intel_dp_dsc_get_slice_count(connector,
> -                                          mode_clock,
> -                                          mode_hdisplay,
> -                                          num_joined_pipes);
> +     if (min_bpp_x16 <= 0 || min_bpp_x16 > max_bpp_x16)
> +             return false;
>  
> -     return dsc_max_compressed_bpp && dsc_slice_count;
> +     return is_bw_sufficient_for_dsc_config(intel_dp,
> +                                            link_clock,
> lane_count,
> +                                            mode_clock,
> mode_hdisplay,
> +                                            dsc_slice_count,
> min_bpp_x16,
> +                                            bw_overhead_flags);
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h
> b/drivers/gpu/drm/i915/display/intel_dp.h
> index 0ec7baec7a8e8..25bfbfd291b0a 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -143,14 +143,6 @@ bool intel_digital_port_connected(struct
> intel_encoder *encoder);
>  bool intel_digital_port_connected_locked(struct intel_encoder
> *encoder);
>  int intel_dp_dsc_compute_max_bpp(const struct intel_connector
> *connector,
>                                u8 dsc_max_bpc);
> -u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display
> *display,
> -                                     u32 link_clock, u32
> lane_count,
> -                                     u32 mode_clock, u32
> mode_hdisplay,
> -                                     int num_joined_pipes,
> -                                     enum intel_output_format
> output_format,
> -                                     u32 pipe_bpp,
> -                                     u32 timeslots);
> -
>  bool intel_dp_mode_valid_with_dsc(struct intel_connector *connector,
>                                 int link_clock, int lane_count,
>                                 int mode_clock, int mode_hdisplay,

Reply via email to