]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Optimize custom brightness curve
authorMario Limonciello <mario.limonciello@amd.com>
Mon, 24 Mar 2025 17:57:25 +0000 (12:57 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 7 Apr 2025 22:01:07 +0000 (18:01 -0400)
[Why]
When BIOS includes a lot of custom brightness data points, walking
the entire list can be time consuming.  This is most noticed when
dragging a power slider.  The "higher" values are "slower" to drag
around.

[How]
Move custom brightness calculation loop into a static function. Before
starting the loop check the "half way" data point to see how it compares
to the input.  If greater than the half way data point use that as the
starting point instead.

Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index f8847cf10dbd0c9af487cd96f9d8590f6cb3660c..f1de629c7637819dfb1957be55e7b834479f815e 100644 (file)
@@ -4826,41 +4826,54 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
        return 1;
 }
 
-static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
-                                       uint32_t brightness)
+static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
+                                     uint32_t *brightness)
 {
-       unsigned int min, max;
        u8 prev_signal = 0, prev_lum = 0;
+       int i = 0;
 
-       if (!get_brightness_range(caps, &min, &max))
-               return brightness;
-
-       for (int i = 0; i < caps->data_points; i++) {
-               u8 signal, lum;
+       if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)
+               return;
 
-               if (amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)
-                       break;
+       if (!caps->data_points)
+               return;
 
-               signal = caps->luminance_data[i].input_signal;
-               lum = caps->luminance_data[i].luminance;
+       /* 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;
 
                /*
                 * brightness == signal: luminance is percent numerator
                 * brightness < signal: interpolate between previous and current luminance numerator
                 * brightness > signal: find next data point
                 */
-               if (brightness < signal)
-                       lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
-                                                          (brightness - prev_signal),
-                                                          signal - prev_signal);
-               else if (brightness > signal) {
+               if (*brightness > signal) {
                        prev_signal = signal;
                        prev_lum = lum;
+                       i++;
                        continue;
                }
-               brightness = DIV_ROUND_CLOSEST(lum * brightness, 101);
-               break;
-       }
+               if (*brightness < signal)
+                       lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
+                                                          (*brightness - prev_signal),
+                                                          signal - prev_signal);
+               *brightness = DIV_ROUND_CLOSEST(lum * *brightness, 101);
+               return;
+       } while (i < caps->data_points);
+}
+
+static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
+                                       uint32_t brightness)
+{
+       unsigned int min, max;
+
+       if (!get_brightness_range(caps, &min, &max))
+               return brightness;
+
+       convert_custom_brightness(caps, &brightness);
 
        // Rescale 0..255 to min..max
        return min + DIV_ROUND_CLOSEST((max - min) * brightness,