[PATCH v8 0/3] platform/x86: ideapad-laptop: Fully support auto keyboard backlight
From: Rong Zhang
Date: Tue Nov 10 2026 - 10:58:44 EST
Currently, the auto brightness mode of keyboard backlight maps to
brightness=0 in LED classdev. The only method to switch to such a mode
is by pressing the manufacturer-defined shortcut (Fn+Space). However, 0
is a multiplexed brightness value; writing 0 simply results in the
backlight being turned off.
Decouple brightness processing code from LED classdev, and add full
support for the auto brightness mode. In this mode, the keyboard
backlight is controlled by the EC according to the ambient light sensor
(ALS).
To utilize this, a private hardware control trigger "ideapad-auto" is
added, with the event handling procedure calling the
led_trigger_notify_hw_control_changed() interface to activate/deactivate
the private trigger according to the current LED trigger state. To align
with LEDS_BRIGHTNESS_HW_CHANGED, the driver neither depends on
LEDS_TRIGGERS_HW_CHANGED nor selects it.
Meanwhile, block brightness changes on exit to prevent the side effect
of LED device unregistration when the private trigger is active from
resetting the brightness to zero, so that the state of auto mode can
retain among boots.
Acked-by: Ike Panhc <ikepanhc@xxxxxxxxx>
Signed-off-by: Rong Zhang <i@xxxxxxxx>
---
Changes in v8:
- Replace unreachable() with an explicit return to work around
miscompilation under certain combination of toolchains (found by
kernel test robot, off-list, thanks Ilpo Järvinen)
- Remove applied material
- Link to v7: https://patch.msgid.link/20260921-leds-trigger-hw-changed-v7-0-fe3cdb6dec51@xxxxxxxx
Changes in v7:
- Add a new patch to the series to collect existing trigger attribute
stuff together into led-triggers.c (thanks Lee Jones)
- Leave all new attribute stuff at led-triggers.c (ditto)
- Rename the offloaded() callback to hw_offloaded() (ditto)
- Rename the trigger_may_offload attribute to
trigger_may_offload_to_hw (ditto)
- Use "[foo_trigger]" to represent a selected and offloaded trigger, and
no longer use a dedicated container to represent selected but not
offloaded ones (ditto)
- Remove messages mainly for debugging (ditto)
- Inline led_trigger_{init,destroy}_hw_changed() into led-class.c by
exporting led_trigger_hw_control_changed_worker() (ditto)
- Rephrase some comments and messages (ditto)
- Constify device attribute trigger_may_offload_to_hw
- Address a concern from Sashiko
- Fix printf format string
- https://sashiko.dev/#/patchset/20260902-leds-trigger-hw-changed-v6-0-55693cd78877@xxxxxxxx?part=11
- Link to v6: https://patch.msgid.link/20260902-leds-trigger-hw-changed-v6-0-55693cd78877@xxxxxxxx
Changes in v6:
- New patch in the series to address a concern from Sashiko
- [PATCH 1] leds: class: Always protect brightness_show() with led_access
- https://sashiko.dev/#/patchset/20260821-leds-trigger-hw-changed-v5-0-3e00d6c4a936@xxxxxxxx?part=7
- Update Date: and KernelVersion: for the document of
/sys/class/leds/<led>/trigger_may_offload
- Implement workqueue deferal mechanism
- Protects ideapad_kbd_bl_led_cdev_brightness_set() with the new mutex
as well
- No longer convert last_hw_brightness into atomic_t as it's not
required now
- https://msgid.link/e2b081dfd8f96511a73b86ab3ec75e5cd759b79b.camel@xxxxxxxx
- Simplify the auto mode state preservation logic by converting
`priv->kbd_bl.initialized' into a tristate integer
- Link to v5: https://patch.msgid.link/20260821-leds-trigger-hw-changed-v5-0-3e00d6c4a936@xxxxxxxx
Changes in v5:
- Address a concern from Sashiko:
- Non-atomic update of led_cdev->flags causes a data race that can
drop the LED_UNREGISTERING flag
- Fix it by synchronize the update with trigger_lock
- https://sashiko.dev/#/patchset/20260802-leds-trigger-hw-changed-v4-0-f97e2ca976fe@xxxxxxxx?part=8
- Address a concern from Sashiko:
- led_trigger_notify_hw_control_changed() might sleep, but without any
internal deferral mechanism or annotation
- Annotate the method with might_sleep(), since the very first users
of the interface, i.e., ideapad-laptop and (supposedly)
thinkpad_acpi, will call the interface from work contexts. It does
not deserve the overhead of internal deferral mechanism
- https://sashiko.dev/#/patchset/20260802-leds-trigger-hw-changed-v4-0-f97e2ca976fe@xxxxxxxx?part=9
- Update "Changes in v4" to include more details
- Link to v4: https://patch.msgid.link/20260802-leds-trigger-hw-changed-v4-0-f97e2ca976fe@xxxxxxxx
Changes in v4:
- Drop the RFC prefix
- Add a new patch in the series to address a concern from Sashiko
- [PATCH v4 08/12] leds: trigger: Do not attach trigger to a removing LED
- Without it, the following patch may expose a race condition if a
future LED driver synchronizes led_classdev_unregister() and
led_trigger_notify_hw_control_changed() poorly. The ideapad-laptop
patches in the series doesn't expose the race condition though
- In theory, the race condition can also be triggered by a userspace
program writing to the "trigger" attribute right before
device_unregister() is called
- https://sashiko.dev/#/patchset/20260719-leds-trigger-hw-changed-v3-0-5fb55722e36e@xxxxxxxx
- Address other concerns from Sashiko
- Reject insane hardware brightness
- Do not notify the LED trigger core when the registration of the
private trigger has failed
- Enable LEDS_TRIGGERS_HW_CHANGED by default when
LEDS_BRIGHTNESS_HW_CHANGED is enabled
- Add missing #include (Thanks Ilpo Järvinen)
- Remove needless #include (ditto)
- Remove needless code alignment (ditto)
- Link to v3: https://patch.msgid.link/20260719-leds-trigger-hw-changed-v3-0-5fb55722e36e@xxxxxxxx
Changes in v3:
- Integrate https://lore.kernel.org/all/20260712-leds-hw-control-brightness-set-v1-1-1de593b09d26@xxxxxxxx/
into the series
- Adopt __led_trigger_is_hw_controlled() in the rest of the series
- Rearrange the series so that the code using the offloaded() callback is
introduced before the driver implementation (thanks Thomas Weißschuh)
- Reword documentations and commit messages (ditto)
- Adopt guard() and lockdep (ditto)
- Address concerns from Sashiko
- Fix a race condition in ideapad_kbd_bl_led_cdev_brightness_set()
- Fix trigger re-registration of ideapad_kbd_bl_auto_trigger
- https://sashiko.dev/#/patchset/20260618-leds-trigger-hw-changed-v2-0-c28c44053cf3%40rong.moe
- Make registration failures of ideapad_kbd_bl_auto_trigger non-fatal
- Link to v2: https://patch.msgid.link/20260618-leds-trigger-hw-changed-v2-0-c28c44053cf3@xxxxxxxx
Changes in v2:
- Restrict the led_trigger_notify_hw_control_changed() interface to
private triggers only
- Drop PATCH v1 1/9 ("leds: Load trigger modules on-demand if used as
hw control trigger"), not relavant any more
- Gate the led_trigger_notify_hw_control_changed() interface behind
Kconfig LEDS_TRIGGERS_HW_CHANGED and LED device flag
LED_TRIG_HW_CHANGED
- Fix lock ordering inversion
- ideapad-laptop:
- Only call led_trigger_notify_hw_control_changed() when needed
- Serialize keyboard backlight notifications
- Reword commit messages and documentations
- Link to v1: https://patch.msgid.link/20260227190617.271388-1-i@xxxxxxxx
---
Rong Zhang (3):
platform/x86: ideapad-laptop: Serialize keyboard backlight tracking
platform/x86: ideapad-laptop: Decouple hardware & classdev brightness for keyboard backlight
platform/x86: ideapad-laptop: Fully support auto keyboard backlight
drivers/platform/x86/lenovo/Kconfig | 1 +
drivers/platform/x86/lenovo/ideapad-laptop.c | 279 +++++++++++++++++++++------
2 files changed, 225 insertions(+), 55 deletions(-)
---
base-commit: 7475ea8b58616b33c04afb976cf0fbaad9dd63fb
change-id: 20260506-leds-trigger-hw-changed-96a62188cbdf
Thanks,
Rong