Commit e0dec00f authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher
Browse files

drm/amd/display: Fix pbn to kbps Conversion

[Why]
Existing routine has two conversion sequence,
pbn_to_kbps and kbps_to_pbn with margin.
Non of those has without-margin calculation.

kbps_to_pbn with margin conversion includes
fec overhead which has already been included in
pbn_div calculation with 0.994 factor considered.
It is a double counted fec overhead factor that causes
potential bw loss.

[How]
Add without-margin calculation.
Fix fec overhead double counted issue.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3735


Reviewed-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: default avatarIvan Lipski <ivan.lipski@amd.com>
Tested-by: default avatarDan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a6ec1726
Loading
Loading
Loading
Loading
+23 −36
Original line number Diff line number Diff line
@@ -884,26 +884,28 @@ struct dsc_mst_fairness_params {
};

#if defined(CONFIG_DRM_AMD_DC_FP)
static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link)
static uint64_t kbps_to_pbn(int kbps, bool is_peak_pbn)
{
	u8 link_coding_cap;
	uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B;
	uint64_t effective_kbps = (uint64_t)kbps;

	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;
	if (is_peak_pbn) {	// add 0.6% (1006/1000) overhead into effective kbps
		effective_kbps *= 1006;
		effective_kbps = div_u64(effective_kbps, 1000);
	}

	return fec_overhead_multiplier_x1000;
	return (uint64_t) DIV64_U64_ROUND_UP(effective_kbps * 64, (54 * 8 * 1000));
}

static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)
static uint32_t pbn_to_kbps(unsigned int pbn, bool with_margin)
{
	u64 peak_kbps = kbps;
	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;

	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));
	return DIV_U64_ROUND_UP(pbn_effective * 8 * 54, 64);
}

static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *params,
@@ -974,7 +976,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 = div_u64((u64)pbn * 994 * 8 * 54, 64);
	kbps = pbn_to_kbps(pbn, false);
	dc_dsc_compute_config(
			param.sink->ctx->dc->res_pool->dscs[0],
			&param.sink->dsc_caps.dsc_dec_caps,
@@ -1003,12 +1005,11 @@ 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, fec_overhead_multiplier_x1000) - vars[i + k].pbn;
			kbps_to_pbn(params[i].bw_range.max_kbps, false) - vars[i + k].pbn;
			bpp_increased[i] = false;
			remaining_to_increase += 1;
		} else {
@@ -1104,7 +1105,6 @@ 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_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
		vars[next_index].pbn = kbps_to_pbn(params[next_index].bw_range.stream_kbps, true);
		ret = drm_dp_atomic_find_time_slots(state,
						    params[next_index].port->mgr,
						    params[next_index].port,
@@ -1197,7 +1197,6 @@ 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));
@@ -1278,7 +1277,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_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
		vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false);
		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,
@@ -1300,7 +1299,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_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000);
			vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.min_kbps, false);
			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,
@@ -1308,7 +1307,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, fec_overhead_multiplier_x1000);
			vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false);
			vars[i + k].dsc_enabled = false;
			vars[i + k].bpp_x16 = 0;
			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
@@ -1763,18 +1762,6 @@ 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)
{
@@ -1873,7 +1860,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 = kbps_from_pbn(aconnector->mst_output_port->full_pbn);
	virtual_channel_bw_in_kbps = pbn_to_kbps(aconnector->mst_output_port->full_pbn, true);

	/* pick the end to end bw bottleneck */
	end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps);
@@ -1926,7 +1913,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 = kbps_from_pbn(immediate_upstream_port->full_pbn);
				virtual_channel_bw_in_kbps = pbn_to_kbps(immediate_upstream_port->full_pbn, true);
				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*/