Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Fangzhi Zuo and committed by
Alex Deucher
e0dec00f a6ec1726

+23 -36
+23 -36
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
··· 884 884 }; 885 885 886 886 #if defined(CONFIG_DRM_AMD_DC_FP) 887 - static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link) 887 + static uint64_t kbps_to_pbn(int kbps, bool is_peak_pbn) 888 888 { 889 - u8 link_coding_cap; 890 - uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B; 889 + uint64_t effective_kbps = (uint64_t)kbps; 891 890 892 - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link); 893 - if (link_coding_cap == DP_128b_132b_ENCODING) 894 - fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B; 891 + if (is_peak_pbn) { // add 0.6% (1006/1000) overhead into effective kbps 892 + effective_kbps *= 1006; 893 + effective_kbps = div_u64(effective_kbps, 1000); 894 + } 895 895 896 - return fec_overhead_multiplier_x1000; 896 + return (uint64_t) DIV64_U64_ROUND_UP(effective_kbps * 64, (54 * 8 * 1000)); 897 897 } 898 898 899 - static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000) 899 + static uint32_t pbn_to_kbps(unsigned int pbn, bool with_margin) 900 900 { 901 - u64 peak_kbps = kbps; 901 + uint64_t pbn_effective = (uint64_t)pbn; 902 902 903 - peak_kbps *= 1006; 904 - peak_kbps *= fec_overhead_multiplier_x1000; 905 - peak_kbps = div_u64(peak_kbps, 1000 * 1000); 906 - return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000)); 903 + if (with_margin) // deduct 0.6% (994/1000) overhead from effective pbn 904 + pbn_effective *= (1000000 / PEAK_FACTOR_X1000); 905 + else 906 + pbn_effective *= 1000; 907 + 908 + return DIV_U64_ROUND_UP(pbn_effective * 8 * 54, 64); 907 909 } 908 910 909 911 static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *params, ··· 976 974 dc_dsc_get_default_config_option(param.sink->ctx->dc, &dsc_options); 977 975 dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16; 978 976 979 - kbps = div_u64((u64)pbn * 994 * 8 * 54, 64); 977 + kbps = pbn_to_kbps(pbn, false); 980 978 dc_dsc_compute_config( 981 979 param.sink->ctx->dc->res_pool->dscs[0], 982 980 &param.sink->dsc_caps.dsc_dec_caps, ··· 1005 1003 int link_timeslots_used; 1006 1004 int fair_pbn_alloc; 1007 1005 int ret = 0; 1008 - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); 1009 1006 1010 1007 for (i = 0; i < count; i++) { 1011 1008 if (vars[i + k].dsc_enabled) { 1012 1009 initial_slack[i] = 1013 - kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn; 1010 + kbps_to_pbn(params[i].bw_range.max_kbps, false) - vars[i + k].pbn; 1014 1011 bpp_increased[i] = false; 1015 1012 remaining_to_increase += 1; 1016 1013 } else { ··· 1105 1104 int next_index; 1106 1105 int remaining_to_try = 0; 1107 1106 int ret; 1108 - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); 1109 1107 int var_pbn; 1110 1108 1111 1109 for (i = 0; i < count; i++) { ··· 1137 1137 1138 1138 DRM_DEBUG_DRIVER("MST_DSC index #%d, try no compression\n", next_index); 1139 1139 var_pbn = vars[next_index].pbn; 1140 - vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000); 1140 + vars[next_index].pbn = kbps_to_pbn(params[next_index].bw_range.stream_kbps, true); 1141 1141 ret = drm_dp_atomic_find_time_slots(state, 1142 1142 params[next_index].port->mgr, 1143 1143 params[next_index].port, ··· 1197 1197 int count = 0; 1198 1198 int i, k, ret; 1199 1199 bool debugfs_overwrite = false; 1200 - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); 1201 1200 struct drm_connector_state *new_conn_state; 1202 1201 1203 1202 memset(params, 0, sizeof(params)); ··· 1277 1278 DRM_DEBUG_DRIVER("MST_DSC Try no compression\n"); 1278 1279 for (i = 0; i < count; i++) { 1279 1280 vars[i + k].aconnector = params[i].aconnector; 1280 - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); 1281 + vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false); 1281 1282 vars[i + k].dsc_enabled = false; 1282 1283 vars[i + k].bpp_x16 = 0; 1283 1284 ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, ··· 1299 1300 DRM_DEBUG_DRIVER("MST_DSC Try max compression\n"); 1300 1301 for (i = 0; i < count; i++) { 1301 1302 if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { 1302 - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000); 1303 + vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.min_kbps, false); 1303 1304 vars[i + k].dsc_enabled = true; 1304 1305 vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; 1305 1306 ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, ··· 1307 1308 if (ret < 0) 1308 1309 return ret; 1309 1310 } else { 1310 - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); 1311 + vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false); 1311 1312 vars[i + k].dsc_enabled = false; 1312 1313 vars[i + k].bpp_x16 = 0; 1313 1314 ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, ··· 1762 1763 return ret; 1763 1764 } 1764 1765 1765 - static uint32_t kbps_from_pbn(unsigned int pbn) 1766 - { 1767 - uint64_t kbps = (uint64_t)pbn; 1768 - 1769 - kbps *= (1000000 / PEAK_FACTOR_X1000); 1770 - kbps *= 8; 1771 - kbps *= 54; 1772 - kbps /= 64; 1773 - 1774 - return (uint32_t)kbps; 1775 - } 1776 - 1777 1766 static bool is_dsc_common_config_possible(struct dc_stream_state *stream, 1778 1767 struct dc_dsc_bw_range *bw_range) 1779 1768 { ··· 1860 1873 dc_link_get_highest_encoding_format(stream->link)); 1861 1874 cur_link_settings = stream->link->verified_link_cap; 1862 1875 root_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings); 1863 - virtual_channel_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn); 1876 + virtual_channel_bw_in_kbps = pbn_to_kbps(aconnector->mst_output_port->full_pbn, true); 1864 1877 1865 1878 /* pick the end to end bw bottleneck */ 1866 1879 end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps); ··· 1913 1926 immediate_upstream_port = aconnector->mst_output_port->parent->port_parent; 1914 1927 1915 1928 if (immediate_upstream_port) { 1916 - virtual_channel_bw_in_kbps = kbps_from_pbn(immediate_upstream_port->full_pbn); 1929 + virtual_channel_bw_in_kbps = pbn_to_kbps(immediate_upstream_port->full_pbn, true); 1917 1930 virtual_channel_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps); 1918 1931 } else { 1919 1932 /* For topology LCT 1 case - only one mstb*/