From 82f8b88d6ac2edf01651bbd84e03ede04b2ca80e Mon Sep 17 00:00:00 2001 From: Manuel Fombuena Date: Tue, 15 Sep 2026 13:45:01 +0100 Subject: [PATCH] leds: st1202: Scale pattern brightness to the 12-bit PWM range The LED1202 PWM registers are 12 bits wide, but st1202_led_pattern_set() writes the 8-bit brightness value carried by struct led_pattern into them unscaled. A pattern step asking for full brightness therefore drives the channel at 255 out of 4095, about 6% duty cycle, so a pattern is dimmer than the same brightness set directly. Scale the value to the full PWM range before programming it. Scale against max_brightness rather than the register maximum. The LED core takes max_brightness from the DT max-brightness property, so a board can declare a ceiling below full scale, and the pattern trigger already rejects steps above it. Scaling against a hardcoded 255 would leave such a board unable to reach its own declared maximum from the pattern path while the brightness path reaches it. Scaling divides by max_brightness. The LED core replaces a zero max-brightness from the device tree with LED_FULL, so the divisor should never be zero, but the helper returns zero rather than rely on that. max_brightness is capped at U8_MAX, the driver's own maximum, so a device tree declaring more than the part supports is treated as full scale. struct led_pattern brightness is signed, so clamp both ends and floor a negative value to LED_OFF rather than let it wrap. Document that a step is relative to max_brightness, since the range given in the documentation no longer holds when the device tree sets max-brightness. Fixes: 259230378c65 ("leds: Add LED1202 I2C driver") Signed-off-by: Manuel Fombuena Assisted-by: LLM Link: https://patch.msgid.link/GV1PR08MB8497B938D3592582E17CB757C5BA2@GV1PR08MB8497.eurprd08.prod.outlook.com Signed-off-by: Lee Jones --- Documentation/leds/leds-st1202.rst | 5 +++++ drivers/leds/leds-st1202.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Documentation/leds/leds-st1202.rst b/Documentation/leds/leds-st1202.rst index ed32eb3a27d4..28479a112389 100644 --- a/Documentation/leds/leds-st1202.rst +++ b/Documentation/leds/leds-st1202.rst @@ -20,6 +20,11 @@ brightness (PWM) and duration must be written to hw_pattern. - Min pattern duration: 22 ms - Max pattern duration: 5610 ms +If the device tree sets max-brightness, that value replaces 255 as the +upper limit, and a step equal to it drives the channel at full scale. +The hardware cannot go above 255, so with a larger max-brightness every +step from 255 upwards is full scale. + The format of the hardware pattern values should be: "brightness duration brightness duration ..." diff --git a/drivers/leds/leds-st1202.c b/drivers/leds/leds-st1202.c index 9985b4b60989..5558ac9612a1 100644 --- a/drivers/leds/leds-st1202.c +++ b/drivers/leds/leds-st1202.c @@ -91,6 +91,16 @@ static u8 st1202_milliseconds_to_prescaler(unsigned int value) return value / ST1202_MILLIS_PATTERN_DUR_MIN; } +static u16 st1202_brightness_to_pwm(int brightness, unsigned int max_brightness) +{ + if (!max_brightness) + return 0; + + brightness = clamp_t(int, brightness, LED_OFF, max_brightness); + + return brightness * ST1202_PATTERN_PWM_FULL / max_brightness; +} + static int st1202_pwm_pattern_write(struct st1202_chip *chip, int led_num, int pattern, unsigned int value) { @@ -235,8 +245,11 @@ static int st1202_led_pattern_set(struct led_classdev *ldev, { struct st1202_led *led = cdev_to_st1202_led(ldev); struct st1202_chip *chip = led->chip; + unsigned int max_brightness; int ret; + max_brightness = min_t(unsigned int, ldev->max_brightness, U8_MAX); + if (len > ST1202_MAX_PATTERNS) return -EINVAL; @@ -254,7 +267,8 @@ static int st1202_led_pattern_set(struct led_classdev *ldev, for (int pattern = 0; pattern < len; pattern++) { ret = st1202_pwm_pattern_write(chip, led->led_num, pattern, - patterns[pattern].brightness); + st1202_brightness_to_pwm(patterns[pattern].brightness, + max_brightness)); if (ret != 0) return ret;