On Thu, 2025-11-27 at 19:49 +0200, Imre Deak wrote:
> A DSC sink supporting DSC slice count N, not necessarily supports slice
> counts less than N. Hence the driver should check the sink's support for
> a particular slice count before using that slice count. Add the helper
> functions required for this.
> 
> Cc: [email protected]
> Signed-off-by: Imre Deak <[email protected]>
> ---
>  drivers/gpu/drm/display/drm_dp_helper.c | 82 +++++++++++++++++--------
>  include/drm/display/drm_dp_helper.h     |  3 +
>  2 files changed, 61 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c 
> b/drivers/gpu/drm/display/drm_dp_helper.c
> index 19564c1afba6c..a697cc227e289 100644
> --- a/drivers/gpu/drm/display/drm_dp_helper.c
> +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> @@ -2705,56 +2705,90 @@ u8 drm_dp_dsc_sink_bpp_incr(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
>  EXPORT_SYMBOL(drm_dp_dsc_sink_bpp_incr);
>  
>  /**
> - * drm_dp_dsc_sink_max_slice_count() - Get the max slice count
> - * supported by the DSC sink.
> - * @dsc_dpcd: DSC capabilities from DPCD
> - * @is_edp: true if its eDP, false for DP
> + * drm_dp_dsc_slice_count_to_mask() - Convert a slice count to a slice count 
> mask
> + * @slice_count: slice count
>   *
> - * Read the slice capabilities DPCD register from DSC sink to get
> - * the maximum slice count supported. This is used to populate
> - * the DSC parameters in the &struct drm_dsc_config by the driver.
> - * Driver creates an infoframe using these parameters to populate
> - * &struct drm_dsc_pps_infoframe. These are sent to the sink using DSC
> - * infoframe using the helper function drm_dsc_pps_infoframe_pack()
> + * Convert @slice_count to a slice count mask.
> + *
> + * Returns the slice count mask.
> + */
> +u32 drm_dp_dsc_slice_count_to_mask(int slice_count)
> +{
> +     return BIT(slice_count - 1);
> +}
> +EXPORT_SYMBOL(drm_dp_dsc_slice_count_to_mask);
> +
> +/**
> + * drm_dp_dsc_sink_slice_count_mask() - Get the mask of valid DSC sink slice 
> counts
> + * @dsc_dpcd: the sink's DSC DPCD capabilities
> + * @is_edp: %true for an eDP sink
> + *
> + * Get the mask of supported slice counts from the sink's DSC DPCD register.
>   *
>   * Returns:
> - * Maximum slice count supported by DSC sink or 0 its invalid
> + * Mask of slice counts supported by the DSC sink:
> + * - > 0: bit#0,1,3,5..,23 set if the sink supports 1,2,4,6..,24 slices
> + * - 0:   if the sink doesn't support any slices
>   */
> -u8 drm_dp_dsc_sink_max_slice_count(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> -                                bool is_edp)
> +u32 drm_dp_dsc_sink_slice_count_mask(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> +                                  bool is_edp)
>  {
>       u8 slice_cap1 = dsc_dpcd[DP_DSC_SLICE_CAP_1 - DP_DSC_SUPPORT];
> +     u32 mask = 0;
>  
>       if (!is_edp) {
>               /* For DP, use values from DSC_SLICE_CAP_1 and DSC_SLICE_CAP2 */
>               u8 slice_cap2 = dsc_dpcd[DP_DSC_SLICE_CAP_2 - DP_DSC_SUPPORT];
>  
>               if (slice_cap2 & DP_DSC_24_PER_DP_DSC_SINK)
> -                     return 24;
> +                     mask |= drm_dp_dsc_slice_count_to_mask(24);
>               if (slice_cap2 & DP_DSC_20_PER_DP_DSC_SINK)
> -                     return 20;
> +                     mask |= drm_dp_dsc_slice_count_to_mask(20);
>               if (slice_cap2 & DP_DSC_16_PER_DP_DSC_SINK)
> -                     return 16;
> +                     mask |= drm_dp_dsc_slice_count_to_mask(16);
>       }
>  
>       /* DP, eDP v1.5+ */
>       if (slice_cap1 & DP_DSC_12_PER_DP_DSC_SINK)
> -             return 12;
> +             mask |= drm_dp_dsc_slice_count_to_mask(12);
>       if (slice_cap1 & DP_DSC_10_PER_DP_DSC_SINK)
> -             return 10;
> +             mask |= drm_dp_dsc_slice_count_to_mask(10);
>       if (slice_cap1 & DP_DSC_8_PER_DP_DSC_SINK)
> -             return 8;
> +             mask |= drm_dp_dsc_slice_count_to_mask(8);
>       if (slice_cap1 & DP_DSC_6_PER_DP_DSC_SINK)
> -             return 6;
> +             mask |= drm_dp_dsc_slice_count_to_mask(6);
>       /* DP, eDP v1.4+ */
>       if (slice_cap1 & DP_DSC_4_PER_DP_DSC_SINK)
> -             return 4;
> +             mask |= drm_dp_dsc_slice_count_to_mask(4);
>       if (slice_cap1 & DP_DSC_2_PER_DP_DSC_SINK)
> -             return 2;
> +             mask |= drm_dp_dsc_slice_count_to_mask(2);
>       if (slice_cap1 & DP_DSC_1_PER_DP_DSC_SINK)
> -             return 1;
> +             mask |= drm_dp_dsc_slice_count_to_mask(1);
>  
> -     return 0;
> +     return mask;
> +}
> +EXPORT_SYMBOL(drm_dp_dsc_sink_slice_count_mask);
> +
> +/**
> + * drm_dp_dsc_sink_max_slice_count() - Get the max slice count
> + * supported by the DSC sink.
> + * @dsc_dpcd: DSC capabilities from DPCD
> + * @is_edp: true if its eDP, false for DP
> + *
> + * Read the slice capabilities DPCD register from DSC sink to get
> + * the maximum slice count supported. This is used to populate
> + * the DSC parameters in the &struct drm_dsc_config by the driver.
> + * Driver creates an infoframe using these parameters to populate
> + * &struct drm_dsc_pps_infoframe. These are sent to the sink using DSC
> + * infoframe using the helper function drm_dsc_pps_infoframe_pack()
> + *
> + * Returns:
> + * Maximum slice count supported by DSC sink or 0 its invalid
> + */
> +u8 drm_dp_dsc_sink_max_slice_count(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> +                                bool is_edp)
> +{
> +     return fls(drm_dp_dsc_sink_slice_count_mask(dsc_dpcd, is_edp));
>  }
>  EXPORT_SYMBOL(drm_dp_dsc_sink_max_slice_count);
>  
> diff --git a/include/drm/display/drm_dp_helper.h 
> b/include/drm/display/drm_dp_helper.h
> index df2f24b950e4c..85e868238e287 100644
> --- a/include/drm/display/drm_dp_helper.h
> +++ b/include/drm/display/drm_dp_helper.h
> @@ -206,6 +206,9 @@ drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
>  
>  /* DP/eDP DSC support */
>  u8 drm_dp_dsc_sink_bpp_incr(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]);
> +u32 drm_dp_dsc_slice_count_to_mask(int slice_count);
> +u32 drm_dp_dsc_sink_slice_count_mask(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> +                                  bool is_edp);
>  u8 drm_dp_dsc_sink_max_slice_count(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
>                                  bool is_edp);
>  u8 drm_dp_dsc_sink_line_buf_depth(const u8 
> dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]);

Reviewed-by: Luca Coelho <[email protected]>

--
Cheers,
Luca.

Reply via email to