[PATCH RFT 1/3] drm/amd/display: Add the AUX backlight minimum once on the custom curve
From: Hugo Sales
Date: Wed Nov 04 2026 - 09:36:48 EST
On an AUX backlight, convert_brightness_from_user() maps the user level
through the ATIF custom brightness curve with
convert_custom_brightness(), which rescales the result to
user_min..user_max. convert_brightness_from_user() then rescales it
again, from 0..user_max to user_min..user_max, so the minimum goes in
twice. On the 1..512 nits AUX fallback range, a request for 0 gives
1998 millinits instead of 1000
Rescale the curve's output to 0..user_max and leave the offset to the
caller
Fixes: 16dc8bc27c2aa ("drm/amd/display: Export full brightness range to userspace")
Signed-off-by: Hugo Sales <hugo@xxxxxxx>
---
I saw this on my laptop, an ASUS ROG Flow X13 GV301QH, with 7.2.9, when
PWM still went through this code: the amdgpu_dm_brightness trace showed
requested=0 converted=6023, where 3084 is the minimum. Commit
d422a66847a9 ("drm/amd/display: map PWM brightness through custom
backlight curve"), in 7.2.10, moved PWM off this path, but on current
kernels it still hits an AUX panel with an ATIF curve. On older stable
kernels this fixes PWM too
With amdgpu.backlight=1, which forces AUX, the GV301QH uses the 1..512
nits fallback range. There the floor goes from 1998 to 1000 millinits,
the midpoint from 159999 to 159310 and the top from 496000 to 495968.
The rounding of the level to 8 bits and of the luminance to a whole
percent stays as it is
No existing test changes: they all run with a minimum of 0, where adding
it twice makes no difference. Patch 3 adds one with a non-zero minimum
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c | 9 ++++-----
.../amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c | 14 +++++++-------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
index 27546febf90d3..8b49cbcde91cd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_backlight.c
@@ -122,10 +122,10 @@ static inline u32 scale_input_to_fw(int max, u64 input)
return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max);
}
-/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */
-static inline u32 scale_fw_to_input(int min, int max, u64 input)
+/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [0..max] */
+static inline u32 scale_fw_to_input(int max, u64 input)
{
- return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL);
+ return DIV_ROUND_CLOSEST_ULL(input * max, AMDGPU_MAX_BL_LEVEL);
}
static u32 backlight_signal_to_luminance(const struct amdgpu_dm_backlight_caps *caps,
@@ -251,8 +251,7 @@ void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
(brightness - lower_signal),
upper_signal - lower_signal);
scale:
- *user_brightness = scale_fw_to_input(min, max,
- DIV_ROUND_CLOSEST(lum * brightness, 101));
+ *user_brightness = scale_fw_to_input(max, DIV_ROUND_CLOSEST(lum * brightness, 101));
}
EXPORT_IF_KUNIT(convert_custom_brightness);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
index c6d15fb8ad989..2d7a07d9ad874 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_backlight_test.c
@@ -1125,10 +1125,10 @@ static void dm_test_custom_brightness_exact_match(struct kunit *test)
/*
* Exact match: lum=50, brightness_scaled=128
- * result = scale_fw_to_input(min, max, DIV_ROUND_CLOSEST(50*128, 101))
- * = scale_fw_to_input(0, 65535, DIV_ROUND_CLOSEST(6400, 101))
- * = scale_fw_to_input(0, 65535, 63)
- * = 0 + DIV_ROUND_CLOSEST(63 * 65535, 255) = 16191 (approx)
+ * result = scale_fw_to_input(max, DIV_ROUND_CLOSEST(50*128, 101))
+ * = scale_fw_to_input(65535, DIV_ROUND_CLOSEST(6400, 101))
+ * = scale_fw_to_input(65535, 63)
+ * = DIV_ROUND_CLOSEST(63 * 65535, 255) = 16191 (approx)
*/
KUNIT_EXPECT_TRUE(test, brightness != 32896);
KUNIT_EXPECT_TRUE(test, brightness < 32896);
@@ -1171,9 +1171,9 @@ static void dm_test_custom_brightness_below_first(struct kunit *test)
/*
* Below first data point: lum = DIV_ROUND_CLOSEST(40 * 50, 100) = 20
- * Then: scale_fw_to_input(0, 65535, DIV_ROUND_CLOSEST(20 * 50, 101))
- * = scale_fw_to_input(0, 65535, DIV_ROUND_CLOSEST(1000, 101))
- * = scale_fw_to_input(0, 65535, 10)
+ * Then: scale_fw_to_input(65535, DIV_ROUND_CLOSEST(20 * 50, 101))
+ * = scale_fw_to_input(65535, DIV_ROUND_CLOSEST(1000, 101))
+ * = scale_fw_to_input(65535, 10)
* The output should be significantly less than input.
*/
KUNIT_EXPECT_TRUE(test, brightness < 12850);
--
2.56.0