mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
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: 259230378c ("leds: Add LED1202 I2C driver")
Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Assisted-by: LLM
Link: https://patch.msgid.link/GV1PR08MB8497B938D3592582E17CB757C5BA2@GV1PR08MB8497.eurprd08.prod.outlook.com
Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
parent
119a7d375e
commit
82f8b88d6a
|
|
@ -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 ..."
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user