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

[WHY]
Userspace currently is offered a range from 0-0xFF but the PWM is
programmed from 0-0xFFFF.  This can be limiting to some software
that wants to apply greater granularity.

[HOW]
Convert internally to firmware values only when mapping custom
brightness curves because these are in 0-0xFF range. Advertise full
PWM range to userspace.

Cc: Mario Limonciello <mario.limoncie...@amd.com>
Cc: Alex Deucher <alexander.deuc...@amd.com>
Cc: sta...@vger.kernel.org
Reviewed-by: Roman Li <roman...@amd.com>
Signed-off-by: Mario Limonciello <mario.limoncie...@amd.com>
Signed-off-by: Alex Hung <alex.h...@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 ++++++++++++-------
 1 file changed, 27 insertions(+), 14 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 31df545f8c0f..19d38357f508 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4721,9 +4721,23 @@ static int get_brightness_range(const struct 
amdgpu_dm_backlight_caps *caps,
        return 1;
 }
 
+/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */
+static inline u32 scale_input_to_fw(int min, int max, u64 input)
+{
+       return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min);
+}
+
+/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */
+static inline u32 scale_fw_to_input(int min, int max, u64 input)
+{
+       return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), 
AMDGPU_MAX_BL_LEVEL);
+}
+
 static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps 
*caps,
-                                     uint32_t *brightness)
+                                     unsigned int min, unsigned int max,
+                                     uint32_t *user_brightness)
 {
+       u32 brightness = scale_input_to_fw(min, max, *user_brightness);
        u8 prev_signal = 0, prev_lum = 0;
        int i = 0;
 
@@ -4734,7 +4748,7 @@ static void convert_custom_brightness(const struct 
amdgpu_dm_backlight_caps *cap
                return;
 
        /* choose start to run less interpolation steps */
-       if (caps->luminance_data[caps->data_points/2].input_signal > 
*brightness)
+       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;
@@ -4745,17 +4759,18 @@ static void convert_custom_brightness(const struct 
amdgpu_dm_backlight_caps *cap
                 * brightness < signal: interpolate between previous and 
current luminance numerator
                 * brightness > signal: find next data point
                 */
-               if (*brightness > signal) {
+               if (brightness > signal) {
                        prev_signal = signal;
                        prev_lum = lum;
                        i++;
                        continue;
                }
-               if (*brightness < signal)
+               if (brightness < signal)
                        lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
-                                                          (*brightness - 
prev_signal),
+                                                          (brightness - 
prev_signal),
                                                           signal - 
prev_signal);
-               *brightness = DIV_ROUND_CLOSEST(lum * *brightness, 101);
+               *user_brightness = scale_fw_to_input(min, max,
+                                                    DIV_ROUND_CLOSEST(lum * 
brightness, 101));
                return;
        } while (i < caps->data_points);
 }
@@ -4768,11 +4783,10 @@ static u32 convert_brightness_from_user(const struct 
amdgpu_dm_backlight_caps *c
        if (!get_brightness_range(caps, &min, &max))
                return brightness;
 
-       convert_custom_brightness(caps, &brightness);
+       convert_custom_brightness(caps, min, max, &brightness);
 
-       // Rescale 0..255 to min..max
-       return min + DIV_ROUND_CLOSEST((max - min) * brightness,
-                                      AMDGPU_MAX_BL_LEVEL);
+       // Rescale 0..max to min..max
+       return min + DIV_ROUND_CLOSEST_ULL((u64)(max - min) * brightness, max);
 }
 
 static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps 
*caps,
@@ -4785,8 +4799,8 @@ static u32 convert_brightness_to_user(const struct 
amdgpu_dm_backlight_caps *cap
 
        if (brightness < min)
                return 0;
-       // Rescale min..max to 0..255
-       return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min),
+       // Rescale min..max to 0..max
+       return DIV_ROUND_CLOSEST_ULL((u64)max * (brightness - min),
                                 max - min);
 }
 
@@ -4936,11 +4950,10 @@ amdgpu_dm_register_backlight_device(struct 
amdgpu_dm_connector *aconnector)
                drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc 
%d\n", min, max,
                        caps->ac_level, caps->dc_level);
        } else
-               props.brightness = AMDGPU_MAX_BL_LEVEL;
+               props.brightness = props.max_brightness = AMDGPU_MAX_BL_LEVEL;
 
        if (caps->data_points && !(amdgpu_dc_debug_mask & 
DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE))
                drm_info(drm, "Using custom brightness curve\n");
-       props.max_brightness = AMDGPU_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
 
        snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
-- 
2.43.0

Reply via email to