diff options
| author | Imre Deak <imre.deak@intel.com> | 2025-12-15 21:23:42 +0200 |
|---|---|---|
| committer | Imre Deak <imre.deak@intel.com> | 2025-12-19 16:46:30 +0200 |
| commit | 92a73fec6acdcef3f2da7b2d1d4574308ebbe975 (patch) | |
| tree | b27f93a5643efdc9aaed8be7eb70545994b14215 | |
| parent | cc1b753487bb23e5a1c96c9864d515690e15b605 (diff) | |
drm/dp: Add drm_dp_dsc_sink_slice_count_mask()
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: dri-devel@lists.freedesktop.org
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patch.msgid.link/20251215192357.172201-3-imre.deak@intel.com
| -rw-r--r-- | drivers/gpu/drm/display/drm_dp_helper.c | 82 | ||||
| -rw-r--r-- | 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 19564c1afba6..a697cc227e28 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 df2f24b950e4..85e868238e28 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]); |
