mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
leds: st1202: Disable channel when brightness is set to zero
When brightness_set() is called with LED_OFF, only the ILED register is
zeroed; the channel enable bit is left set from probe time. A hardware
channel enabled with ILED=0 still draws a small residual current, causing
a dim glow even when the LED is supposed to be off.
Fix this by splitting st1202_channel_set() into a lockless inner function
__st1202_channel_set() and a locking wrapper, then calling the inner
function from brightness_set() while it already holds the mutex. The
channel is now disabled when value is zero and re-enabled when non-zero,
in the same lock region as the ILED write.
Fixes: 259230378c ("leds: Add LED1202 I2C driver")
Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Assisted-by: Claude:claude-sonnet-4-6
Link: https://patch.msgid.link/GV1PR08MB8497F11B30FE7D74CAA25135C5F52@GV1PR08MB8497.eurprd08.prod.outlook.com
Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
committed by
Lee Jones
parent
7cbe470366
commit
0767335233
+39
-29
@@ -128,39 +128,11 @@ static int st1202_duration_pattern_write(struct st1202_chip *chip, int pattern,
|
||||
st1202_prescalar_to_miliseconds(value));
|
||||
}
|
||||
|
||||
static void st1202_brightness_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
|
||||
struct st1202_chip *chip = led->chip;
|
||||
|
||||
guard(mutex)(&chip->lock);
|
||||
|
||||
for (int patt = 0; patt < ST1202_MAX_PATTERNS; patt++)
|
||||
st1202_pwm_pattern_write(chip, led->led_num, patt, ST1202_PATTERN_PWM_FULL);
|
||||
st1202_write_reg(chip, ST1202_ILED_REG0 + led->led_num, value);
|
||||
}
|
||||
|
||||
static enum led_brightness st1202_brightness_get(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
|
||||
struct st1202_chip *chip = led->chip;
|
||||
u8 value = 0;
|
||||
|
||||
guard(mutex)(&chip->lock);
|
||||
|
||||
st1202_read_reg(chip, ST1202_ILED_REG0 + led->led_num, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active)
|
||||
static int __st1202_channel_set(struct st1202_chip *chip, int led_num, bool active)
|
||||
{
|
||||
u8 chan_low, chan_high;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&chip->lock);
|
||||
|
||||
if (led_num <= 7) {
|
||||
ret = st1202_read_reg(chip, ST1202_CHAN_ENABLE_LOW, &chan_low);
|
||||
if (ret < 0)
|
||||
@@ -188,6 +160,40 @@ static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int st1202_channel_set(struct st1202_chip *chip, int led_num, bool active)
|
||||
{
|
||||
guard(mutex)(&chip->lock);
|
||||
|
||||
return __st1202_channel_set(chip, led_num, active);
|
||||
}
|
||||
|
||||
static void st1202_brightness_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
|
||||
struct st1202_chip *chip = led->chip;
|
||||
|
||||
guard(mutex)(&chip->lock);
|
||||
|
||||
for (int patt = 0; patt < ST1202_MAX_PATTERNS; patt++)
|
||||
st1202_pwm_pattern_write(chip, led->led_num, patt, ST1202_PATTERN_PWM_FULL);
|
||||
st1202_write_reg(chip, ST1202_ILED_REG0 + led->led_num, value);
|
||||
__st1202_channel_set(chip, led->led_num, !!value);
|
||||
}
|
||||
|
||||
static enum led_brightness st1202_brightness_get(struct led_classdev *led_cdev)
|
||||
{
|
||||
struct st1202_led *led = cdev_to_st1202_led(led_cdev);
|
||||
struct st1202_chip *chip = led->chip;
|
||||
u8 value = 0;
|
||||
|
||||
guard(mutex)(&chip->lock);
|
||||
|
||||
st1202_read_reg(chip, ST1202_ILED_REG0 + led->led_num, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int st1202_led_set(struct led_classdev *ldev, enum led_brightness value)
|
||||
{
|
||||
struct st1202_led *led = cdev_to_st1202_led(ldev);
|
||||
@@ -257,6 +263,10 @@ static int st1202_led_pattern_set(struct led_classdev *ldev,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = __st1202_channel_set(chip, led->led_num, true);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = st1202_write_reg(chip, ST1202_CONFIG_REG, (ST1202_CONFIG_REG_PATSR |
|
||||
ST1202_CONFIG_REG_PATS | ST1202_CONFIG_REG_SHFT));
|
||||
if (ret != 0)
|
||||
|
||||
Reference in New Issue
Block a user