Commit a9ebb3e4 authored by Harry Wentland's avatar Harry Wentland Committed by Dave Airlie

drm/dp/mst: Calculate MST PBN with 31.32 fixed point

Our PBN value overflows the 20 bits integer part of the 20.12
fixed point. We need to use 31.32 fixed point to avoid this.

This happens with display clocks larger than 293122 (at 24 bpp),
which we see with the Sharp (and similar) 4k tiled displays.
Signed-off-by: default avatarHarry Wentland <harry.wentland@amd.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 64566b5e
...@@ -2606,32 +2606,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status); ...@@ -2606,32 +2606,31 @@ EXPORT_SYMBOL(drm_dp_check_act_status);
*/ */
int drm_dp_calc_pbn_mode(int clock, int bpp) int drm_dp_calc_pbn_mode(int clock, int bpp)
{ {
fixed20_12 pix_bw; u64 kbps;
fixed20_12 fbpp; s64 peak_kbps;
fixed20_12 result; u32 numerator;
fixed20_12 margin, tmp; u32 denominator;
u32 res;
kbps = clock * bpp;
pix_bw.full = dfixed_const(clock);
fbpp.full = dfixed_const(bpp); /*
tmp.full = dfixed_const(8); * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
fbpp.full = dfixed_div(fbpp, tmp); * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
* common multiplier to render an integer PBN for all link rate/lane
result.full = dfixed_mul(pix_bw, fbpp); * counts combinations
margin.full = dfixed_const(54); * calculate
tmp.full = dfixed_const(64); * peak_kbps *= (1006/1000)
margin.full = dfixed_div(margin, tmp); * peak_kbps *= (64/54)
result.full = dfixed_div(result, margin); * peak_kbps *= 8 convert to bytes
*/
margin.full = dfixed_const(1006);
tmp.full = dfixed_const(1000); numerator = 64 * 1006;
margin.full = dfixed_div(margin, tmp); denominator = 54 * 8 * 1000 * 1000;
result.full = dfixed_mul(result, margin);
kbps *= numerator;
result.full = dfixed_div(result, tmp); peak_kbps = drm_fixp_from_fraction(kbps, denominator);
result.full = dfixed_ceil(result);
res = dfixed_trunc(result); return drm_fixp2int_ceil(peak_kbps);
return res;
} }
EXPORT_SYMBOL(drm_dp_calc_pbn_mode); EXPORT_SYMBOL(drm_dp_calc_pbn_mode);
...@@ -2639,11 +2638,23 @@ static int test_calc_pbn_mode(void) ...@@ -2639,11 +2638,23 @@ static int test_calc_pbn_mode(void)
{ {
int ret; int ret;
ret = drm_dp_calc_pbn_mode(154000, 30); ret = drm_dp_calc_pbn_mode(154000, 30);
if (ret != 689) if (ret != 689) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
154000, 30, 689, ret);
return -EINVAL; return -EINVAL;
}
ret = drm_dp_calc_pbn_mode(234000, 30); ret = drm_dp_calc_pbn_mode(234000, 30);
if (ret != 1047) if (ret != 1047) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
234000, 30, 1047, ret);
return -EINVAL; return -EINVAL;
}
ret = drm_dp_calc_pbn_mode(297000, 24);
if (ret != 1063) {
DRM_ERROR("PBN calculation test failed - clock %d, bpp %d, expected PBN %d, actual PBN %d.\n",
297000, 24, 1063, ret);
return -EINVAL;
}
return 0; return 0;
} }
......
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