[PATCH v2] leds: pca9532: don't stop blinking for non-zero brightness

Tobias Deiminger posted 1 patch 10 hours ago
drivers/leds/leds-pca9532.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
[PATCH v2] leds: pca9532: don't stop blinking for non-zero brightness
Posted by Tobias Deiminger 10 hours ago
pca9532 unexpectedly stopped blinking when changing brightness to a
non-zero value. To reproduce:

 echo timer > /sys/class/leds/led-1/trigger   # blinks
 echo 255 > /sys/class/leds/led-1/brightness  # blinking stops, light on
 cat /sys/class/leds/led-1/trigger            # still claims [timer]

According to Documentation/leds/leds-class.rst, only brightness = 0
shall be a stop condition:

> You can change the brightness value of a LED independently of the
> timer trigger. However, if you set the brightness value to LED_OFF it
> will also disable the timer trigger.

Therefore add a guard to continue blinking when brightness != LED_OFF,
similar to how pca955x does it since 575f10dc64a2 ("leds: pca955x: Add
HW blink support").

Signed-off-by: Tobias Deiminger <tobias.deiminger@linutronix.de>
---
Changes in v2:
- Fix code style (capitalize start of comment, brace-placement).
- Link to v1: https://lore.kernel.org/r/20260321102121.1563365-1-tobias.deiminger@linutronix.de

Notes:
    A more advanced solution was to not simply return early on
    set_brightness, but actually support blinking at arbitrary brightness.
    This would however require conditional fallback to SW blinking, since
    PCA 9532 doesn't support routing PWM 0 (dim) and PWM 1 (blink) in
    series. The bugfix here keeps it simple. Optional SW blinking could be
    tried in a separate patch.

 drivers/leds/leds-pca9532.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 0344189bb991..dae7c6760508 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -182,11 +182,13 @@ static int pca9532_set_brightness(struct led_classdev *led_cdev,
 	int err = 0;
 	struct pca9532_led *led = ldev_to_led(led_cdev);
 
-	if (value == LED_OFF)
+	if (value == LED_OFF) {
 		led->state = PCA9532_OFF;
-	else if (value == LED_FULL)
+	} else if (led->state == PCA9532_PWM1) {
+		return 0; /* Non-zero brightness shall not stop HW blinking */
+	} else if (value == LED_FULL) {
 		led->state = PCA9532_ON;
-	else {
+	} else {
 		led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
 		err = pca9532_calcpwm(led->client, PCA9532_PWM_ID_0, 0, value);
 		if (err)

base-commit: b2c87f5e98cd88095dbc6802197526703d5e4e48
-- 
2.47.3