Skip to content

Commit 5a6b545

Browse files
AMD-aricalexdeucher
authored andcommitted
drm/amd/display: LFC not working on 2.0x range monitors (v2)
[Why] Nominal pixel clock and EDID information differ in precision so although monitor reports maximum refresh is 2x minimum, LFC was not being enabled. [How] Use minimum refresh rate as nominal/2 when EDID dictates that min refresh = max refresh/2. v2: squash in 64 bit divide fix Signed-off-by: Aric Cyr <[email protected]> Reviewed-by: Nicholas Kazlauskas <[email protected]> Acked-by: Rodrigo Siqueira <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 5c41c02 commit 5a6b545

File tree

1 file changed

+19
-15
lines changed
  • drivers/gpu/drm/amd/display/modules/freesync

1 file changed

+19
-15
lines changed

drivers/gpu/drm/amd/display/modules/freesync/freesync.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
734734
{
735735
struct core_freesync *core_freesync = NULL;
736736
unsigned long long nominal_field_rate_in_uhz = 0;
737+
unsigned long long rounded_nominal_in_uhz = 0;
737738
unsigned int refresh_range = 0;
738739
unsigned long long min_refresh_in_uhz = 0;
739740
unsigned long long max_refresh_in_uhz = 0;
@@ -750,17 +751,20 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
750751
min_refresh_in_uhz = in_config->min_refresh_in_uhz;
751752
max_refresh_in_uhz = in_config->max_refresh_in_uhz;
752753

753-
// Don't allow min > max
754-
if (min_refresh_in_uhz > max_refresh_in_uhz)
755-
min_refresh_in_uhz = max_refresh_in_uhz;
756-
757754
// Full range may be larger than current video timing, so cap at nominal
758755
if (max_refresh_in_uhz > nominal_field_rate_in_uhz)
759756
max_refresh_in_uhz = nominal_field_rate_in_uhz;
760757

761758
// Full range may be larger than current video timing, so cap at nominal
762-
if (min_refresh_in_uhz > nominal_field_rate_in_uhz)
763-
min_refresh_in_uhz = nominal_field_rate_in_uhz;
759+
if (min_refresh_in_uhz > max_refresh_in_uhz)
760+
min_refresh_in_uhz = max_refresh_in_uhz;
761+
762+
// If a monitor reports exactly max refresh of 2x of min, enforce it on nominal
763+
rounded_nominal_in_uhz =
764+
div_u64(nominal_field_rate_in_uhz + 50000, 100000) * 100000;
765+
if (in_config->max_refresh_in_uhz == (2 * in_config->min_refresh_in_uhz) &&
766+
in_config->max_refresh_in_uhz == rounded_nominal_in_uhz)
767+
min_refresh_in_uhz = div_u64(nominal_field_rate_in_uhz, 2);
764768

765769
if (!vrr_settings_require_update(core_freesync,
766770
in_config, (unsigned int)min_refresh_in_uhz, (unsigned int)max_refresh_in_uhz,
@@ -792,21 +796,21 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
792796
refresh_range = in_out_vrr->max_refresh_in_uhz -
793797
in_out_vrr->min_refresh_in_uhz;
794798

795-
in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
796-
2 * in_out_vrr->min_duration_in_us;
797-
if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
798-
in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
799-
800799
in_out_vrr->supported = true;
801800
}
802801

803802
in_out_vrr->fixed.ramping_active = in_config->ramping;
804803

805804
in_out_vrr->btr.btr_enabled = in_config->btr;
806805

807-
if (in_out_vrr->max_refresh_in_uhz <
808-
2 * in_out_vrr->min_refresh_in_uhz)
806+
if (in_out_vrr->max_refresh_in_uhz < (2 * in_out_vrr->min_refresh_in_uhz))
809807
in_out_vrr->btr.btr_enabled = false;
808+
else {
809+
in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
810+
2 * in_out_vrr->min_duration_in_us;
811+
if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
812+
in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
813+
}
810814

811815
in_out_vrr->btr.btr_active = false;
812816
in_out_vrr->btr.inserted_duration_in_us = 0;
@@ -1008,8 +1012,8 @@ unsigned long long mod_freesync_calc_nominal_field_rate(
10081012
unsigned int total = stream->timing.h_total * stream->timing.v_total;
10091013

10101014
/* Calculate nominal field rate for stream, rounded up to nearest integer */
1011-
nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz / 10;
1012-
nominal_field_rate_in_uhz *= 1000ULL * 1000ULL * 1000ULL;
1015+
nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz;
1016+
nominal_field_rate_in_uhz *= 100000000ULL;
10131017

10141018
nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz, total);
10151019

0 commit comments

Comments
 (0)