From 065458a7990dcef151f00743df9e09b878453d99 Mon Sep 17 00:00:00 2001 From: jsg Date: Mon, 29 Jan 2024 01:23:04 +0000 Subject: [PATCH] drm/dp_mst: Fix fractional DSC bpp handling From Ville Syrjala 4e042f022255604c68ab5d5f73c8f437d24d651e in linux-6.6.y/6.6.14 7707dd6022593f3edd8e182e7935870cf326f874 in mainline linux --- .../pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- sys/dev/pci/drm/display/drm_dp_mst_topology.c | 20 +++++-------------- sys/dev/pci/drm/i915/display/intel_dp_mst.c | 5 ++--- .../include/drm/display/drm_dp_mst_helper.h | 2 +- 5 files changed, 10 insertions(+), 21 deletions(-) diff --git a/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9400cd74a13..241bd616402 100644 --- a/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6886,7 +6886,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, max_bpc); bpp = convert_dc_color_depth_into_bpc(color_depth) * 3; clock = adjusted_mode->clock; - dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false); + dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp << 4); } dm_new_connector_state->vcpi_slots = diff --git a/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 28f5eb9ecbd..10dd4cd6f59 100644 --- a/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/sys/dev/pci/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1636,7 +1636,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( } else { /* check if mode could be supported within full_pbn */ bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; - pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); + pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp << 4); if (pbn > full_pbn) return DC_FAIL_BANDWIDTH_VALIDATE; } diff --git a/sys/dev/pci/drm/display/drm_dp_mst_topology.c b/sys/dev/pci/drm/display/drm_dp_mst_topology.c index 18a02f0de12..778b59616d6 100644 --- a/sys/dev/pci/drm/display/drm_dp_mst_topology.c +++ b/sys/dev/pci/drm/display/drm_dp_mst_topology.c @@ -4700,13 +4700,12 @@ EXPORT_SYMBOL(drm_dp_check_act_status); /** * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode. - * @clock: dot clock for the mode - * @bpp: bpp for the mode. - * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel + * @clock: dot clock + * @bpp: bpp as .4 binary fixed point * * This uses the formula in the spec to calculate the PBN value for a mode. */ -int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc) +int drm_dp_calc_pbn_mode(int clock, int bpp) { /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 @@ -4717,18 +4716,9 @@ int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc) * peak_kbps *= (1006/1000) * peak_kbps *= (64/54) * peak_kbps *= 8 convert to bytes - * - * If the bpp is in units of 1/16, further divide by 16. Put this - * factor in the numerator rather than the denominator to avoid - * integer overflow */ - - if (dsc) - return DIV_ROUND_UP_ULL(mul_u32_u32(clock * (bpp / 16), 64 * 1006), - 8 * 54 * 1000 * 1000); - - return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006), - 8 * 54 * 1000 * 1000); + return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006 >> 4), + 1000 * 8 * 54 * 1000); } EXPORT_SYMBOL(drm_dp_calc_pbn_mode); diff --git a/sys/dev/pci/drm/i915/display/intel_dp_mst.c b/sys/dev/pci/drm/i915/display/intel_dp_mst.c index 77bd1313c80..f104bd7f8c2 100644 --- a/sys/dev/pci/drm/i915/display/intel_dp_mst.c +++ b/sys/dev/pci/drm/i915/display/intel_dp_mst.c @@ -109,8 +109,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, continue; crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, - dsc ? bpp << 4 : bpp, - dsc); + bpp << 4); slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr, connector->port, @@ -941,7 +940,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return ret; if (mode_rate > max_rate || mode->clock > max_dotclk || - drm_dp_calc_pbn_mode(mode->clock, min_bpp, false) > port->full_pbn) { + drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) { *status = MODE_CLOCK_HIGH; return 0; } diff --git a/sys/dev/pci/drm/include/drm/display/drm_dp_mst_helper.h b/sys/dev/pci/drm/include/drm/display/drm_dp_mst_helper.h index 6c62607933e..06dc5d1ec1a 100644 --- a/sys/dev/pci/drm/include/drm/display/drm_dp_mst_helper.h +++ b/sys/dev/pci/drm/include/drm/display/drm_dp_mst_helper.h @@ -832,7 +832,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, int link_rate, int link_lane_count); -int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc); +int drm_dp_calc_pbn_mode(int clock, int bpp); void drm_dp_mst_update_slots(struct drm_dp_mst_topology_state *mst_state, uint8_t link_encoding_cap); -- 2.20.1