[PATCH] leds: pwm: Fix active-low brightness with default-state keep

From: raoxu

Date: Mon Nov 09 2026 - 04:13:00 EST


From: Xu Rao <raoxu@xxxxxxxxxxxxx>

With default-state set to "keep", led_pwm_add() derives the initial
brightness from the PWM duty cycle without accounting for active-low
LEDs. However, led_pwm_set() inverts the duty cycle for these LEDs.

For an enabled active-low PWM with zero duty cycle, the LED is fully
on but its cached brightness is set to zero. Conversely, a full duty
cycle is reported as maximum brightness instead of off. This exposes
an incorrect brightness to userspace and can restore the wrong value
after suspend. With an optional enable GPIO, the incorrect brightness
also causes the wrong initial GPIO level to be selected.

Invert the computed brightness for active-low LEDs, matching the
conversion used by led_pwm_set() while leaving the PWM state intact.

The supplied fix was reviewed and this commit message prepared with
OpenCode AI assistance.

Fixes: 3d3d65bd2764 ("leds: pwm: add support for default-state device property")
Signed-off-by: Xu Rao <raoxu@xxxxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
---
drivers/leds/leds-pwm.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 6c1f2f50ff85..da307767dbe8 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -131,6 +131,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
brightness = led->max_brightness;
brightness *= led_data->pwmstate.duty_cycle;
do_div(brightness, led_data->pwmstate.period);
+ if (led_data->active_low)
+ brightness = led->max_brightness - brightness;
led_data->cdev.brightness = brightness;
}
break;
--
2.50.1