Skip to content

Commit c1d6a22

Browse files
committed
drm/dp: Add helpers to calculate the link BW overhead
Add helpers drivers can use to calculate the BW allocation overhead - due to SSC, FEC, DSC and data alignment on symbol cycles - and the channel coding efficiency - due to the 8b/10b, 128b/132b encoding. On 128b/132b links the FEC overhead is part of the coding efficiency, so not accounted for in the BW allocation overhead. The drivers can use these functions to calculate a ratio, controlling the stream symbol insertion rate of the source device in each SST TU or MST MTP frame. Drivers can calculate this m/n = (pixel_data_rate * drm_dp_bw_overhead()) / (link_data_rate * drm_dp_bw_channel_coding_efficiency()) ratio for a given link and pixel stream and with that the slots_per_mtp = CEIL(64 * m / n) allocated slots per MTP for the stream in a link frame and with that the pbn = slots_per_mtp * drm_mst_get_pbn_divider() allocated PBNs for the stream on the MST link path. Take drm_dp_bw_overhead() into use in drm_dp_calc_pbn_mode(), for drivers calculating the PBN value directly. v2: - Add dockbook description to drm_dp_bw_channel_coding_efficiency(). (LKP). - Clarify the way m/n ratio is calculated in the commit log. v3: - Fix compile breakage for !CONFIG_BACKLIGHT_CLASS_DEVICE. (LKP) - Account for FEC_PM overhead (+ 0.0015625 %), add comment with the formula to calculate the total FEC overhead. (Ville) v4: - Rename DRM_DP_OVERHEAD_SSC to DRM_DP_OVERHEAD_SSC_REF_CLK. (Ville) v5: - Clarify in the commit log what MTP means. - Simplify the commit log's formula to calculate PBN. Cc: Lyude Paul <[email protected]> Cc: Ville Syrjälä <[email protected]> Cc: kernel test robot <[email protected]> Cc: [email protected] Reviewed-by: Stanislav Lisovskiy <[email protected]> (v2) Acked-by: Maxime Ripard <[email protected]> Reviewed-by: Lyude Paul <[email protected]> Signed-off-by: Imre Deak <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent a6315ec commit c1d6a22

File tree

3 files changed

+160
-6
lines changed

3 files changed

+160
-6
lines changed

drivers/gpu/drm/display/drm_dp_helper.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3897,3 +3897,135 @@ int drm_panel_dp_aux_backlight(struct drm_panel *panel, struct drm_dp_aux *aux)
38973897
EXPORT_SYMBOL(drm_panel_dp_aux_backlight);
38983898

38993899
#endif
3900+
3901+
/* See DP Standard v2.1 2.6.4.4.1.1, 2.8.4.4, 2.8.7 */
3902+
static int drm_dp_link_symbol_cycles(int lane_count, int pixels, int bpp_x16,
3903+
int symbol_size, bool is_mst)
3904+
{
3905+
int cycles = DIV_ROUND_UP(pixels * bpp_x16, 16 * symbol_size * lane_count);
3906+
int align = is_mst ? 4 / lane_count : 1;
3907+
3908+
return ALIGN(cycles, align);
3909+
}
3910+
3911+
static int drm_dp_link_dsc_symbol_cycles(int lane_count, int pixels, int slice_count,
3912+
int bpp_x16, int symbol_size, bool is_mst)
3913+
{
3914+
int slice_pixels = DIV_ROUND_UP(pixels, slice_count);
3915+
int slice_data_cycles = drm_dp_link_symbol_cycles(lane_count, slice_pixels,
3916+
bpp_x16, symbol_size, is_mst);
3917+
int slice_eoc_cycles = is_mst ? 4 / lane_count : 1;
3918+
3919+
return slice_count * (slice_data_cycles + slice_eoc_cycles);
3920+
}
3921+
3922+
/**
3923+
* drm_dp_bw_overhead - Calculate the BW overhead of a DP link stream
3924+
* @lane_count: DP link lane count
3925+
* @hactive: pixel count of the active period in one scanline of the stream
3926+
* @dsc_slice_count: DSC slice count if @flags/DRM_DP_LINK_BW_OVERHEAD_DSC is set
3927+
* @bpp_x16: bits per pixel in .4 binary fixed point
3928+
* @flags: DRM_DP_OVERHEAD_x flags
3929+
*
3930+
* Calculate the BW allocation overhead of a DP link stream, depending
3931+
* on the link's
3932+
* - @lane_count
3933+
* - SST/MST mode (@flags / %DRM_DP_OVERHEAD_MST)
3934+
* - symbol size (@flags / %DRM_DP_OVERHEAD_UHBR)
3935+
* - FEC mode (@flags / %DRM_DP_OVERHEAD_FEC)
3936+
* - SSC/REF_CLK mode (@flags / %DRM_DP_OVERHEAD_SSC_REF_CLK)
3937+
* as well as the stream's
3938+
* - @hactive timing
3939+
* - @bpp_x16 color depth
3940+
* - compression mode (@flags / %DRM_DP_OVERHEAD_DSC).
3941+
* Note that this overhead doesn't account for the 8b/10b, 128b/132b
3942+
* channel coding efficiency, for that see
3943+
* @drm_dp_link_bw_channel_coding_efficiency().
3944+
*
3945+
* Returns the overhead as 100% + overhead% in 1ppm units.
3946+
*/
3947+
int drm_dp_bw_overhead(int lane_count, int hactive,
3948+
int dsc_slice_count,
3949+
int bpp_x16, unsigned long flags)
3950+
{
3951+
int symbol_size = flags & DRM_DP_BW_OVERHEAD_UHBR ? 32 : 8;
3952+
bool is_mst = flags & DRM_DP_BW_OVERHEAD_MST;
3953+
u32 overhead = 1000000;
3954+
int symbol_cycles;
3955+
3956+
/*
3957+
* DP Standard v2.1 2.6.4.1
3958+
* SSC downspread and ref clock variation margin:
3959+
* 5300ppm + 300ppm ~ 0.6%
3960+
*/
3961+
if (flags & DRM_DP_BW_OVERHEAD_SSC_REF_CLK)
3962+
overhead += 6000;
3963+
3964+
/*
3965+
* DP Standard v2.1 2.6.4.1.1, 3.5.1.5.4:
3966+
* FEC symbol insertions for 8b/10b channel coding:
3967+
* After each 250 data symbols on 2-4 lanes:
3968+
* 250 LL + 5 FEC_PARITY_PH + 1 CD_ADJ (256 byte FEC block)
3969+
* After each 2 x 250 data symbols on 1 lane:
3970+
* 2 * 250 LL + 11 FEC_PARITY_PH + 1 CD_ADJ (512 byte FEC block)
3971+
* After 256 (2-4 lanes) or 128 (1 lane) FEC blocks:
3972+
* 256 * 256 bytes + 1 FEC_PM
3973+
* or
3974+
* 128 * 512 bytes + 1 FEC_PM
3975+
* (256 * 6 + 1) / (256 * 250) = 2.4015625 %
3976+
*/
3977+
if (flags & DRM_DP_BW_OVERHEAD_FEC)
3978+
overhead += 24016;
3979+
3980+
/*
3981+
* DP Standard v2.1 2.7.9, 5.9.7
3982+
* The FEC overhead for UHBR is accounted for in its 96.71% channel
3983+
* coding efficiency.
3984+
*/
3985+
WARN_ON((flags & DRM_DP_BW_OVERHEAD_UHBR) &&
3986+
(flags & DRM_DP_BW_OVERHEAD_FEC));
3987+
3988+
if (flags & DRM_DP_BW_OVERHEAD_DSC)
3989+
symbol_cycles = drm_dp_link_dsc_symbol_cycles(lane_count, hactive,
3990+
dsc_slice_count,
3991+
bpp_x16, symbol_size,
3992+
is_mst);
3993+
else
3994+
symbol_cycles = drm_dp_link_symbol_cycles(lane_count, hactive,
3995+
bpp_x16, symbol_size,
3996+
is_mst);
3997+
3998+
return DIV_ROUND_UP_ULL(mul_u32_u32(symbol_cycles * symbol_size * lane_count,
3999+
overhead * 16),
4000+
hactive * bpp_x16);
4001+
}
4002+
EXPORT_SYMBOL(drm_dp_bw_overhead);
4003+
4004+
/**
4005+
* drm_dp_bw_channel_coding_efficiency - Get a DP link's channel coding efficiency
4006+
* @is_uhbr: Whether the link has a 128b/132b channel coding
4007+
*
4008+
* Return the channel coding efficiency of the given DP link type, which is
4009+
* either 8b/10b or 128b/132b (aka UHBR). The corresponding overhead includes
4010+
* the 8b -> 10b, 128b -> 132b pixel data to link symbol conversion overhead
4011+
* and for 128b/132b any link or PHY level control symbol insertion overhead
4012+
* (LLCP, FEC, PHY sync, see DP Standard v2.1 3.5.2.18). For 8b/10b the
4013+
* corresponding FEC overhead is BW allocation specific, included in the value
4014+
* returned by drm_dp_bw_overhead().
4015+
*
4016+
* Returns the efficiency in the 100%/coding-overhead% ratio in
4017+
* 1ppm units.
4018+
*/
4019+
int drm_dp_bw_channel_coding_efficiency(bool is_uhbr)
4020+
{
4021+
if (is_uhbr)
4022+
return 967100;
4023+
else
4024+
/*
4025+
* Note that on 8b/10b MST the efficiency is only
4026+
* 78.75% due to the 1 out of 64 MTPH packet overhead,
4027+
* not accounted for here.
4028+
*/
4029+
return 800000;
4030+
}
4031+
EXPORT_SYMBOL(drm_dp_bw_channel_coding_efficiency);

drivers/gpu/drm/display/drm_dp_mst_topology.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4726,17 +4726,28 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
47264726
int drm_dp_calc_pbn_mode(int clock, int bpp)
47274727
{
47284728
/*
4729-
* margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
47304729
* The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
47314730
* common multiplier to render an integer PBN for all link rate/lane
47324731
* counts combinations
47334732
* calculate
4734-
* peak_kbps *= (1006/1000)
4735-
* peak_kbps *= (64/54)
4736-
* peak_kbps *= 8 convert to bytes
4733+
* peak_kbps = clock * bpp / 16
4734+
* peak_kbps *= SSC overhead / 1000000
4735+
* peak_kbps /= 8 convert to Kbytes
4736+
* peak_kBps *= (64/54) / 1000 convert to PBN
47374737
*/
4738-
return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006 >> 4),
4739-
1000 * 8 * 54 * 1000);
4738+
/*
4739+
* TODO: Use the actual link and mode parameters to calculate
4740+
* the overhead. For now it's assumed that these are
4741+
* 4 link lanes, 4096 hactive pixels, which don't add any
4742+
* significant data padding overhead and that there is no DSC
4743+
* or FEC overhead.
4744+
*/
4745+
int overhead = drm_dp_bw_overhead(4, 4096, 0, bpp,
4746+
DRM_DP_BW_OVERHEAD_MST |
4747+
DRM_DP_BW_OVERHEAD_SSC_REF_CLK);
4748+
4749+
return DIV64_U64_ROUND_UP(mul_u32_u32(clock * bpp, 64 * overhead >> 4),
4750+
1000000ULL * 8 * 54 * 1000);
47404751
}
47414752
EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
47424753

include/drm/display/drm_dp_helper.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,4 +788,15 @@ bool drm_dp_downstream_rgb_to_ycbcr_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZ
788788
const u8 port_cap[4], u8 color_spc);
789789
int drm_dp_pcon_convert_rgb_to_ycbcr(struct drm_dp_aux *aux, u8 color_spc);
790790

791+
#define DRM_DP_BW_OVERHEAD_MST BIT(0)
792+
#define DRM_DP_BW_OVERHEAD_UHBR BIT(1)
793+
#define DRM_DP_BW_OVERHEAD_SSC_REF_CLK BIT(2)
794+
#define DRM_DP_BW_OVERHEAD_FEC BIT(3)
795+
#define DRM_DP_BW_OVERHEAD_DSC BIT(4)
796+
797+
int drm_dp_bw_overhead(int lane_count, int hactive,
798+
int dsc_slice_count,
799+
int bpp_x16, unsigned long flags);
800+
int drm_dp_bw_channel_coding_efficiency(bool is_uhbr);
801+
791802
#endif /* _DRM_DP_HELPER_H_ */

0 commit comments

Comments
 (0)