From: Mario Limonciello <mario.limoncie...@amd.com>

[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.h...@amd.com>
Signed-off-by: Mario Limonciello <mario.limoncie...@amd.com>
Signed-off-by: Alex Hung <alex.h...@amd.com>
Tested-by: Dan Wheeler <daniel.whee...@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 64 +++++++++++--------
 1 file changed, 38 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 12eb1a91a4e9..242f98564261 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4817,8 +4817,8 @@ static void convert_custom_brightness(const struct 
amdgpu_dm_backlight_caps *cap
                                      uint32_t *user_brightness)
 {
        u32 brightness = scale_input_to_fw(min, max, *user_brightness);
-       u8 prev_signal = 0, prev_lum = 0;
-       int i = 0;
+       u8 lower_signal, upper_signal, upper_lum, lower_lum, lum;
+       int left, right;
 
        if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)
                return;
@@ -4826,32 +4826,44 @@ static void convert_custom_brightness(const struct 
amdgpu_dm_backlight_caps *cap
        if (!caps->data_points)
                return;
 
-       /* choose start to run less interpolation steps */
-       if (caps->luminance_data[caps->data_points/2].input_signal > brightness)
-               i = caps->data_points/2;
-       do {
-               u8 signal = caps->luminance_data[i].input_signal;
-               u8 lum = caps->luminance_data[i].luminance;
+       left = 0;
+       right = caps->data_points - 1;
+       while (left <= right) {
+               int mid = left + (right - left) / 2;
+               u8 signal = caps->luminance_data[mid].input_signal;
 
-               /*
-                * brightness == signal: luminance is percent numerator
-                * brightness < signal: interpolate between previous and 
current luminance numerator
-                * brightness > signal: find next data point
-                */
-               if (brightness > signal) {
-                       prev_signal = signal;
-                       prev_lum = lum;
-                       i++;
-                       continue;
+               /* Exact match found */
+               if (signal == brightness) {
+                       lum = caps->luminance_data[mid].luminance;
+                       goto scale;
                }
-               if (brightness < signal)
-                       lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
-                                                          (brightness - 
prev_signal),
-                                                          signal - 
prev_signal);
-               *user_brightness = scale_fw_to_input(min, max,
-                                                    DIV_ROUND_CLOSEST(lum * 
brightness, 101));
-               return;
-       } while (i < caps->data_points);
+
+               if (signal < brightness)
+                       left = mid + 1;
+               else
+                       right = mid - 1;
+       }
+
+       /* verify bound */
+       if (left >= caps->data_points)
+               left = caps->data_points - 1;
+
+       /* At this point, left > right */
+       lower_signal = caps->luminance_data[right].input_signal;
+       upper_signal = caps->luminance_data[left].input_signal;
+       lower_lum = caps->luminance_data[right].luminance;
+       upper_lum = caps->luminance_data[left].luminance;
+
+       /* interpolate */
+       if (right == left || !lower_lum)
+               lum = upper_lum;
+       else
+               lum = lower_lum + DIV_ROUND_CLOSEST((upper_lum - lower_lum) *
+                                                   (brightness - lower_signal),
+                                                   upper_signal - 
lower_signal);
+scale:
+       *user_brightness = scale_fw_to_input(min, max,
+                                            DIV_ROUND_CLOSEST(lum * 
brightness, 101));
 }
 
 static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps 
*caps,
-- 
2.43.0

Reply via email to