On Tue, Dec 9, 2025 at 12:34 PM Mario Limonciello
<[email protected]> wrote:
>
> Deeply daisy chained DP/MST displays are no longer able to light
> up. This reverts commit 1788ef30725da53face7e311cdf62ad65fababcd.
>
> Cc: Jerry Zuo <[email protected]>
> Cc: [email protected] # 6.17+
> Reported-by: [email protected]
> Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4756
> Signed-off-by: Mario Limonciello <[email protected]>

Acked-by: Alex Deucher <[email protected]>

> ---
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 59 +++++++++++--------
>  1 file changed, 36 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index dbd1da4d85d3..5e92eaa67aa3 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -884,28 +884,26 @@ struct dsc_mst_fairness_params {
>  };
>
>  #if defined(CONFIG_DRM_AMD_DC_FP)
> -static uint64_t kbps_to_pbn(int kbps, bool is_peak_pbn)
> +static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link)
>  {
> -       uint64_t effective_kbps = (uint64_t)kbps;
> +       u8 link_coding_cap;
> +       uint16_t fec_overhead_multiplier_x1000 = 
> PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B;
>
> -       if (is_peak_pbn) {      // add 0.6% (1006/1000) overhead into 
> effective kbps
> -               effective_kbps *= 1006;
> -               effective_kbps = div_u64(effective_kbps, 1000);
> -       }
> +       link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link);
> +       if (link_coding_cap == DP_128b_132b_ENCODING)
> +               fec_overhead_multiplier_x1000 = 
> PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B;
>
> -       return (uint64_t) DIV64_U64_ROUND_UP(effective_kbps * 64, (54 * 8 * 
> 1000));
> +       return fec_overhead_multiplier_x1000;
>  }
>
> -static uint32_t pbn_to_kbps(unsigned int pbn, bool with_margin)
> +static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)
>  {
> -       uint64_t pbn_effective = (uint64_t)pbn;
> -
> -       if (with_margin)        // deduct 0.6% (994/1000) overhead from 
> effective pbn
> -               pbn_effective *= (1000000 / PEAK_FACTOR_X1000);
> -       else
> -               pbn_effective *= 1000;
> +       u64 peak_kbps = kbps;
>
> -       return DIV_U64_ROUND_UP(pbn_effective * 8 * 54, 64);
> +       peak_kbps *= 1006;
> +       peak_kbps *= fec_overhead_multiplier_x1000;
> +       peak_kbps = div_u64(peak_kbps, 1000 * 1000);
> +       return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000));
>  }
>
>  static void set_dsc_configs_from_fairness_vars(struct 
> dsc_mst_fairness_params *params,
> @@ -976,7 +974,7 @@ static int bpp_x16_from_pbn(struct 
> dsc_mst_fairness_params param, int pbn)
>         dc_dsc_get_default_config_option(param.sink->ctx->dc, &dsc_options);
>         dsc_options.max_target_bpp_limit_override_x16 = 
> drm_connector->display_info.max_dsc_bpp * 16;
>
> -       kbps = pbn_to_kbps(pbn, false);
> +       kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
>         dc_dsc_compute_config(
>                         param.sink->ctx->dc->res_pool->dscs[0],
>                         &param.sink->dsc_caps.dsc_dec_caps,
> @@ -1005,11 +1003,12 @@ static int increase_dsc_bpp(struct drm_atomic_state 
> *state,
>         int link_timeslots_used;
>         int fair_pbn_alloc;
>         int ret = 0;
> +       uint16_t fec_overhead_multiplier_x1000 = 
> get_fec_overhead_multiplier(dc_link);
>
>         for (i = 0; i < count; i++) {
>                 if (vars[i + k].dsc_enabled) {
>                         initial_slack[i] =
> -                       kbps_to_pbn(params[i].bw_range.max_kbps, false) - 
> vars[i + k].pbn;
> +                       kbps_to_peak_pbn(params[i].bw_range.max_kbps, 
> fec_overhead_multiplier_x1000) - vars[i + k].pbn;
>                         bpp_increased[i] = false;
>                         remaining_to_increase += 1;
>                 } else {
> @@ -1105,6 +1104,7 @@ static int try_disable_dsc(struct drm_atomic_state 
> *state,
>         int next_index;
>         int remaining_to_try = 0;
>         int ret;
> +       uint16_t fec_overhead_multiplier_x1000 = 
> get_fec_overhead_multiplier(dc_link);
>         int var_pbn;
>
>         for (i = 0; i < count; i++) {
> @@ -1137,7 +1137,7 @@ static int try_disable_dsc(struct drm_atomic_state 
> *state,
>
>                 DRM_DEBUG_DRIVER("MST_DSC index #%d, try no compression\n", 
> next_index);
>                 var_pbn = vars[next_index].pbn;
> -               vars[next_index].pbn = 
> kbps_to_pbn(params[next_index].bw_range.stream_kbps, true);
> +               vars[next_index].pbn = 
> kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, 
> fec_overhead_multiplier_x1000);
>                 ret = drm_dp_atomic_find_time_slots(state,
>                                                     
> params[next_index].port->mgr,
>                                                     params[next_index].port,
> @@ -1197,6 +1197,7 @@ static int compute_mst_dsc_configs_for_link(struct 
> drm_atomic_state *state,
>         int count = 0;
>         int i, k, ret;
>         bool debugfs_overwrite = false;
> +       uint16_t fec_overhead_multiplier_x1000 = 
> get_fec_overhead_multiplier(dc_link);
>         struct drm_connector_state *new_conn_state;
>
>         memset(params, 0, sizeof(params));
> @@ -1277,7 +1278,7 @@ static int compute_mst_dsc_configs_for_link(struct 
> drm_atomic_state *state,
>         DRM_DEBUG_DRIVER("MST_DSC Try no compression\n");
>         for (i = 0; i < count; i++) {
>                 vars[i + k].aconnector = params[i].aconnector;
> -               vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, 
> false);
> +               vars[i + k].pbn = 
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps, 
> fec_overhead_multiplier_x1000);
>                 vars[i + k].dsc_enabled = false;
>                 vars[i + k].bpp_x16 = 0;
>                 ret = drm_dp_atomic_find_time_slots(state, 
> params[i].port->mgr, params[i].port,
> @@ -1299,7 +1300,7 @@ static int compute_mst_dsc_configs_for_link(struct 
> drm_atomic_state *state,
>         DRM_DEBUG_DRIVER("MST_DSC Try max compression\n");
>         for (i = 0; i < count; i++) {
>                 if (params[i].compression_possible && 
> params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) {
> -                       vars[i + k].pbn = 
> kbps_to_pbn(params[i].bw_range.min_kbps, false);
> +                       vars[i + k].pbn = 
> kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000);
>                         vars[i + k].dsc_enabled = true;
>                         vars[i + k].bpp_x16 = 
> params[i].bw_range.min_target_bpp_x16;
>                         ret = drm_dp_atomic_find_time_slots(state, 
> params[i].port->mgr,
> @@ -1307,7 +1308,7 @@ static int compute_mst_dsc_configs_for_link(struct 
> drm_atomic_state *state,
>                         if (ret < 0)
>                                 return ret;
>                 } else {
> -                       vars[i + k].pbn = 
> kbps_to_pbn(params[i].bw_range.stream_kbps, false);
> +                       vars[i + k].pbn = 
> kbps_to_peak_pbn(params[i].bw_range.stream_kbps, 
> fec_overhead_multiplier_x1000);
>                         vars[i + k].dsc_enabled = false;
>                         vars[i + k].bpp_x16 = 0;
>                         ret = drm_dp_atomic_find_time_slots(state, 
> params[i].port->mgr,
> @@ -1762,6 +1763,18 @@ int pre_validate_dsc(struct drm_atomic_state *state,
>         return ret;
>  }
>
> +static uint32_t kbps_from_pbn(unsigned int pbn)
> +{
> +       uint64_t kbps = (uint64_t)pbn;
> +
> +       kbps *= (1000000 / PEAK_FACTOR_X1000);
> +       kbps *= 8;
> +       kbps *= 54;
> +       kbps /= 64;
> +
> +       return (uint32_t)kbps;
> +}
> +
>  static bool is_dsc_common_config_possible(struct dc_stream_state *stream,
>                                           struct dc_dsc_bw_range *bw_range)
>  {
> @@ -1860,7 +1873,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
>                         dc_link_get_highest_encoding_format(stream->link));
>         cur_link_settings = stream->link->verified_link_cap;
>         root_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, 
> &cur_link_settings);
> -       virtual_channel_bw_in_kbps = 
> pbn_to_kbps(aconnector->mst_output_port->full_pbn, true);
> +       virtual_channel_bw_in_kbps = 
> kbps_from_pbn(aconnector->mst_output_port->full_pbn);
>
>         /* pick the end to end bw bottleneck */
>         end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, 
> virtual_channel_bw_in_kbps);
> @@ -1913,7 +1926,7 @@ enum dc_status dm_dp_mst_is_port_support_mode(
>                                 immediate_upstream_port = 
> aconnector->mst_output_port->parent->port_parent;
>
>                         if (immediate_upstream_port) {
> -                               virtual_channel_bw_in_kbps = 
> pbn_to_kbps(immediate_upstream_port->full_pbn, true);
> +                               virtual_channel_bw_in_kbps = 
> kbps_from_pbn(immediate_upstream_port->full_pbn);
>                                 virtual_channel_bw_in_kbps = 
> min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
>                         } else {
>                                 /* For topology LCT 1 case - only one mstb*/
> --
> 2.51.2
>

Reply via email to