Commit e4ed4dbb authored by Anthony Koo's avatar Anthony Koo Committed by Alex Deucher

drm/amd/display: Fix LFC multiplier changing erratically

[Why]
1. There is a calculation that is using frame_time_in_us instead of
last_render_time_in_us to calculate whether choosing an LFC multiplier
would cause the inserted frame duration to be outside of range.

2. We do not handle unsigned integer subtraction correctly and it underflows
to a really large value, which causes some logic errors.

[How]
1. Fix logic to calculate 'within range' using last_render_time_in_us
2. Split out delta_from_mid_point_delta_in_us calculation to ensure
we don't underflow and wrap around
Signed-off-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a49f6727
...@@ -324,22 +324,44 @@ static void apply_below_the_range(struct core_freesync *core_freesync, ...@@ -324,22 +324,44 @@ 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.
* - Delta for CEIL: delta_from_mid_point_in_us_1
* - Delta for FLOOR: delta_from_mid_point_in_us_2
*/ */
if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us && if ((last_render_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 || /* Check for out of range.
mid_point_frames_floor < 2)) { * If using CEIL produces a value that is out of range,
* then we are forced to use FLOOR.
*/
frames_to_insert = mid_point_frames_floor;
} else if (mid_point_frames_floor < 2) {
/* Check if FLOOR would result in non-LFC. In this case
* choose to use CEIL
*/
frames_to_insert = mid_point_frames_ceil;
} else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
/* If choosing CEIL results in a frame duration that is
* closer to the mid point of the range.
* Choose CEIL
*/
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_in_us_1;
} else { } else {
/* If choosing FLOOR results in a frame duration that is
* closer to the mid point of the range.
* Choose FLOOR
*/
frames_to_insert = mid_point_frames_floor; frames_to_insert = mid_point_frames_floor;
delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 -
delta_from_mid_point_in_us_2;
} }
/* Prefer current frame multiplier when BTR is enabled unless it drifts /* Prefer current frame multiplier when BTR is enabled unless it drifts
* too far from the midpoint * too far from the midpoint
*/ */
if (delta_from_mid_point_in_us_1 < 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;
} else {
delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 -
delta_from_mid_point_in_us_2;
}
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) <
......
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