drm/amd/display: Take FEC Overhead into Timeslot Calculation
authorFangzhi Zuo <Jerry.Zuo@amd.com>
Wed, 1 Mar 2023 02:34:58 +0000 (21:34 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 14 Mar 2023 19:35:39 +0000 (15:35 -0400)
8b/10b encoding needs to add 3% fec overhead into the pbn.
In the Synapcis Cascaded MST hub, the first stage MST branch device
needs the information to determine the timeslot count for the
second stage MST branch device. Missing this overhead will leads to
insufficient timeslot allocation.

Cc: stable@vger.kernel.org
Cc: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h

index 9241d48..6378352 100644 (file)
@@ -670,12 +670,25 @@ struct dsc_mst_fairness_params {
        struct amdgpu_dm_connector *aconnector;
 };
 
-static int kbps_to_peak_pbn(int kbps)
+static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link)
+{
+       u8 link_coding_cap;
+       uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B;
+
+       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 fec_overhead_multiplier_x1000;
+}
+
+static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)
 {
        u64 peak_kbps = kbps;
 
        peak_kbps *= 1006;
-       peak_kbps = div_u64(peak_kbps, 1000);
+       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));
 }
 
@@ -773,11 +786,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_peak_pbn(params[i].bw_range.max_kbps) - 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 {
@@ -873,6 +887,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);
 
        for (i = 0; i < count; i++) {
                if (vars[i + k].dsc_enabled
@@ -902,7 +917,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
                if (next_index == -1)
                        break;
 
-               vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
+               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,
@@ -915,7 +930,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
                        vars[next_index].dsc_enabled = false;
                        vars[next_index].bpp_x16 = 0;
                } else {
-                       vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
+                       vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps, fec_overhead_multiplier_x1000);
                        ret = drm_dp_atomic_find_time_slots(state,
                                                            params[next_index].port->mgr,
                                                            params[next_index].port,
@@ -944,6 +959,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);
 
        memset(params, 0, sizeof(params));
 
@@ -1005,7 +1021,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        /* Try no compression */
        for (i = 0; i < count; i++) {
                vars[i + k].aconnector = params[i].aconnector;
-               vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
+               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,
@@ -1024,7 +1040,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        /* Try max compression */
        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_peak_pbn(params[i].bw_range.min_kbps);
+                       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,
@@ -1032,7 +1048,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_peak_pbn(params[i].bw_range.stream_kbps);
+                       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,
index 0b57502..1e4ede1 100644 (file)
@@ -46,6 +46,9 @@
 #define SYNAPTICS_CASCADED_HUB_ID  0x5A
 #define IS_SYNAPTICS_CASCADED_PANAMERA(devName, data) ((IS_SYNAPTICS_PANAMERA(devName) && ((int)data[2] == SYNAPTICS_CASCADED_HUB_ID)) ? 1 : 0)
 
+#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B     1031
+#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B  1000
+
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;