From b506bc8657a698bb74daf9fc572c678b51ee396f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 Jul 2025 11:28:41 +0200 Subject: [PATCH] 6.15-stable patches added patches: drm-amd-display-export-full-brightness-range-to-userspace.patch drm-amd-display-fix-amdgpu_max_bl_level-value.patch drm-amd-display-only-read-acpi-backlight-caps-once.patch drm-amd-display-optimize-custom-brightness-curve.patch --- ...t-full-brightness-range-to-userspace.patch | 131 ++++++++++++++++++ ...isplay-fix-amdgpu_max_bl_level-value.patch | 63 +++++++++ ...y-only-read-acpi-backlight-caps-once.patch | 69 +++++++++ ...lay-optimize-custom-brightness-curve.patch | 108 +++++++++++++++ queue-6.15/series | 4 + 5 files changed, 375 insertions(+) create mode 100644 queue-6.15/drm-amd-display-export-full-brightness-range-to-userspace.patch create mode 100644 queue-6.15/drm-amd-display-fix-amdgpu_max_bl_level-value.patch create mode 100644 queue-6.15/drm-amd-display-only-read-acpi-backlight-caps-once.patch create mode 100644 queue-6.15/drm-amd-display-optimize-custom-brightness-curve.patch diff --git a/queue-6.15/drm-amd-display-export-full-brightness-range-to-userspace.patch b/queue-6.15/drm-amd-display-export-full-brightness-range-to-userspace.patch new file mode 100644 index 0000000000..2f163832c8 --- /dev/null +++ b/queue-6.15/drm-amd-display-export-full-brightness-range-to-userspace.patch @@ -0,0 +1,131 @@ +From 16dc8bc27c2aa3c93905d3e885e27f1e3535f09a Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Thu, 29 May 2025 09:46:32 -0500 +Subject: drm/amd/display: Export full brightness range to userspace + +From: Mario Limonciello + +commit 16dc8bc27c2aa3c93905d3e885e27f1e3535f09a upstream. + +[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 +Cc: Alex Deucher +Reviewed-by: Roman Li +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 8dbd72cb790058ce52279af38a43c2b302fdd3e5) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 ++++++++++++++-------- + 1 file changed, 27 insertions(+), 14 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4655,9 +4655,23 @@ static int get_brightness_range(const st + 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; + +@@ -4668,7 +4682,7 @@ static void convert_custom_brightness(co + 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; +@@ -4679,17 +4693,18 @@ static void convert_custom_brightness(co + * 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); + } +@@ -4702,11 +4717,10 @@ static u32 convert_brightness_from_user( + 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, +@@ -4719,8 +4733,8 @@ static u32 convert_brightness_to_user(co + + 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); + } + +@@ -4870,11 +4884,10 @@ amdgpu_dm_register_backlight_device(stru + 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", diff --git a/queue-6.15/drm-amd-display-fix-amdgpu_max_bl_level-value.patch b/queue-6.15/drm-amd-display-fix-amdgpu_max_bl_level-value.patch new file mode 100644 index 0000000000..9439515d6f --- /dev/null +++ b/queue-6.15/drm-amd-display-fix-amdgpu_max_bl_level-value.patch @@ -0,0 +1,63 @@ +From 66abb996999de0d440a02583a6e70c2c24deab45 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Mon, 23 Jun 2025 12:11:13 -0500 +Subject: drm/amd/display: Fix AMDGPU_MAX_BL_LEVEL value + +From: Mario Limonciello + +commit 66abb996999de0d440a02583a6e70c2c24deab45 upstream. + +[Why] +commit 16dc8bc27c2a ("drm/amd/display: Export full brightness range to +userspace") adjusted the brightness range to scale to larger values, but +missed updating AMDGPU_MAX_BL_LEVEL which is needed to make sure that +scaling works properly with custom brightness curves. + +[How] +As the change for max brightness of 0xFFFF only applies to devices +supporting DC, use existing DC define MAX_BACKLIGHT_LEVEL. + +Fixes: 16dc8bc27c2a ("drm/amd/display: Export full brightness range to userspace") +Acked-by: Alex Deucher +Link: https://lore.kernel.org/r/20250623171114.1156451-1-mario.limonciello@amd.com +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +(cherry picked from commit 5b852044eb0d3e1f1c946d32e05fcb068e0a20a0) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4655,16 +4655,16 @@ static int get_brightness_range(const st + return 1; + } + +-/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */ ++/* Rescale from [min..max] to [0..MAX_BACKLIGHT_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); ++ return DIV_ROUND_CLOSEST_ULL(input * MAX_BACKLIGHT_LEVEL, max - min); + } + +-/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */ ++/* Rescale from [0..MAX_BACKLIGHT_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); ++ return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), MAX_BACKLIGHT_LEVEL); + } + + static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps, +@@ -4884,7 +4884,7 @@ amdgpu_dm_register_backlight_device(stru + 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 = props.max_brightness = AMDGPU_MAX_BL_LEVEL; ++ props.brightness = props.max_brightness = MAX_BACKLIGHT_LEVEL; + + if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) + drm_info(drm, "Using custom brightness curve\n"); diff --git a/queue-6.15/drm-amd-display-only-read-acpi-backlight-caps-once.patch b/queue-6.15/drm-amd-display-only-read-acpi-backlight-caps-once.patch new file mode 100644 index 0000000000..0ef7df8b80 --- /dev/null +++ b/queue-6.15/drm-amd-display-only-read-acpi-backlight-caps-once.patch @@ -0,0 +1,69 @@ +From ffcaed1d7ecef31198000dfbbea791f30f7ca437 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Thu, 29 May 2025 11:33:44 -0500 +Subject: drm/amd/display: Only read ACPI backlight caps once + +From: Mario Limonciello + +commit ffcaed1d7ecef31198000dfbbea791f30f7ca437 upstream. + +[WHY] +Backlight caps are read already in amdgpu_dm_update_backlight_caps(). +They may be updated by update_connector_ext_caps(). Reading again when +registering backlight device may cause wrong values to be used. + +[HOW] +Use backlight caps already registered to the dm. + +Cc: Mario Limonciello +Cc: Alex Deucher +Reviewed-by: Roman Li +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Hung +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 148144f6d2f14b02eaaa39b86bbe023cbff350bd) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4832,7 +4832,7 @@ amdgpu_dm_register_backlight_device(stru + struct drm_device *drm = aconnector->base.dev; + struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm; + struct backlight_properties props = { 0 }; +- struct amdgpu_dm_backlight_caps caps = { 0 }; ++ struct amdgpu_dm_backlight_caps *caps; + char bl_name[16]; + int min, max; + +@@ -4846,20 +4846,20 @@ amdgpu_dm_register_backlight_device(stru + return; + } + +- amdgpu_acpi_get_backlight_caps(&caps); +- if (caps.caps_valid && get_brightness_range(&caps, &min, &max)) { ++ caps = &dm->backlight_caps[aconnector->bl_idx]; ++ if (get_brightness_range(caps, &min, &max)) { + if (power_supply_is_system_supplied() > 0) +- props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps.ac_level, 100); ++ props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->ac_level, 100); + else +- props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps.dc_level, 100); ++ props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->dc_level, 100); + /* min is zero, so max needs to be adjusted */ + props.max_brightness = max - min; + drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max, +- caps.ac_level, caps.dc_level); ++ caps->ac_level, caps->dc_level); + } else + props.brightness = AMDGPU_MAX_BL_LEVEL; + +- if (caps.data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) ++ 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; diff --git a/queue-6.15/drm-amd-display-optimize-custom-brightness-curve.patch b/queue-6.15/drm-amd-display-optimize-custom-brightness-curve.patch new file mode 100644 index 0000000000..d9227c4335 --- /dev/null +++ b/queue-6.15/drm-amd-display-optimize-custom-brightness-curve.patch @@ -0,0 +1,108 @@ +From 03b979e1025fba1d47cae005022fcdbba140f043 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Mon, 24 Mar 2025 12:57:25 -0500 +Subject: drm/amd/display: Optimize custom brightness curve + +From: Mario Limonciello + +commit 03b979e1025fba1d47cae005022fcdbba140f043 upstream. + +[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 +Signed-off-by: Mario Limonciello +Signed-off-by: Roman Li +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 53 +++++++++++++--------- + 1 file changed, 33 insertions(+), 20 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -4655,41 +4655,54 @@ static int get_brightness_range(const st + 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, diff --git a/queue-6.15/series b/queue-6.15/series index c6970d09e1..933aac67ea 100644 --- a/queue-6.15/series +++ b/queue-6.15/series @@ -258,3 +258,7 @@ io_uring-gate-req_f_isreg-on-s_anon_inode-as-well.patch riscv-uaccess-only-restore-the-csr_status-sum-bit.patch drm-amd-display-add-debugging-message-for-brightness-caps.patch drm-amd-display-fix-default-dc-and-ac-levels.patch +drm-amd-display-only-read-acpi-backlight-caps-once.patch +drm-amd-display-optimize-custom-brightness-curve.patch +drm-amd-display-export-full-brightness-range-to-userspace.patch +drm-amd-display-fix-amdgpu_max_bl_level-value.patch -- 2.39.5