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.
