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: Anthony Koo <Anthony.Koo@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Anthony Koo 2020-07-29 17:33:27 -04:00 committed by Alex Deucher
parent c0c96fc9c2
commit 575da8db31
1 changed files with 31 additions and 9 deletions

View File

@ -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
* 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 &&
(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;
delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
delta_from_mid_point_in_us_1;
} else {
if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) {
/* Check for out of range.
* 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;
} 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;
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
* 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 &&
delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <