mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
leds: class: Remove hardware control trigger when writing brightness
Since commitb819dc7d8f("leds: core: Report ENODATA for brightness of hardware controlled LED"), the brightness attribute becomes write-only when the LED is controlled fully by the hardware. A write-only attribute is very confusing. Moreover, most LED drivers set hardware brightness innocently with the side effect of disabling hardware control, but the hardware control trigger remains active, resulting in the software and hardware being out of sync. Fix it by removing the hardware control trigger when writing the brightness attribute. This should also match the semantics of hardware control: When the LED is in hw control, no software blink is possible and doing so will effectively disable hw control. Fixes:b819dc7d8f("leds: core: Report ENODATA for brightness of hardware controlled LED") Acked-by: Ike Panhc <ikepanhc@gmail.com> Signed-off-by: Rong Zhang <i@rong.moe> Link: https://patch.msgid.link/20260921-leds-trigger-hw-changed-v7-3-fe3cdb6dec51@rong.moe Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
parent
7879d62774
commit
96b4ddd6d2
|
|
@ -28,7 +28,9 @@ Description:
|
|||
Writing 0 to this file clears active trigger.
|
||||
|
||||
Writing non-zero to this file while trigger is active changes the
|
||||
top brightness trigger is going to use.
|
||||
top brightness trigger is going to use, unless the current
|
||||
trigger is offloaded to hardware (in which case writing any
|
||||
value will deactivate the trigger).
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ static ssize_t brightness_store(struct device *dev,
|
|||
|
||||
if (state == LED_OFF)
|
||||
led_trigger_remove(led_cdev);
|
||||
else
|
||||
led_trigger_remove_hw_control(led_cdev);
|
||||
|
||||
led_set_brightness(led_cdev, state);
|
||||
|
||||
ret = size;
|
||||
|
|
|
|||
|
|
@ -287,6 +287,15 @@ void led_trigger_remove(struct led_classdev *led_cdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(led_trigger_remove);
|
||||
|
||||
void led_trigger_remove_hw_control(struct led_classdev *led_cdev)
|
||||
{
|
||||
guard(rwsem_write)(&led_cdev->trigger_lock);
|
||||
|
||||
if (__led_trigger_is_hw_controlled(led_cdev))
|
||||
led_trigger_set(led_cdev, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(led_trigger_remove_hw_control);
|
||||
|
||||
static bool led_match_default_trigger(struct led_classdev *led_cdev,
|
||||
struct led_trigger *trig)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -533,6 +533,7 @@ void led_trigger_blink_oneshot(struct led_trigger *trigger,
|
|||
void led_trigger_set_default(struct led_classdev *led_cdev);
|
||||
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger);
|
||||
void led_trigger_remove(struct led_classdev *led_cdev);
|
||||
void led_trigger_remove_hw_control(struct led_classdev *led_cdev);
|
||||
|
||||
bool led_trigger_is_hw_controlled(struct led_classdev *led_cdev);
|
||||
|
||||
|
|
@ -586,6 +587,7 @@ static inline int led_trigger_set(struct led_classdev *led_cdev,
|
|||
}
|
||||
|
||||
static inline void led_trigger_remove(struct led_classdev *led_cdev) {}
|
||||
static inline void led_trigger_remove_hw_control(struct led_classdev *led_cdev) {}
|
||||
|
||||
static inline bool led_trigger_is_hw_controlled(struct led_classdev *led_cdev)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user