leds: flash: LM3643 dual LED flash driver
Subsystems (2)
v2 cover leds: flash: LM3643 dual LED flash driver
This series adds a flash LED driver for the Texas Instruments LM3643. I wrote it to support the Windows Hello NIR illuminator on my ThinkPad X9-15 Gen 1, which has a single LED connected to both current sources. The driver has also been tested by Ruslan Koreev on a ThinkPad X1 Carbon Gen 14.
On both ThinkPad models the chip is described by ACPI but has no _DSD. The original RFC asked how to supply the missing child nodes. This series includes DMI-matched software nodes for both laptop models.
1/4 DT binding
2/4 driver
3/4 DMI match table and values for the X1 Carbon
4/4 DMI entry for the X9-15 Gen 1
Changes in v2:
- Rebased onto leds/for-leds-next
- dt-bindings: make flash-max-microamp, led-max-microamp and flash-max-timeout-us required
- driver: return device to standby state when the last output is switched off (squashed fix provided by Ruslan Koreev)
- New 3/4: DMI mechanism and entry for the X1 Carbon developed by Ruslan. Plus a minor update to provide a reg property for consistency with the DT bindings.
- New 4/4: DMI entry for the X9-15 Gen 1 and update struct names to be model-specific.
v1: https://lore.kernel.org/all/[email protected]/
Rillian Grant (3):
dt-bindings: leds: Document TI LM3643 dual LED flash driver
leds: flash: Add support for the TI LM3643 dual LED flash driver
leds: flash: lm3643: Describe the LED on the Lenovo ThinkPad X9-15 Gen
1
Ruslan Koreev (1):
leds: flash: lm3643: Describe the LED of ACPI boards without LED nodes
.../devicetree/bindings/leds/ti,lm3643.yaml | 129 +++ MAINTAINERS | 7 + drivers/leds/flash/Kconfig | 12 + drivers/leds/flash/Makefile | 1 + drivers/leds/flash/leds-lm3643.c | 919 ++++++++++++++++++ 5 files changed, 1068 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/ti,lm3643.yaml create mode 100644 drivers/leds/flash/leds-lm3643.c
base-commit: 05b4738b0078f7d6f154f68068a11c8a0635e9df
Signature · 1 line
2.55.0
PATCH v2 1/4 dt-bindings: leds: Document TI LM3643 dual LED flash driver
Document Texas Instruments LM3643 dual LED flash driver devicetree bindings.
--- .../devicetree/bindings/leds/ti,lm3643.yaml | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/ti,lm3643.yaml
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +129 -0
@@ -0,0 +1,129 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/ti,lm3643.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments LM3643 1500mA dual LED Flash Driver + +maintainers: + - Rillian Grant <[email protected]> + +description: | + The LM3643 is a dual LED flash driver utilizing a synchronous boost converter + to provide power to two current sources. + + The dual high-side current sources can be tied together to provide flash + currents up to 1.5A through a single LED. + + Datasheet: https://www.ti.com/lit/ds/symlink/lm3643.pdf + +properties: + compatible: + enum: + - ti,lm3643 + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^led@[0-1]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + description: Index of the LED. + minimum: 0 + maximum: 1 + + led-sources: + minItems: 1 + maxItems: 2 + items: + minimum: 0 + maximum: 1 + + flash-max-microamp: + description: | + Maximum flash current through this LED. Each high-side current source + can provide up to 1.5A. The maximum current the boost can deliver is + 1.5A across both sources. + + Valid values for an LED connected to one source: + 10900 - 1500000, step by 11725 (rounded down) + Valid values for an LED connected to both sources: + 21800 - 1500000, step by 23450 (rounded down) + + minimum: 10900 + maximum: 1500000 + + led-max-microamp: + description: | + Maximum torch current through this LED. In torch mode each high-side + current source can provide up to 179mA. + + Valid values for an LED connected to one source: + 977 - 179000, step by 1400 (rounded down) + Valid values for an LED connected to both sources: + 1954 - 358000, step by 2800 (rounded down) + + minimum: 977 + maximum: 358000 + + flash-max-timeout-us: + description: | + The chip supports timeouts from 10ms to 100ms in increments of 10ms + and from 100ms to 400ms in increments of 50ms. The provided value + will be rounded down to a supported value. + + minimum: 10000 + maximum: 400000 + + required: + - reg + - led-sources + - flash-max-microamp + - led-max-microamp + - flash-max-timeout-us + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + +additionalProperties: false + +examples: + - | + #include <dt-bindings/leds/common.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + flash-led-controller@63 { + compatible = "ti,lm3643"; + reg = <0x63>; + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + led-sources = <0>, <1>; + function = LED_FUNCTION_FLASH; + color = <LED_COLOR_ID_IR>; + flash-max-microamp = <750000>; + led-max-microamp = <180000>; + flash-max-timeout-us = <150000>; + }; + }; + };
Signature · 1 line
2.55.0
[email protected]
AI reviewRe: [PATCH v2 1/4] dt-bindings: leds: Document TI LM3643 dual LED flash driver
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
Document Texas Instruments LM3643 dual LED flash driver devicetree bindings.
Signed-off-by Rillian Grant <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCH v2 1/4] dt-bindings: leds: Document TI LM3643 dual LED flash driver
In reply to Rillian GrantDocumentation/devicetree/bindings/leds/ti,lm3643.yaml line 28
Quoted 8 lines · Rillian Grant
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +8
-0+properties: + compatible: + enum: + - ti,lm3643 + + reg: + maxItems: 1 +
Missing supply, enable-gpios.
Quoted 6 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +6
-0+ "#address-cells": + const: 1 + + "#size-cells": + const: 0 +
Documentation/devicetree/bindings/leds/ti,lm3643.yaml line 44
Quoted 10 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +10
-0+patternProperties: + "^led@[0-1]$": + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + description: Index of the LED. + minimum: 0
Drop, that's alerady minimum.
Documentation/devicetree/bindings/leds/ti,lm3643.yaml line 51
Quoted 7 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +7
-0+ maximum: 1 + + led-sources: + minItems: 1 + maxItems: 2 + items: + minimum: 0
As well
Quoted 21 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +21
-0+ maximum: 1 + + flash-max-microamp: + description: | + Maximum flash current through this LED. Each high-side current source + can provide up to 1.5A. The maximum current the boost can deliver is + 1.5A across both sources. + + Valid values for an LED connected to one source: + 10900 - 1500000, step by 11725 (rounded down) + Valid values for an LED connected to both sources: + 21800 - 1500000, step by 23450 (rounded down) + + minimum: 10900 + maximum: 1500000 + + led-max-microamp: + description: | + Maximum torch current through this LED. In torch mode each high-side + current source can provide up to 179mA. +
Documentation/devicetree/bindings/leds/ti,lm3643.yaml line 82
Quoted 10 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +10
-0+ Valid values for an LED connected to one source: + 977 - 179000, step by 1400 (rounded down) + Valid values for an LED connected to both sources: + 1954 - 358000, step by 2800 (rounded down) + + minimum: 977 + maximum: 358000 + + flash-max-timeout-us: + description: |
Drop |
Documentation/devicetree/bindings/leds/ti,lm3643.yaml line 86
Quoted 4 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +4
-0+ The chip supports timeouts from 10ms to 100ms in increments of 10ms + and from 100ms to 400ms in increments of 50ms. The provided value + will be rounded down to a supported value. +
Drop blank line
Quoted 17 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +17
-0+ minimum: 10000 + maximum: 400000 + + required: + - reg + - led-sources + - flash-max-microamp + - led-max-microamp + - flash-max-timeout-us + +required: + - compatible + - reg + - "#address-cells" + - "#size-cells" + +additionalProperties: false
Documentation/devicetree/bindings/leds/ti,lm3643.yaml line 113
Quoted 10 lines
Documentation/devicetree/bindings/leds/ti,lm3643.yaml new file +10
-0+ +examples: + - | + #include <dt-bindings/leds/common.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + flash-led-controller@63 {
led-controller@63
Best regards,
Krzysztof
PATCH v2 2/4 leds: flash: Add support for the TI LM3643 dual LED flash driver
In reply to Rillian GrantThe LM3643 is an I2C dual LED flash driver. Its two high-side current sources share a synchronous boost converter and each supports torch and flash modes with programmable current and flash timeout alongside fault reporting.
It also supports connecting both sources together to supply one LED with current up to the boost converter's 1.5A maximum. In that case the current will be split between each source symmetrically and the sources will be enabled and disabled at the same time.
As strobing is toggled chip-wide the driver returns -EBUSY when a sibling LED is active.
Flash timeouts do not have a constant step. The driver advertises the most granular step and rounds down to the nearest supported value.
Register behavior was taken from the datasheet (SNVS967A).
--- MAINTAINERS | 7 + drivers/leds/flash/Kconfig | 12 + drivers/leds/flash/Makefile | 1 + drivers/leds/flash/leds-lm3643.c | 786 +++++++++++++++++++++++++++++++ 4 files changed, 806 insertions(+) create mode 100644 drivers/leds/flash/leds-lm3643.c
MAINTAINERS +7 -0
@@ -27036,6 +27036,13 @@ F: include/linux/dma/k3-udma-glue.h F: include/linux/dma/ti-cppi5.h X: drivers/dma/ti/cppi41.c +TEXAS INSTRUMENTS LM3643 LED FLASH DRIVER +M: Rillian Grant <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/devicetree/bindings/leds/ti,lm3643.yaml +F: drivers/leds/flash/leds-lm3643.c + TEXAS INSTRUMENTS TPS25990 HARDWARE MONITOR DRIVER M: Jerome Brunet <[email protected]> L: [email protected]
drivers/leds/flash/Kconfig +12 -0
@@ -39,6 +39,18 @@ config LEDS_LM3601X This option enables support for the TI LM3601x family of flash, torch and indicator classes. +config LEDS_LM3643 + tristate "LED support for LM3643 dual LED flash driver" + depends on I2C + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS + select REGMAP_I2C + help + This option enables support for the Texas Instruments LM3643 dual + LED flash driver. + + This driver can also be built as a module. If so, the module + will be called "leds-lm3643". + config LEDS_MAX77693 tristate "LED support for MAX77693 Flash" depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
drivers/leds/flash/Makefile +1 -0
@@ -6,6 +6,7 @@ obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o +obj-$(CONFIG_LEDS_LM3643) += leds-lm3643.o obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_QCOM_FLASH) += leds-qcom-flash.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o
drivers/leds/flash/leds-lm3643.c new file +786 -0
786 lines not on this page · raw message
Signature · 1 line
2.55.0
[email protected]
AI reviewRe: [PATCH v2 2/4] leds: flash: Add support for the TI LM3643 dual LED flash driver
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] leds: TOCTOU race in max_brightness clamping after registration --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] leds: TOCTOU race in max_brightness clamping after registration --
commit 0af4a3a129a9adf0eccf2c17265d6d72e8d4acac
Author: Rillian Grant <[email protected]>
leds: flash: Add support for the TI LM3643 dual LED flash driver
This commit adds support for the TI LM3643 dual LED flash driver. The chip features two high-side current sources sharing a synchronous boost converter, supporting programmable torch and flash modes with fault reporting.
Quoted 5 lines
drivers/leds/flash/leds-lm3643.c new file +0
-0
[ ... ]
Quoted 3 lines
drivers/leds/flash/leds-lm3643.c new file +3
-0+static int lm3643_register_led (struct device *dev,struct lm3643 *chip, +struct fwnode_handle *fwnode) +{
[ ... ]
drivers/leds/flash/leds-lm3643.c line 688
Quoted 10 lines
drivers/leds/flash/leds-lm3643.c new file +10
-0+ ret =devm_led_classdev_flash_register_ext (dev, flash_cdev, &init_data); +if (ret) +return ret; + +if (led_cdev->max_brightness > torch_max_brightness) { +dev_warn (dev,"max-brightness %u not supported (using %u)\n" , + led_cdev->max_brightness, + torch_max_brightness); + led_cdev->max_brightness = torch_max_brightness; + }
[Severity: Medium]
Is there a TOCTOU race condition here? By clamping led_cdev->max_brightness after calling devm_led_classdev_flash_register_ext(), isn't there a window where the device is exposed to userspace with the unclamped value?
Once registered, sysfs attributes are active and a KOBJ_ADD uevent is sent. Could a fast userspace process read the unclamped max_brightness and write an over-limit brightness value before the driver clamps it, potentially driving the LED beyond its configured led-max-microamp thermal limit?
This could happen if a device tree provides a max-brightness property higher than the led-max-microamp limit. The LED core's led_classdev_register_ext() overwrites led_cdev->max_brightness with this value and creates the sysfs interfaces before this subsequent clamping step runs.
Quoted 3 lines
drivers/leds/flash/leds-lm3643.c new file +3
-0+ +return lm3643_register_v4l2 (dev, led, fwnode); +}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
PATCH v2 3/4 leds: flash: lm3643: Describe the LED of ACPI boards without LED nodes
In reply to Rillian GrantFrom: Ruslan Koreev <[email protected]>
Lenovo ThinkPads enumerate the LM3643 through ACPI (HID TXNW3643) without a _DSD, so the device has no LED child nodes and the driver refuses to probe. On these laptops the chip drives the Windows Hello IR flood illuminator, with both current sources feeding a single LED, and Lenovo's Windows driver applies a fixed configuration to any LM3643 it finds.
Add a DMI table that provides that description as a software node when the firmware offers none: one IR flash LED on both outputs, with torch and flash limits well below the chip's maximums. Start with the ThinkPad X1 Carbon Gen 14.
The description is keyed by DMI instead of being applied to every TXNW3643 because the wiring is a board property: which output feeds which LED and how much current the LED tolerates cannot be read from the chip, and a wrong guess overdrives an LED. The firmware cannot be fixed from the driver side, and a per-board table is what x86-android-tablets does for devices whose ACPI tables describe nothing either. Boards with a _DSD are not affected, the fallback only runs when the device has no child nodes. The limits are conservative because the LED part is not documented; the illuminator is bright enough for face authentication at a fraction of them.
Tested on that laptop: torch through /sys/class/leds/ir:flash lights the ST VD55G1 IR camera's field of view, and the resulting frames are good enough for face authentication.
--- drivers/leds/flash/leds-lm3643.c | 93 ++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+)
drivers/leds/flash/leds-lm3643.c +93 -0
@@ -9,6 +9,7 @@#include <linux/bitfield.h> #include <linux/bits.h> #include <linux/cleanup.h> +#include <linux/dmi.h> #include <linux/i2c.h> #include <linux/led-class-flash.h> #include <linux/leds.h>
@@ -690,6 +691,92 @@ static int lm3643_register_led(struct device *dev, struct lm3643 *chip,return lm3643_register_v4l2 (dev, led, fwnode); } +/* +* Lenovo ThinkPads enumerate the chip through ACPI (HID TXNW3643) without a +* _DSD, so the LED is not described by firmware. On the boards below it drives +* the Windows Hello IR flood illuminator, with both current sources feeding a +* single LED. Describe that with a software node, with torch and flash limits +* (100 mA and 300 mA per output) well below the chip's maximums. +*/ +static const u32 lm3643_ir_flood_sources[] = {0 ,1 }; + +static const struct property_entry lm3643_ir_flood_props[] = { +PROPERTY_ENTRY_U32 ("reg" ,0 ), +PROPERTY_ENTRY_U32_ARRAY ("led-sources" , lm3643_ir_flood_sources), +PROPERTY_ENTRY_STRING ("function" ,LED_FUNCTION_FLASH ), +PROPERTY_ENTRY_U32 ("color" ,LED_COLOR_ID_IR ), +PROPERTY_ENTRY_U32 ("led-max-microamp" ,200000 ), +PROPERTY_ENTRY_U32 ("flash-max-microamp" ,600000 ), +PROPERTY_ENTRY_U32 ("flash-max-timeout-us" ,100000 ), + { } +}; + +static const struct software_node lm3643_ir_flood_root = { + .name ="lm3643" , +}; + +static const struct software_node lm3643_ir_flood_led = { + .name ="led-0" , + .parent = &lm3643_ir_flood_root, + .properties = lm3643_ir_flood_props, +}; + +static const struct software_node *lm3643_ir_flood_nodes[] = { + &lm3643_ir_flood_root, + &lm3643_ir_flood_led, +NULL +}; + +static const struct dmi_system_id lm3643_dmi_leds[] = { + { +/* Lenovo ThinkPad X1 Carbon Gen 14 */ + .matches = { +DMI_MATCH (DMI_SYS_VENDOR ,"LENOVO" ), +DMI_MATCH (DMI_PRODUCT_VERSION ,"ThinkPad X1 Carbon Gen 14" ), + }, + .driver_data = (void *)lm3643_ir_flood_nodes, + }, + { } +}; + +static void lm3643_remove_dmi_leds (void *data) +{ +struct device *dev = data; +const struct dmi_system_id *id =dmi_first_match (lm3643_dmi_leds); + +set_secondary_fwnode (dev,NULL ); +if (id) +software_node_unregister_node_group (id->driver_data); +} + +static int lm3643_add_dmi_leds (struct device *dev) +{ +const struct dmi_system_id *id; +const struct software_node **nodes; +int ret; + +if (!has_acpi_companion (dev)) +return 0 ; + + id =dmi_first_match (lm3643_dmi_leds); +if (!id) +return 0 ; + + nodes = id->driver_data; +/* The nodes are static: a second chip on the same board cannot reuse them */ +if (software_node_fwnode (nodes[0 ])) +return dev_err_probe (dev, -EBUSY ,"LED description already in use\n" ); + + ret =software_node_register_node_group (nodes); +if (ret) +return dev_err_probe (dev, ret,"failed to register the LED description\n" ); + +set_secondary_fwnode (dev,software_node_fwnode (nodes[0 ])); +dev_info (dev,"no LED nodes in firmware, using the DMI description\n" ); + +return devm_add_action_or_reset (dev, lm3643_remove_dmi_leds, dev); +} +static int lm3643_probe (struct i2c_client *client) {struct device *dev = &client->dev;
@@ -699,6 +786,12 @@ static int lm3643_probe(struct i2c_client *client)int ret; count =device_get_child_node_count (dev); +if (!count) { + ret =lm3643_add_dmi_leds (dev); +if (ret) +return ret; + count =device_get_child_node_count (dev); + }if (!count || count >LM3643_NUM_CHANNELS )return dev_err_probe (dev, -EINVAL ,"%u LED nodes found, expected 1 to %d\n" , count,LM3643_NUM_CHANNELS );
Signature · 1 line
2.55.0
[email protected]
AI reviewRe: [PATCH v2 3/4] leds: flash: lm3643: Describe the LED of ACPI boards without LED nodes
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] leds: lm3643: informational logging during probe violates subsystem guidelines --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] leds: lm3643: informational logging during probe violates subsystem guidelines --
commit 526bd68dbe5899ef1f96b678f6b5d764ba338f79
Author: Ruslan Koreev <[email protected]>
leds: flash: lm3643: Describe the LED of ACPI boards without LED nodes
This commit adds a DMI table to describe the LM3643 LED setup on Lenovo ThinkPads that lack proper firmware descriptions (no _DSD). It provides a software node configuration to drive the Windows Hello IR flood illuminator.
Quoted 4 lines
drivers/leds/flash/leds-lm3643.c +0
-0
[ ... ]
Quoted 1 line
drivers/leds/flash/leds-lm3643.c +0
-0@@ -690,6 +691,92 @@ static int lm3643_register_led(struct device *dev, struct lm3643 *chip,
[ ... ]
Quoted 2 lines
drivers/leds/flash/leds-lm3643.c +2
-0+static int lm3643_add_dmi_leds (struct device *dev) +{
[ ... ]
drivers/leds/flash/leds-lm3643.c static int lm3643_register_led(struct device *dev, struct lm3643 *chip, · line 775
Quoted 6 lines
drivers/leds/flash/leds-lm3643.c +6
-0+ ret =software_node_register_node_group (nodes); +if (ret) +return dev_err_probe (dev, ret,"failed to register the LED description\n" ); + +set_secondary_fwnode (dev,software_node_fwnode (nodes[0 ])); +dev_info (dev,"no LED nodes in firmware, using the DMI description\n" );
[Severity: Low]
Does this informational log message violate the LED subsystem guidelines?
The subsystem rules strictly mandate: "Only log errors or warnings." Since this call to dev_info() executes automatically in lm3643_add_dmi_leds() during hardware enumeration on matching laptops, it will add unnecessary minor log noise during boot.
Quoted 3 lines
drivers/leds/flash/leds-lm3643.c +3
-0+ +return devm_add_action_or_reset (dev, lm3643_remove_dmi_leds, dev); +}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Re: [PATCH v2 3/4] leds: flash: lm3643: Describe the LED of ACPI boards without LED nodes
Quoted 8 lines · On Monday, 28 September 2026 10:50:14 BST [email protected] wrote:
The subsystem rules strictly mandate: "Only log errors or warnings." Since this call to
dev_info()executes automatically inlm3643_add_dmi_leds()during hardware enumeration on matching laptops, it will add unnecessary minor log noise during boot.drivers/leds/flash/leds-lm3643.c static int lm3643_register_led(struct device *dev, struct lm3643 *chip, · line 778
Quoted 3 lines
drivers/leds/flash/leds-lm3643.c +3
-0+ +return devm_add_action_or_reset (dev, lm3643_remove_dmi_leds, dev); +}
Agreed. I will replace with a dev_dbg() call in the next revision.
PATCH v2 4/4 leds: flash: lm3643: Describe the LED on the Lenovo ThinkPad X9-15 Gen 1
In reply to Rillian GrantThe ThinkPad X9-15 Gen 1 enumerates the LM3643 through ACPI (HID TXNW3643) without a _DSD, like the X1 Carbon Gen 14. It drives the Windows Hello IR flood illuminator with both current sources feeding a single LED.
The flash limits were obtained from an ETW trace of the SPB class extension during a Windows Hello unlock. The Windows driver programs 304 mA per current source (code 0x19 with the LED2 override set) and a 400 ms flash timeout.
There is no vendor value for the torch limit, so use the same conservative limit as the X1 Carbon Gen 14.
Rename the X1 Carbon Gen 14 nodes after the machine now that the table has a second entry. Sources and root node remain shared.
--- drivers/leds/flash/leds-lm3643.c | 70 +++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 15 deletions(-)
drivers/leds/flash/leds-lm3643.c +55 -15
@@ -691,16 +691,21 @@ static int lm3643_register_led(struct device *dev, struct lm3643 *chip,return lm3643_register_v4l2 (dev, led, fwnode); } -/* -* Lenovo ThinkPads enumerate the chip through ACPI (HID TXNW3643) without a -* _DSD, so the LED is not described by firmware. On the boards below it drives -* the Windows Hello IR flood illuminator, with both current sources feeding a -* single LED. Describe that with a software node, with torch and flash limits -* (100 mA and 300 mA per output) well below the chip's maximums. -*/ static const u32 lm3643_ir_flood_sources[] = {0 ,1 }; -static const struct property_entry lm3643_ir_flood_props[] = { +static const struct software_node lm3643_ir_flood_root = { + .name ="lm3643" , +}; + +/* +* The Lenovo ThinkPad X1 Carbon Gen 14 enumerates the chip through ACPI +* (HID TXNW3643) without a _DSD, so the LED is not described by firmware. +* On the X1 Gen 14 it drives the Windows Hello IR flood illuminator, with +* both current sources feeding a single LED. Describe that with a software +* node, with torch and flash limits (100 mA and 300 mA per output) well below +* the chip's maximums. +*/ +static const struct property_entry lm3643_x1c14_props[] = {PROPERTY_ENTRY_U32 ("reg" ,0 ),PROPERTY_ENTRY_U32_ARRAY ("led-sources" , lm3643_ir_flood_sources),PROPERTY_ENTRY_STRING ("function" ,LED_FUNCTION_FLASH ),
@@ -711,19 +716,46 @@ static const struct property_entry lm3643_ir_flood_props[] = { { } }; -static const struct software_node lm3643_ir_flood_root = { - .name ="lm3643" , +static const struct software_node lm3643_x1c14_led = { + .name ="led-0" , + .parent = &lm3643_ir_flood_root, + .properties = lm3643_x1c14_props, +}; + +static const struct software_node *lm3643_x1c14_nodes[] = { + &lm3643_ir_flood_root, + &lm3643_x1c14_led, +NULL }; -static const struct software_node lm3643_ir_flood_led = { +/* +* The Lenovo ThinkPad X9-15 Gen 1 enumerates the chip through ACPI +* (HID TXNW3643) without a _DSD. On the X9-15 it drives the Windows Hello IR +* flood illuminator, with both current sources feeding a single LED. Flash +* maximums were obtained from an SPB class extension ETW trace of the +* vendor-supplied Windows driver. The torch limit is a conservative value well +* below the chip's maximum. +*/ +static const struct property_entry lm3643_x9_15_props[] = { +PROPERTY_ENTRY_U32 ("reg" ,0 ), +PROPERTY_ENTRY_U32_ARRAY ("led-sources" , lm3643_ir_flood_sources), +PROPERTY_ENTRY_STRING ("function" ,LED_FUNCTION_FLASH ), +PROPERTY_ENTRY_U32 ("color" ,LED_COLOR_ID_IR ), +PROPERTY_ENTRY_U32 ("led-max-microamp" ,200000 ), +PROPERTY_ENTRY_U32 ("flash-max-microamp" ,608050 ), +PROPERTY_ENTRY_U32 ("flash-max-timeout-us" ,400000 ), + { } +}; + +static const struct software_node lm3643_x9_15_led = { .name ="led-0" , .parent = &lm3643_ir_flood_root, - .properties = lm3643_ir_flood_props, + .properties = lm3643_x9_15_props, }; -static const struct software_node *lm3643_ir_flood_nodes[] = { +static const struct software_node *lm3643_x9_15_nodes[] = { &lm3643_ir_flood_root, - &lm3643_ir_flood_led, + &lm3643_x9_15_led,NULL };
@@ -734,7 +766,15 @@ static const struct dmi_system_id lm3643_dmi_leds[] = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon Gen 14"), }, - .driver_data = (void *)lm3643_ir_flood_nodes, + .driver_data = (void *)lm3643_x1c14_nodes, + }, + { + /* Lenovo ThinkPad X9-15 Gen 1 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X9-15 Gen 1"), + }, + .driver_data = (void *)lm3643_x9_15_nodes, }, { } };
Signature · 1 line
2.55.0
[email protected]
AI reviewRe: [PATCH v2 4/4] leds: flash: lm3643: Describe the LED on the Lenovo ThinkPad X9-15 Gen 1
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 10 lines
The ThinkPad X9-15 Gen 1 enumerates the LM3643 through ACPI (HID TXNW3643) without a
_DSD, like the X1 Carbon Gen 14. It drives the Windows Hello IR flood illuminator with both current sources feeding a single LED.The flash limits were obtained from an ETW trace of the SPB class extension during a Windows Hello unlock. The Windows driver programs 304 mA per current source (code
0x19with the LED2 override set) and a 400 ms flash timeout.
Quoted 7 lines
There is no vendor value for the torch limit, so use the same conservative limit as the X1 Carbon Gen 14.
Rename the X1 Carbon Gen 14 nodes after the machine now that the table has a second entry. Sources and root node remain shared.
Signed-off-by Rillian Grant <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Hi Rillian,
Quoted 5 lines · Rillian Grant
This series adds a flash LED driver for the Texas Instruments LM3643. I wrote it to support the Windows Hello NIR illuminator on my ThinkPad X9-15 Gen 1, which has a single LED connected to both current sources. The driver has also been tested by Ruslan Koreev on a ThinkPad X1 Carbon Gen 14.
Thanks for folding my patches in. I retested v2 on the X1 Carbon Gen 14 (7.2.5): the DMI description is picked up, max_brightness is 71 and writes above it are clamped, max_flash_brightness is 600000, torch off puts the chip back in standby (ENABLE reads 0x00), and a flash strobe times out and reports flash-timeout-exceeded as expected.
About the Sashiko comment on 2/4: led_classdev_register_ext() reads max-brightness from the fwnode before it creates the class device, so the window only exists when the firmware node has a max-brightness larger than what led-max-microamp allows. The DMI nodes don't set it. If you want to close it anyway, clamping the code in lm3643_torch_set_brightness() against the limit derived from led-max-microamp would make it independent of max_brightness.
For 3/4, dev_dbg() is fine with me.
Ruslan