Commit bb2746ac authored by Aric Cyr's avatar Aric Cyr Committed by Alex Deucher

drm/amd/display: Improve LFC behaviour

[Why]
There can be some unsynchronized frames when entering/exiting
LFC.  This may cause tearing or stuttering at such transitions.

[How]
Add a enter/exit margin to algorithm to smoothly transition into
and out of LFC without desynchronizing frames.
Signed-off-by: default avatarAric Cyr <aric.cyr@amd.com>
Reviewed-by: default avatarReza Amini <Reza.Amini@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Acked-by: default avatarSivapiriyan Kumarasamy <Sivapiriyan.Kumarasamy@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ec4388a2
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
#define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65) #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
/* Number of elements in the render times cache array */ /* Number of elements in the render times cache array */
#define RENDER_TIMES_MAX_COUNT 10 #define RENDER_TIMES_MAX_COUNT 10
/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */ /* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
#define BTR_EXIT_MARGIN 2000 #define BTR_MAX_MARGIN 2500
/* Threshold to change BTR multiplier (to avoid frequent changes) */ /* Threshold to change BTR multiplier (to avoid frequent changes) */
#define BTR_DRIFT_MARGIN 2000 #define BTR_DRIFT_MARGIN 2000
/*Threshold to exit fixed refresh rate*/ /*Threshold to exit fixed refresh rate*/
...@@ -250,24 +250,22 @@ static void apply_below_the_range(struct core_freesync *core_freesync, ...@@ -250,24 +250,22 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF; unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF; unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
unsigned int frames_to_insert = 0; unsigned int frames_to_insert = 0;
unsigned int min_frame_duration_in_ns = 0;
unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
unsigned int delta_from_mid_point_delta_in_us; unsigned int delta_from_mid_point_delta_in_us;
unsigned int max_render_time_in_us =
min_frame_duration_in_ns = ((unsigned int) (div64_u64( in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
(1000000000ULL * 1000000),
in_out_vrr->max_refresh_in_uhz)));
/* Program BTR */ /* Program BTR */
if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) { if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
/* Exit Below the Range */ /* Exit Below the Range */
if (in_out_vrr->btr.btr_active) { if (in_out_vrr->btr.btr_active) {
in_out_vrr->btr.frame_counter = 0; in_out_vrr->btr.frame_counter = 0;
in_out_vrr->btr.btr_active = false; in_out_vrr->btr.btr_active = false;
} }
} else if (last_render_time_in_us > max_render_time_in_us) { } else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
/* Enter Below the Range */ /* Enter Below the Range */
in_out_vrr->btr.btr_active = true; if (!in_out_vrr->btr.btr_active) {
in_out_vrr->btr.btr_active = true;
}
} }
/* BTR set to "not active" so disengage */ /* BTR set to "not active" so disengage */
...@@ -323,7 +321,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync, ...@@ -323,7 +321,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
/* Choose number of frames to insert based on how close it /* Choose number of frames to insert based on how close it
* can get to the mid point of the variable range. * can get to the mid point of the variable range.
*/ */
if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us &&
(delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 ||
mid_point_frames_floor < 2)) {
frames_to_insert = mid_point_frames_ceil; frames_to_insert = mid_point_frames_ceil;
delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
delta_from_mid_point_in_us_1; delta_from_mid_point_in_us_1;
...@@ -339,7 +339,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync, ...@@ -339,7 +339,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
if (in_out_vrr->btr.frames_to_insert != 0 && if (in_out_vrr->btr.frames_to_insert != 0 &&
delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) { delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) < if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
in_out_vrr->max_duration_in_us) && max_render_time_in_us) &&
((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) > ((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
in_out_vrr->min_duration_in_us)) in_out_vrr->min_duration_in_us))
frames_to_insert = in_out_vrr->btr.frames_to_insert; frames_to_insert = in_out_vrr->btr.frames_to_insert;
...@@ -788,6 +788,11 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, ...@@ -788,6 +788,11 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
refresh_range = in_out_vrr->max_refresh_in_uhz - refresh_range = in_out_vrr->max_refresh_in_uhz -
in_out_vrr->min_refresh_in_uhz; in_out_vrr->min_refresh_in_uhz;
in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
2 * in_out_vrr->min_duration_in_us;
if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
in_out_vrr->supported = true; in_out_vrr->supported = true;
} }
...@@ -803,6 +808,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, ...@@ -803,6 +808,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
in_out_vrr->btr.inserted_duration_in_us = 0; in_out_vrr->btr.inserted_duration_in_us = 0;
in_out_vrr->btr.frames_to_insert = 0; in_out_vrr->btr.frames_to_insert = 0;
in_out_vrr->btr.frame_counter = 0; in_out_vrr->btr.frame_counter = 0;
in_out_vrr->btr.mid_point_in_us = in_out_vrr->btr.mid_point_in_us =
(in_out_vrr->min_duration_in_us + (in_out_vrr->min_duration_in_us +
in_out_vrr->max_duration_in_us) / 2; in_out_vrr->max_duration_in_us) / 2;
......
...@@ -92,6 +92,7 @@ struct mod_vrr_params_btr { ...@@ -92,6 +92,7 @@ struct mod_vrr_params_btr {
uint32_t inserted_duration_in_us; uint32_t inserted_duration_in_us;
uint32_t frames_to_insert; uint32_t frames_to_insert;
uint32_t frame_counter; uint32_t frame_counter;
uint32_t margin_in_us;
}; };
struct mod_vrr_params_fixed_refresh { struct mod_vrr_params_fixed_refresh {
......
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