summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/modules/freesync
diff options
context:
space:
mode:
authorpo-tchen <robin.chen@amd.com>2024-09-20 15:41:55 +0800
committerAlex Deucher <alexander.deucher@amd.com>2024-10-07 14:11:49 -0400
commitaacbed5b41d93bb741d8dab6e3e008a732f3e3df (patch)
treec1e8aadd0edbce0030622e2cafcacf890c3dd76c /drivers/gpu/drm/amd/display/modules/freesync
parentffa1e31f70d2e97c121709b44a8960f5d7becb10 (diff)
downloadlinux-aacbed5b41d93bb741d8dab6e3e008a732f3e3df.tar.gz
linux-aacbed5b41d93bb741d8dab6e3e008a732f3e3df.tar.bz2
linux-aacbed5b41d93bb741d8dab6e3e008a732f3e3df.zip
drm/amd/display: Display lost signal on playing video
[Why] When Source extend the vblank to reach the minimum panel refresh rate, the vtotal length could have 1 line longer than the maximum supported vtotal. The reason is we optimized the vtotal/refresh-rate calculation to get more accurate vtotal number by rounding the calculation result. But when the target refresh rate is the minimum refresh rate, the vtotal result could be round up and over the maximum supported vtotal. Reviewed-by: Anthony Koo <anthony.koo@amd.com> Signed-off-by: po-tchen <robin.chen@amd.com> Signed-off-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules/freesync')
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index bbd259cea4f4..fc4268729017 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -48,6 +48,7 @@
#define VSYNCS_BETWEEN_FLIP_THRESHOLD 2
#define FREESYNC_CONSEC_FLIP_AFTER_VSYNC 5
#define FREESYNC_VSYNC_TO_FLIP_DELTA_IN_US 500
+#define MICRO_HZ_TO_HZ(x) (x / 1000000)
struct core_freesync {
struct mod_freesync public;
@@ -132,9 +133,19 @@ unsigned int mod_freesync_calc_v_total_from_refresh(
((unsigned int)(div64_u64((1000000000ULL * 1000000),
refresh_in_uhz)));
- v_total = div64_u64(div64_u64(((unsigned long long)(
- frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)),
- stream->timing.h_total) + 500000, 1000000);
+ if (MICRO_HZ_TO_HZ(refresh_in_uhz) <= stream->timing.min_refresh_in_uhz) {
+ /* When the target refresh rate is the minimum panel refresh rate,
+ * round down the vtotal value to avoid stretching vblank over
+ * panel's vtotal boundary.
+ */
+ v_total = div64_u64(div64_u64(((unsigned long long)(
+ frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)),
+ stream->timing.h_total), 1000000);
+ } else {
+ v_total = div64_u64(div64_u64(((unsigned long long)(
+ frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)),
+ stream->timing.h_total) + 500000, 1000000);
+ }
/* v_total cannot be less than nominal */
if (v_total < stream->timing.v_total) {