]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/amd/display: Fix pbn_div Calculation Error
authorFangzhi Zuo <Jerry.Zuo@amd.com>
Tue, 8 Apr 2025 19:11:43 +0000 (15:11 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 5 Sep 2025 21:38:41 +0000 (17:38 -0400)
[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>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
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 5ae01b0ac0934f62a8fa3567194e3f6b50a6de42..e34d98a945f2fbd98df09a5658352141d99a6527 100644 (file)
@@ -8015,7 +8015,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
        if (IS_ERR(mst_state))
                return PTR_ERR(mst_state);
 
-       mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link));
+       mst_state->pbn_div.full = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
 
        if (!state->duplicated) {
                int max_bpc = conn_state->max_requested_bpc;
index 6911c339bc61b96403af6fb9c6c2e3175a8a045c..5e92eaa67aa33d0924f2b3b05b5581bcf2d254f4 100644 (file)
@@ -854,13 +854,20 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
        drm_connector_attach_dp_subconnector_property(&aconnector->base);
 }
 
-int dm_mst_get_pbn_divider(struct dc_link *link)
+uint32_t dm_mst_get_pbn_divider(struct dc_link *link)
 {
+       uint32_t pbn_div_x100;
+       uint64_t dividend, divisor;
+
        if (!link)
                return 0;
 
-       return dc_link_bandwidth_kbps(link,
-                       dc_link_get_link_cap(link)) / (8 * 1000 * 54);
+       dividend = (uint64_t)dc_link_bandwidth_kbps(link, dc_link_get_link_cap(link)) * 100;
+       divisor = 8 * 1000 * 54;
+
+       pbn_div_x100 = div64_u64(dividend, divisor);
+
+       return dfixed_const(pbn_div_x100) / 100;
 }
 
 struct dsc_mst_fairness_params {
index 65f76a7d00dbfa963fce1fb577520c0c0b8d4823..6f7ea684b555f7b4ff03df6c2f16317932673d5a 100644 (file)
@@ -60,7 +60,7 @@ enum mst_msg_ready_type {
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;
 
-int dm_mst_get_pbn_divider(struct dc_link *link);
+uint32_t dm_mst_get_pbn_divider(struct dc_link *link);
 
 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
                                       struct amdgpu_dm_connector *aconnector,