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

Configure Feed

Select the types of activity you want to include in your feed.

drm/amd/display: Fix pbn_div Calculation Error

[Why]
dm_mst_get_pbn_divider() returns value integer coming from
the cast from fixed point, but the casted integer will then be used
in dfixed_const to be multiplied by 4096. The cast from fixed point to integer
causes the calculation error becomes bigger when multiplied by 4096.

That makes the calculated pbn_div value becomes smaller than
it should be, which leads to the req_slot number becomes bigger.

Such error is getting reflected in 8k30 timing,
where the correct and incorrect calculated req_slot 62.9 Vs 63.1.
That makes the wrong calculation failed to light up 8k30
after a dock under HBR3 x 4.

[How]
Restore the accuracy by keeping the fraction part
calculated for the left shift operation.

Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: Wayne Lin <wayne.lin@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
12cdfb61 1bde5584

+12 -5
+1 -1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 8015 8015 if (IS_ERR(mst_state)) 8016 8016 return PTR_ERR(mst_state); 8017 8017 8018 - mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link)); 8018 + mst_state->pbn_div.full = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link); 8019 8019 8020 8020 if (!state->duplicated) { 8021 8021 int max_bpc = conn_state->max_requested_bpc;
+10 -3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
··· 854 854 drm_connector_attach_dp_subconnector_property(&aconnector->base); 855 855 } 856 856 857 - int dm_mst_get_pbn_divider(struct dc_link *link) 857 + uint32_t dm_mst_get_pbn_divider(struct dc_link *link) 858 858 { 859 + uint32_t pbn_div_x100; 860 + uint64_t dividend, divisor; 861 + 859 862 if (!link) 860 863 return 0; 861 864 862 - return dc_link_bandwidth_kbps(link, 863 - dc_link_get_link_cap(link)) / (8 * 1000 * 54); 865 + dividend = (uint64_t)dc_link_bandwidth_kbps(link, dc_link_get_link_cap(link)) * 100; 866 + divisor = 8 * 1000 * 54; 867 + 868 + pbn_div_x100 = div64_u64(dividend, divisor); 869 + 870 + return dfixed_const(pbn_div_x100) / 100; 864 871 } 865 872 866 873 struct dsc_mst_fairness_params {
+1 -1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
··· 60 60 struct amdgpu_display_manager; 61 61 struct amdgpu_dm_connector; 62 62 63 - int dm_mst_get_pbn_divider(struct dc_link *link); 63 + uint32_t dm_mst_get_pbn_divider(struct dc_link *link); 64 64 65 65 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, 66 66 struct amdgpu_dm_connector *aconnector,