Skip to content

Commit de63b05

Browse files
superm1alexdeucher
authored andcommitted
drm/amd/display: Optimize custom brightness curve interpolation
[Why] Custom brightness curve works by walking through all data points one by one. When the brightness value is at either extreme this is a lot of data points to walk. This is especially noticeable when moving a brightness slider around how it can lag. [How] Bisect the data points to find the closest for interpolation. Reviewed-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 002a612 commit de63b05

1 file changed

Lines changed: 38 additions & 26 deletions

File tree

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4817,41 +4817,53 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *cap
48174817
uint32_t *user_brightness)
48184818
{
48194819
u32 brightness = scale_input_to_fw(min, max, *user_brightness);
4820-
u8 prev_signal = 0, prev_lum = 0;
4821-
int i = 0;
4820+
u8 lower_signal, upper_signal, upper_lum, lower_lum, lum;
4821+
int left, right;
48224822

48234823
if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)
48244824
return;
48254825

48264826
if (!caps->data_points)
48274827
return;
48284828

4829-
/* choose start to run less interpolation steps */
4830-
if (caps->luminance_data[caps->data_points/2].input_signal > brightness)
4831-
i = caps->data_points/2;
4832-
do {
4833-
u8 signal = caps->luminance_data[i].input_signal;
4834-
u8 lum = caps->luminance_data[i].luminance;
4829+
left = 0;
4830+
right = caps->data_points - 1;
4831+
while (left <= right) {
4832+
int mid = left + (right - left) / 2;
4833+
u8 signal = caps->luminance_data[mid].input_signal;
48354834

4836-
/*
4837-
* brightness == signal: luminance is percent numerator
4838-
* brightness < signal: interpolate between previous and current luminance numerator
4839-
* brightness > signal: find next data point
4840-
*/
4841-
if (brightness > signal) {
4842-
prev_signal = signal;
4843-
prev_lum = lum;
4844-
i++;
4845-
continue;
4835+
/* Exact match found */
4836+
if (signal == brightness) {
4837+
lum = caps->luminance_data[mid].luminance;
4838+
goto scale;
48464839
}
4847-
if (brightness < signal)
4848-
lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
4849-
(brightness - prev_signal),
4850-
signal - prev_signal);
4851-
*user_brightness = scale_fw_to_input(min, max,
4852-
DIV_ROUND_CLOSEST(lum * brightness, 101));
4853-
return;
4854-
} while (i < caps->data_points);
4840+
4841+
if (signal < brightness)
4842+
left = mid + 1;
4843+
else
4844+
right = mid - 1;
4845+
}
4846+
4847+
/* verify bound */
4848+
if (left >= caps->data_points)
4849+
left = caps->data_points - 1;
4850+
4851+
/* At this point, left > right */
4852+
lower_signal = caps->luminance_data[right].input_signal;
4853+
upper_signal = caps->luminance_data[left].input_signal;
4854+
lower_lum = caps->luminance_data[right].luminance;
4855+
upper_lum = caps->luminance_data[left].luminance;
4856+
4857+
/* interpolate */
4858+
if (right == left || !lower_lum)
4859+
lum = upper_lum;
4860+
else
4861+
lum = lower_lum + DIV_ROUND_CLOSEST((upper_lum - lower_lum) *
4862+
(brightness - lower_signal),
4863+
upper_signal - lower_signal);
4864+
scale:
4865+
*user_brightness = scale_fw_to_input(min, max,
4866+
DIV_ROUND_CLOSEST(lum * brightness, 101));
48554867
}
48564868

48574869
static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,

0 commit comments

Comments
 (0)