Commit 68dc1846 authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher

drm/amd/display: Take FEC Overhead into Timeslot Calculation

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: default avatarHersen Wu <hersenxs.wu@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f4f3b7de
...@@ -681,12 +681,25 @@ struct dsc_mst_fairness_params { ...@@ -681,12 +681,25 @@ struct dsc_mst_fairness_params {
struct amdgpu_dm_connector *aconnector; 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; u64 peak_kbps = kbps;
peak_kbps *= 1006; 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)); return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000));
} }
...@@ -780,11 +793,12 @@ static int increase_dsc_bpp(struct drm_atomic_state *state, ...@@ -780,11 +793,12 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
int link_timeslots_used; int link_timeslots_used;
int fair_pbn_alloc; int fair_pbn_alloc;
int ret = 0; int ret = 0;
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (vars[i + k].dsc_enabled) { if (vars[i + k].dsc_enabled) {
initial_slack[i] = 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; bpp_increased[i] = false;
remaining_to_increase += 1; remaining_to_increase += 1;
} else { } else {
...@@ -880,6 +894,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, ...@@ -880,6 +894,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
int next_index; int next_index;
int remaining_to_try = 0; int remaining_to_try = 0;
int ret; int ret;
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (vars[i + k].dsc_enabled if (vars[i + k].dsc_enabled
...@@ -909,7 +924,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, ...@@ -909,7 +924,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
if (next_index == -1) if (next_index == -1)
break; 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, ret = drm_dp_atomic_find_time_slots(state,
params[next_index].port->mgr, params[next_index].port->mgr,
params[next_index].port, params[next_index].port,
...@@ -922,7 +937,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, ...@@ -922,7 +937,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
vars[next_index].dsc_enabled = false; vars[next_index].dsc_enabled = false;
vars[next_index].bpp_x16 = 0; vars[next_index].bpp_x16 = 0;
} else { } 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, ret = drm_dp_atomic_find_time_slots(state,
params[next_index].port->mgr, params[next_index].port->mgr,
params[next_index].port, params[next_index].port,
...@@ -951,6 +966,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, ...@@ -951,6 +966,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
int count = 0; int count = 0;
int i, k, ret; int i, k, ret;
bool debugfs_overwrite = false; bool debugfs_overwrite = false;
uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
memset(params, 0, sizeof(params)); memset(params, 0, sizeof(params));
...@@ -1012,7 +1028,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, ...@@ -1012,7 +1028,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
/* Try no compression */ /* Try no compression */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
vars[i + k].aconnector = params[i].aconnector; 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].dsc_enabled = false;
vars[i + k].bpp_x16 = 0; vars[i + k].bpp_x16 = 0;
ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
...@@ -1031,7 +1047,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, ...@@ -1031,7 +1047,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
/* Try max compression */ /* Try max compression */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { 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].dsc_enabled = true;
vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; 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, ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
...@@ -1039,7 +1055,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, ...@@ -1039,7 +1055,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
if (ret < 0) if (ret < 0)
return ret; return ret;
} else { } 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].dsc_enabled = false;
vars[i + k].bpp_x16 = 0; vars[i + k].bpp_x16 = 0;
ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
......
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
#define SYNAPTICS_CASCADED_HUB_ID 0x5A #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 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_display_manager;
struct amdgpu_dm_connector; struct amdgpu_dm_connector;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment