From 758e743362cdc0cc45d8717431b2eabf29084ef1 Mon Sep 17 00:00:00 2001 From: Pawel Zalewski Date: Wed, 23 Jul 2025 11:02:08 +0100 Subject: [PATCH 01/14] leds: leds-is31fl32xx: Add support for is31fl3236a Also add an additional and optional control register for setting the output PWM frequency to 22kHz. The default is 3kHz and this option puts the operational frequency outside of the audible range. Signed-off-by: Pawel Zalewski Link: https://lore.kernel.org/r/20250723-leds-is31fl3236a-v6-3-210328058625@thegoodpenguin.co.uk Signed-off-by: Lee Jones --- drivers/leds/leds-is31fl32xx.c | 47 +++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index 8793330dd414..dc9349f9d350 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -32,6 +32,8 @@ #define IS31FL3216_CONFIG_SSD_ENABLE BIT(7) #define IS31FL3216_CONFIG_SSD_DISABLE 0 +#define IS31FL32XX_PWM_FREQUENCY_22KHZ 0x01 + struct is31fl32xx_priv; struct is31fl32xx_led_data { struct led_classdev cdev; @@ -53,6 +55,7 @@ struct is31fl32xx_priv { * @pwm_update_reg : address of PWM Update register * @global_control_reg : address of Global Control register (optional) * @reset_reg : address of Reset register (optional) + * @output_frequency_setting_reg: address of output frequency register (optional) * @pwm_register_base : address of first PWM register * @pwm_registers_reversed: : true if PWM registers count down instead of up * @led_control_register_base : address of first LED control register (optional) @@ -76,6 +79,7 @@ struct is31fl32xx_chipdef { u8 pwm_update_reg; u8 global_control_reg; u8 reset_reg; + u8 output_frequency_setting_reg; u8 pwm_register_base; bool pwm_registers_reversed; u8 led_control_register_base; @@ -90,6 +94,19 @@ static const struct is31fl32xx_chipdef is31fl3236_cdef = { .pwm_update_reg = 0x25, .global_control_reg = 0x4a, .reset_reg = 0x4f, + .output_frequency_setting_reg = IS31FL32XX_REG_NONE, + .pwm_register_base = 0x01, + .led_control_register_base = 0x26, + .enable_bits_per_led_control_register = 1, +}; + +static const struct is31fl32xx_chipdef is31fl3236a_cdef = { + .channels = 36, + .shutdown_reg = 0x00, + .pwm_update_reg = 0x25, + .global_control_reg = 0x4a, + .reset_reg = 0x4f, + .output_frequency_setting_reg = 0x4b, .pwm_register_base = 0x01, .led_control_register_base = 0x26, .enable_bits_per_led_control_register = 1, @@ -101,6 +118,7 @@ static const struct is31fl32xx_chipdef is31fl3235_cdef = { .pwm_update_reg = 0x25, .global_control_reg = 0x4a, .reset_reg = 0x4f, + .output_frequency_setting_reg = IS31FL32XX_REG_NONE, .pwm_register_base = 0x05, .led_control_register_base = 0x2a, .enable_bits_per_led_control_register = 1, @@ -112,6 +130,7 @@ static const struct is31fl32xx_chipdef is31fl3218_cdef = { .pwm_update_reg = 0x16, .global_control_reg = IS31FL32XX_REG_NONE, .reset_reg = 0x17, + .output_frequency_setting_reg = IS31FL32XX_REG_NONE, .pwm_register_base = 0x01, .led_control_register_base = 0x13, .enable_bits_per_led_control_register = 6, @@ -126,6 +145,7 @@ static const struct is31fl32xx_chipdef is31fl3216_cdef = { .pwm_update_reg = 0xB0, .global_control_reg = IS31FL32XX_REG_NONE, .reset_reg = IS31FL32XX_REG_NONE, + .output_frequency_setting_reg = IS31FL32XX_REG_NONE, .pwm_register_base = 0x10, .pwm_registers_reversed = true, .led_control_register_base = 0x01, @@ -363,8 +383,21 @@ static struct is31fl32xx_led_data *is31fl32xx_find_led_data( static int is31fl32xx_parse_dt(struct device *dev, struct is31fl32xx_priv *priv) { + const struct is31fl32xx_chipdef *cdef = priv->cdef; int ret = 0; + if ((cdef->output_frequency_setting_reg != IS31FL32XX_REG_NONE) && + of_property_read_bool(dev_of_node(dev), "issi,22khz-pwm")) { + + ret = is31fl32xx_write(priv, cdef->output_frequency_setting_reg, + IS31FL32XX_PWM_FREQUENCY_22KHZ); + + if (ret) { + dev_err(dev, "Failed to write output PWM frequency register\n"); + return ret; + } + } + for_each_available_child_of_node_scoped(dev_of_node(dev), child) { struct led_init_data init_data = {}; struct is31fl32xx_led_data *led_data = @@ -404,12 +437,13 @@ static int is31fl32xx_parse_dt(struct device *dev, } static const struct of_device_id of_is31fl32xx_match[] = { - { .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, }, - { .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, }, - { .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, }, - { .compatible = "si-en,sn3218", .data = &is31fl3218_cdef, }, - { .compatible = "issi,is31fl3216", .data = &is31fl3216_cdef, }, - { .compatible = "si-en,sn3216", .data = &is31fl3216_cdef, }, + { .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, }, + { .compatible = "issi,is31fl3236a", .data = &is31fl3236a_cdef, }, + { .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, }, + { .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, }, + { .compatible = "si-en,sn3218", .data = &is31fl3218_cdef, }, + { .compatible = "issi,is31fl3216", .data = &is31fl3216_cdef, }, + { .compatible = "si-en,sn3216", .data = &is31fl3216_cdef, }, {}, }; @@ -466,6 +500,7 @@ static void is31fl32xx_remove(struct i2c_client *client) */ static const struct i2c_device_id is31fl32xx_id[] = { { "is31fl3236" }, + { "is31fl3236a" }, { "is31fl3235" }, { "is31fl3218" }, { "sn3218" }, From f4fc2d87aa167e3da5333c3db6cf702db1f98c05 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 24 Jul 2025 12:20:30 +0100 Subject: [PATCH 02/14] leds: Kconfig: Fix spelling mistake "limitiation" -> "limitation" There is a spelling mistake in the LEDS_BD2606MVV config. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20250724112030.142121-1-colin.i.king@gmail.com Signed-off-by: Lee Jones --- drivers/leds/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6e3dce7e35a4..06e6291be11b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -674,7 +674,7 @@ config LEDS_BD2606MVV help This option enables support for BD2606MVV LED driver chips accessed via the I2C bus. It supports setting brightness, with - the limitiation that there are groups of two channels sharing + the limitation that there are groups of two channels sharing a brightness setting, but not the on/off setting. To compile this driver as a module, choose M here: the module will From 6e3779e3c6f9dcc9267bf98bef70773a0b13dcbb Mon Sep 17 00:00:00 2001 From: Len Bao Date: Sun, 27 Jul 2025 07:56:45 +0000 Subject: [PATCH 03/14] leds: max77705: Function return instead of variable assignment Coverity noticed that assigning value -EINVAL to 'ret' in the if statement is useless because 'ret' is overwritten a few lines later. However, after inspect the code, this warning reveals that we need to return -EINVAL instead of the variable assignment. So, fix it. Coverity-id: 1646104 Fixes: aebb5fc9a0d8 ("leds: max77705: Add LEDs support") Signed-off-by: Len Bao Link: https://lore.kernel.org/r/20250727075649.34496-1-len.bao@gmx.us Signed-off-by: Lee Jones --- drivers/leds/leds-max77705.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-max77705.c b/drivers/leds/leds-max77705.c index 933cb4f19be9..b7403b3fcf5e 100644 --- a/drivers/leds/leds-max77705.c +++ b/drivers/leds/leds-max77705.c @@ -180,7 +180,7 @@ static int max77705_add_led(struct device *dev, struct regmap *regmap, struct fw ret = fwnode_property_read_u32(np, "reg", ®); if (ret || reg >= MAX77705_LED_NUM_LEDS) - ret = -EINVAL; + return -EINVAL; info = devm_kcalloc(dev, num_channels, sizeof(*info), GFP_KERNEL); if (!info) From 5974e8f6c3e47ab097c3dd8ece7324d1f88fe739 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 29 Jul 2025 12:51:22 +0800 Subject: [PATCH 04/14] leds: flash: leds-qcom-flash: Update torch current clamp setting There is a register to clamp the flash current per LED channel when safety timer is disabled. It needs to be updated according to the maximum torch LED current setting to ensure the torch current won't be clamped unexpectedly. Fixes: 96a2e242a5dc ("leds: flash: Add driver to support flash LED module in QCOM PMICs") Signed-off-by: Fenglin Wu Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20250729-fix-torch-clamp-issue-v2-1-9b83816437a3@oss.qualcomm.com Signed-off-by: Lee Jones --- drivers/leds/flash/leds-qcom-flash.c | 62 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c index 89cf5120f5d5..db7c2c743adc 100644 --- a/drivers/leds/flash/leds-qcom-flash.c +++ b/drivers/leds/flash/leds-qcom-flash.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -114,36 +114,39 @@ enum { REG_THERM_THRSH1, REG_THERM_THRSH2, REG_THERM_THRSH3, + REG_TORCH_CLAMP, REG_MAX_COUNT, }; static const struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = { - REG_FIELD(0x08, 0, 7), /* status1 */ - REG_FIELD(0x09, 0, 7), /* status2 */ - REG_FIELD(0x0a, 0, 7), /* status3 */ - REG_FIELD_ID(0x40, 0, 7, 3, 1), /* chan_timer */ - REG_FIELD_ID(0x43, 0, 6, 3, 1), /* itarget */ - REG_FIELD(0x46, 7, 7), /* module_en */ - REG_FIELD(0x47, 0, 5), /* iresolution */ - REG_FIELD_ID(0x49, 0, 2, 3, 1), /* chan_strobe */ - REG_FIELD(0x4c, 0, 2), /* chan_en */ - REG_FIELD(0x56, 0, 2), /* therm_thrsh1 */ - REG_FIELD(0x57, 0, 2), /* therm_thrsh2 */ - REG_FIELD(0x58, 0, 2), /* therm_thrsh3 */ + [REG_STATUS1] = REG_FIELD(0x08, 0, 7), + [REG_STATUS2] = REG_FIELD(0x09, 0, 7), + [REG_STATUS3] = REG_FIELD(0x0a, 0, 7), + [REG_CHAN_TIMER] = REG_FIELD_ID(0x40, 0, 7, 3, 1), + [REG_ITARGET] = REG_FIELD_ID(0x43, 0, 6, 3, 1), + [REG_MODULE_EN] = REG_FIELD(0x46, 7, 7), + [REG_IRESOLUTION] = REG_FIELD(0x47, 0, 5), + [REG_CHAN_STROBE] = REG_FIELD_ID(0x49, 0, 2, 3, 1), + [REG_CHAN_EN] = REG_FIELD(0x4c, 0, 2), + [REG_THERM_THRSH1] = REG_FIELD(0x56, 0, 2), + [REG_THERM_THRSH2] = REG_FIELD(0x57, 0, 2), + [REG_THERM_THRSH3] = REG_FIELD(0x58, 0, 2), + [REG_TORCH_CLAMP] = REG_FIELD(0xec, 0, 6), }; static const struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = { - REG_FIELD(0x06, 0, 7), /* status1 */ - REG_FIELD(0x07, 0, 6), /* status2 */ - REG_FIELD(0x09, 0, 7), /* status3 */ - REG_FIELD_ID(0x3e, 0, 7, 4, 1), /* chan_timer */ - REG_FIELD_ID(0x42, 0, 6, 4, 1), /* itarget */ - REG_FIELD(0x46, 7, 7), /* module_en */ - REG_FIELD(0x49, 0, 3), /* iresolution */ - REG_FIELD_ID(0x4a, 0, 6, 4, 1), /* chan_strobe */ - REG_FIELD(0x4e, 0, 3), /* chan_en */ - REG_FIELD(0x7a, 0, 2), /* therm_thrsh1 */ - REG_FIELD(0x78, 0, 2), /* therm_thrsh2 */ + [REG_STATUS1] = REG_FIELD(0x06, 0, 7), + [REG_STATUS2] = REG_FIELD(0x07, 0, 6), + [REG_STATUS3] = REG_FIELD(0x09, 0, 7), + [REG_CHAN_TIMER] = REG_FIELD_ID(0x3e, 0, 7, 4, 1), + [REG_ITARGET] = REG_FIELD_ID(0x42, 0, 6, 4, 1), + [REG_MODULE_EN] = REG_FIELD(0x46, 7, 7), + [REG_IRESOLUTION] = REG_FIELD(0x49, 0, 3), + [REG_CHAN_STROBE] = REG_FIELD_ID(0x4a, 0, 6, 4, 1), + [REG_CHAN_EN] = REG_FIELD(0x4e, 0, 3), + [REG_THERM_THRSH1] = REG_FIELD(0x7a, 0, 2), + [REG_THERM_THRSH2] = REG_FIELD(0x78, 0, 2), + [REG_TORCH_CLAMP] = REG_FIELD(0xed, 0, 6), }; struct qcom_flash_data { @@ -156,6 +159,7 @@ struct qcom_flash_data { u8 max_channels; u8 chan_en_bits; u8 revision; + u8 torch_clamp; }; struct qcom_flash_led { @@ -702,6 +706,7 @@ static int qcom_flash_register_led_device(struct device *dev, u32 current_ua, timeout_us; u32 channels[4]; int i, rc, count; + u8 torch_clamp; count = fwnode_property_count_u32(node, "led-sources"); if (count <= 0) { @@ -751,6 +756,12 @@ static int qcom_flash_register_led_device(struct device *dev, current_ua = min_t(u32, current_ua, TORCH_CURRENT_MAX_UA * led->chan_count); led->max_torch_current_ma = current_ua / UA_PER_MA; + torch_clamp = (current_ua / led->chan_count) / TORCH_IRES_UA; + if (torch_clamp != 0) + torch_clamp--; + + flash_data->torch_clamp = max_t(u8, flash_data->torch_clamp, torch_clamp); + if (fwnode_property_present(node, "flash-max-microamp")) { flash->led_cdev.flags |= LED_DEV_CAP_FLASH; @@ -917,8 +928,7 @@ static int qcom_flash_led_probe(struct platform_device *pdev) flash_data->leds_count++; } - return 0; - + return regmap_field_write(flash_data->r_fields[REG_TORCH_CLAMP], flash_data->torch_clamp); release: while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count) v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]); From 7d5c3cac1f395324673e9ec32b65e4f6ff23fcb9 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Tue, 29 Jul 2025 12:51:23 +0800 Subject: [PATCH 05/14] leds: flash: leds-qcom-flash: Add a separate register map for PMI8998 The 3-channel flash module in PMI8998 has several registers different than the others, such as: torch_clamp. Add different register fields for it. Signed-off-by: Fenglin Wu Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20250729-fix-torch-clamp-issue-v2-2-9b83816437a3@oss.qualcomm.com Signed-off-by: Lee Jones --- drivers/leds/flash/leds-qcom-flash.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/leds/flash/leds-qcom-flash.c b/drivers/leds/flash/leds-qcom-flash.c index db7c2c743adc..b03a6833e3e3 100644 --- a/drivers/leds/flash/leds-qcom-flash.c +++ b/drivers/leds/flash/leds-qcom-flash.c @@ -118,6 +118,22 @@ enum { REG_MAX_COUNT, }; +static const struct reg_field mvflash_3ch_pmi8998_regs[REG_MAX_COUNT] = { + [REG_STATUS1] = REG_FIELD(0x08, 0, 5), + [REG_STATUS2] = REG_FIELD(0x09, 0, 7), + [REG_STATUS3] = REG_FIELD(0x0a, 0, 7), + [REG_CHAN_TIMER] = REG_FIELD_ID(0x40, 0, 7, 3, 1), + [REG_ITARGET] = REG_FIELD_ID(0x43, 0, 6, 3, 1), + [REG_MODULE_EN] = REG_FIELD(0x46, 7, 7), + [REG_IRESOLUTION] = REG_FIELD(0x47, 0, 5), + [REG_CHAN_STROBE] = REG_FIELD_ID(0x49, 0, 2, 3, 1), + [REG_CHAN_EN] = REG_FIELD(0x4c, 0, 2), + [REG_THERM_THRSH1] = REG_FIELD(0x56, 0, 2), + [REG_THERM_THRSH2] = REG_FIELD(0x57, 0, 2), + [REG_THERM_THRSH3] = REG_FIELD(0x58, 0, 2), + [REG_TORCH_CLAMP] = REG_FIELD(0xea, 0, 6), +}; + static const struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = { [REG_STATUS1] = REG_FIELD(0x08, 0, 7), [REG_STATUS2] = REG_FIELD(0x09, 0, 7), @@ -862,13 +878,20 @@ static int qcom_flash_led_probe(struct platform_device *pdev) return rc; } - if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) { + if (val == FLASH_SUBTYPE_3CH_PM8150_VAL) { flash_data->hw_type = QCOM_MVFLASH_3CH; flash_data->max_channels = 3; regs = devm_kmemdup(dev, mvflash_3ch_regs, sizeof(mvflash_3ch_regs), GFP_KERNEL); if (!regs) return -ENOMEM; + } else if (val == FLASH_SUBTYPE_3CH_PMI8998_VAL) { + flash_data->hw_type = QCOM_MVFLASH_3CH; + flash_data->max_channels = 3; + regs = devm_kmemdup(dev, mvflash_3ch_pmi8998_regs, + sizeof(mvflash_3ch_pmi8998_regs), GFP_KERNEL); + if (!regs) + return -ENOMEM; } else if (val == FLASH_SUBTYPE_4CH_VAL) { flash_data->hw_type = QCOM_MVFLASH_4CH; flash_data->max_channels = 4; From fe4ffdbab4bb3cda1d72b93f7d2c3f7ea3df415d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 4 Aug 2025 13:49:48 +0200 Subject: [PATCH 06/14] leds: qnap-mcu: Fix state numbering for USB LED The "@Cx" commands span a number of different functions, from the status and USB LEDs to the buzzer and power button. So change the USB-LED enum to start at 0 and adapt the offset accordingly to not suggest @CD would relate to the USB-LED - while in fact "@CD" is a state of the status LED. Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20250804114949.3127417-2-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/leds/leds-qnap-mcu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/leds/leds-qnap-mcu.c b/drivers/leds/leds-qnap-mcu.c index 4e4709456261..fe055c5511b8 100644 --- a/drivers/leds/leds-qnap-mcu.c +++ b/drivers/leds/leds-qnap-mcu.c @@ -104,9 +104,9 @@ static int qnap_mcu_register_err_led(struct device *dev, struct qnap_mcu *mcu, i } enum qnap_mcu_usb_led_mode { - QNAP_MCU_USB_LED_ON = 1, - QNAP_MCU_USB_LED_OFF = 3, - QNAP_MCU_USB_LED_BLINK = 2, + QNAP_MCU_USB_LED_ON = 0, + QNAP_MCU_USB_LED_OFF = 2, + QNAP_MCU_USB_LED_BLINK = 1, }; struct qnap_mcu_usb_led { @@ -137,7 +137,7 @@ static int qnap_mcu_usb_led_set(struct led_classdev *led_cdev, * Byte 3 is shared between the usb led target on/off/blink * and also the buzzer control (in the input driver) */ - cmd[2] = 'D' + usb_led->mode; + cmd[2] = 'E' + usb_led->mode; return qnap_mcu_exec_with_ack(usb_led->mcu, cmd, sizeof(cmd)); } @@ -161,7 +161,7 @@ static int qnap_mcu_usb_led_blink_set(struct led_classdev *led_cdev, * Byte 3 is shared between the USB LED target on/off/blink * and also the buzzer control (in the input driver) */ - cmd[2] = 'D' + usb_led->mode; + cmd[2] = 'E' + usb_led->mode; return qnap_mcu_exec_with_ack(usb_led->mcu, cmd, sizeof(cmd)); } From c2d5d8f247049e22ef0afe8188cf8a6430144a17 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 4 Aug 2025 13:49:49 +0200 Subject: [PATCH 07/14] leds: qnap-mcu: Add support for the red and green status LEDs There is one more set of two LEDs on the qnap devices to indicate status. One LED is green, the other is red and while they occupy the same space on the front panel, they cannot be enabled at the same time. But they can interact via blink functions, the MCU can flash them alternately, going red -> green -> red -> ... either in 500ms or 1s intervals. They can of course also blink individually. Add specific LED functions for them and register them on probe. Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20250804114949.3127417-3-heiko@sntech.de Signed-off-by: Lee Jones --- drivers/leds/leds-qnap-mcu.c | 165 +++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/drivers/leds/leds-qnap-mcu.c b/drivers/leds/leds-qnap-mcu.c index fe055c5511b8..6df110e33ac9 100644 --- a/drivers/leds/leds-qnap-mcu.c +++ b/drivers/leds/leds-qnap-mcu.c @@ -190,6 +190,166 @@ static int qnap_mcu_register_usb_led(struct device *dev, struct qnap_mcu *mcu) return qnap_mcu_usb_led_set(&usb_led->cdev, 0); } +enum qnap_mcu_status_led_mode { + QNAP_MCU_STATUS_LED_OFF = 0, + QNAP_MCU_STATUS_LED_ON = 1, + QNAP_MCU_STATUS_LED_BLINK_FAST = 2, /* 500ms / 500ms */ + QNAP_MCU_STATUS_LED_BLINK_SLOW = 3, /* 1s / 1s */ +}; + +struct qnap_mcu_status_led { + struct led_classdev cdev; + struct qnap_mcu_status_led *red; + u8 mode; +}; + +struct qnap_mcu_status { + struct qnap_mcu *mcu; + struct qnap_mcu_status_led red; + struct qnap_mcu_status_led green; +}; + +static inline struct qnap_mcu_status_led *cdev_to_qnap_mcu_status_led(struct led_classdev *led_cdev) +{ + return container_of(led_cdev, struct qnap_mcu_status_led, cdev); +} + +static inline struct qnap_mcu_status *statusled_to_qnap_mcu_status(struct qnap_mcu_status_led *led) +{ + return container_of(led->red, struct qnap_mcu_status, red); +} + +static u8 qnap_mcu_status_led_encode(struct qnap_mcu_status *status) +{ + if (status->red.mode == QNAP_MCU_STATUS_LED_OFF) { + switch (status->green.mode) { + case QNAP_MCU_STATUS_LED_OFF: + return '9'; + case QNAP_MCU_STATUS_LED_ON: + return '6'; + case QNAP_MCU_STATUS_LED_BLINK_FAST: + return '5'; + case QNAP_MCU_STATUS_LED_BLINK_SLOW: + return 'A'; + } + } else if (status->green.mode == QNAP_MCU_STATUS_LED_OFF) { + switch (status->red.mode) { + case QNAP_MCU_STATUS_LED_OFF: + return '9'; + case QNAP_MCU_STATUS_LED_ON: + return '7'; + case QNAP_MCU_STATUS_LED_BLINK_FAST: + return '4'; + case QNAP_MCU_STATUS_LED_BLINK_SLOW: + return 'B'; + } + } else if (status->green.mode == QNAP_MCU_STATUS_LED_ON && + status->red.mode == QNAP_MCU_STATUS_LED_ON) { + return 'D'; + } else if (status->green.mode == QNAP_MCU_STATUS_LED_BLINK_SLOW && + status->red.mode == QNAP_MCU_STATUS_LED_BLINK_SLOW) { + return 'C'; + } + + /* + * Here both LEDs are on in some fashion, either both blinking fast, + * or in different speeds, so default to fast blinking for both. + */ + return '8'; +} + +static int qnap_mcu_status_led_update(struct qnap_mcu *mcu, + struct qnap_mcu_status *status) +{ + u8 cmd[] = { '@', 'C', 0 }; + + cmd[2] = qnap_mcu_status_led_encode(status); + + return qnap_mcu_exec_with_ack(mcu, cmd, sizeof(cmd)); +} + +static int qnap_mcu_status_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct qnap_mcu_status_led *status_led = cdev_to_qnap_mcu_status_led(led_cdev); + struct qnap_mcu_status *base = statusled_to_qnap_mcu_status(status_led); + + /* Don't disturb a possible set blink-mode if LED stays on */ + if (brightness != 0 && status_led->mode >= QNAP_MCU_STATUS_LED_BLINK_FAST) + return 0; + + status_led->mode = brightness ? QNAP_MCU_STATUS_LED_ON : + QNAP_MCU_STATUS_LED_OFF; + + return qnap_mcu_status_led_update(base->mcu, base); +} + +static int qnap_mcu_status_led_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct qnap_mcu_status_led *status_led = cdev_to_qnap_mcu_status_led(led_cdev); + struct qnap_mcu_status *base = statusled_to_qnap_mcu_status(status_led); + + if (status_led->mode == QNAP_MCU_STATUS_LED_OFF) + return 0; + + if (*delay_on <= 500) { + *delay_on = 500; + *delay_off = 500; + status_led->mode = QNAP_MCU_STATUS_LED_BLINK_FAST; + } else { + *delay_on = 1000; + *delay_off = 1000; + status_led->mode = QNAP_MCU_STATUS_LED_BLINK_SLOW; + } + + return qnap_mcu_status_led_update(base->mcu, base); +} + +static int qnap_mcu_register_status_leds(struct device *dev, struct qnap_mcu *mcu) +{ + struct qnap_mcu_status *status; + int ret; + + status = devm_kzalloc(dev, sizeof(*status), GFP_KERNEL); + if (!status) + return -ENOMEM; + + status->mcu = mcu; + + /* + * point to the red led, so that statusled_to_qnap_mcu_status + * can resolve the main status struct containing both leds + */ + status->red.red = &status->red; + status->green.red = &status->red; + + status->red.mode = QNAP_MCU_STATUS_LED_OFF; + status->red.cdev.name = "red:status"; + status->red.cdev.brightness_set_blocking = qnap_mcu_status_led_set; + status->red.cdev.blink_set = qnap_mcu_status_led_blink_set; + status->red.cdev.brightness = 0; + status->red.cdev.max_brightness = 1; + + status->green.mode = QNAP_MCU_STATUS_LED_OFF; + status->green.cdev.name = "green:status"; + status->green.cdev.brightness_set_blocking = qnap_mcu_status_led_set; + status->green.cdev.blink_set = qnap_mcu_status_led_blink_set; + status->green.cdev.brightness = 0; + status->green.cdev.max_brightness = 1; + + ret = devm_led_classdev_register(dev, &status->red.cdev); + if (ret) + return ret; + + ret = devm_led_classdev_register(dev, &status->green.cdev); + if (ret) + return ret; + + return qnap_mcu_status_led_update(status->mcu, status); +} + static int qnap_mcu_leds_probe(struct platform_device *pdev) { struct qnap_mcu *mcu = dev_get_drvdata(pdev->dev.parent); @@ -210,6 +370,11 @@ static int qnap_mcu_leds_probe(struct platform_device *pdev) "failed to register USB LED\n"); } + ret = qnap_mcu_register_status_leds(&pdev->dev, mcu); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register status LEDs\n"); + return 0; } From 19c5010e8ae23faf7b98fd738ff9970bb9066b78 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 11 Aug 2025 15:54:03 +0200 Subject: [PATCH 08/14] dt-bindings: leds: issi,is31fl319x: Drop 'db' suffix duplicating dtschema A common property unit suffix '-db' was added to dtschema, thus in-kernel bindings should not reference the type. Signed-off-by: Krzysztof Kozlowski Acked-by: "Rob Herring (Arm)" Link: https://lore.kernel.org/r/20250811-dt-bindings-db-v1-1-457301523bb5@linaro.org Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml b/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml index 3c0431c51159..906735acfbaf 100644 --- a/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml +++ b/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml @@ -42,7 +42,6 @@ properties: description: GPIO attached to the SDB pin. audio-gain-db: - $ref: /schemas/types.yaml#/definitions/uint32 default: 0 description: Audio gain selection for external analog modulation input. enum: [0, 3, 6, 9, 12, 15, 18, 21] From d6058316d16ee0d1861c0550051b2492efb54b79 Mon Sep 17 00:00:00 2001 From: Andrei Lalaev Date: Wed, 20 Aug 2025 10:47:12 +0200 Subject: [PATCH 09/14] leds: leds-lp55xx: Use correct address for memory programming Memory programming doesn't work for devices without page support. For example, LP5562 has 3 engines but doesn't support pages, the start address is changed depending on engine number. According to datasheet [1], the PROG MEM register addresses for each engine are as follows: Engine 1: 0x10 Engine 2: 0x30 Engine 3: 0x50 However, the current implementation incorrectly calculates the address of PROG MEM register using the engine index starting from 1: prog_mem_base = 0x10 LP55xx_BYTES_PER_PAGE = 0x20 Engine 1: 0x10 + 0x20 * 1 = 0x30 Engine 2: 0x10 + 0x20 * 2 = 0x50 Engine 3: 0x10 + 0x20 * 3 = 0x70 This results in writing to the wrong engine memory, causing pattern programming to fail. To correct it, the engine index should be decreased: Engine 1: 0x10 + 0x20 * 0 = 0x10 Engine 2: 0x10 + 0x20 * 1 = 0x30 Engine 3: 0x10 + 0x20 * 2 = 0x50 1 - https://www.ti.com/lit/ds/symlink/lp5562.pdf Fixes: 31379a57cf2f ("leds: leds-lp55xx: Generalize update_program_memory function") Signed-off-by: Andrei Lalaev Link: https://lore.kernel.org/r/20250820-lp5562-prog-mem-address-v1-1-8569647fa71d@anton-paar.com Signed-off-by: Lee Jones --- drivers/leds/leds-lp55xx-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index e71456a56ab8..fd447eb7eb15 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -212,7 +212,7 @@ int lp55xx_update_program_memory(struct lp55xx_chip *chip, * For LED chip that support page, PAGE is already set in load_engine. */ if (!cfg->pages_per_engine) - start_addr += LP55xx_BYTES_PER_PAGE * idx; + start_addr += LP55xx_BYTES_PER_PAGE * (idx - 1); for (page = 0; page < program_length / LP55xx_BYTES_PER_PAGE; page++) { /* Write to the next page each 32 bytes (if supported) */ From 96e048fa11d6aedf4add4c2f93a8d06445948056 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 7 Sep 2025 12:16:09 +0200 Subject: [PATCH 10/14] leds: is31fl319x: Use devm_mutex_init() Use devm_mutex_init() instead of hand-writing it. This saves some LoC, improves readability and saves some space in the generated .o file. Before: ====== text data bss dec hex filename 20011 6752 128 26891 690b drivers/leds/leds-is31fl319x.o After: ===== text data bss dec hex filename 19715 6680 128 26523 679b drivers/leds/leds-is31fl319x.o Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/267aba6eab12be67c297fcd52fcf45a0856338bb.1757240150.git.christophe.jaillet@wanadoo.fr Signed-off-by: Lee Jones --- drivers/leds/leds-is31fl319x.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c index 27bfab3da479..e411cee06dab 100644 --- a/drivers/leds/leds-is31fl319x.c +++ b/drivers/leds/leds-is31fl319x.c @@ -483,11 +483,6 @@ static inline int is31fl3196_db_to_gain(u32 dezibel) return dezibel / IS31FL3196_AUDIO_GAIN_DB_STEP; } -static void is31f1319x_mutex_destroy(void *lock) -{ - mutex_destroy(lock); -} - static int is31fl319x_probe(struct i2c_client *client) { struct is31fl319x_chip *is31; @@ -503,8 +498,7 @@ static int is31fl319x_probe(struct i2c_client *client) if (!is31) return -ENOMEM; - mutex_init(&is31->lock); - err = devm_add_action_or_reset(dev, is31f1319x_mutex_destroy, &is31->lock); + err = devm_mutex_init(dev, &is31->lock); if (err) return err; From 3f5df63955756fbe253a2a26043accf7318fa53a Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Wed, 10 Sep 2025 14:01:08 +0200 Subject: [PATCH 11/14] dt-bindings: leds: Add generic LED consumer documentation Introduce common generic led consumer binding, where consumer defines led(s) by phandle, as opposed to trigger-source binding where the trigger source is defined in led itself. Add already used in some schemas 'leds' parameter which expects phandle-array. Additionally, introduce 'led-names' which could be used by consumers to map LED devices to their respective functions. Signed-off-by: Aleksandrs Vinarskis Reviewed-by: "Rob Herring (Arm)" Link: https://lore.kernel.org/r/20250910-leds-v5-1-bb90a0f897d5@vinarskis.com Signed-off-by: Lee Jones --- .../bindings/leds/leds-consumer.yaml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-consumer.yaml diff --git a/Documentation/devicetree/bindings/leds/leds-consumer.yaml b/Documentation/devicetree/bindings/leds/leds-consumer.yaml new file mode 100644 index 000000000000..fe6a0faa1d3b --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-consumer.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/leds-consumer.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Common leds consumer + +maintainers: + - Aleksandrs Vinarskis + +description: + Some LED defined in DT are required by other DT consumers, for example + v4l2 subnode may require privacy or flash LED. Unlike trigger-source + approach which is typically used as 'soft' binding, referencing LED + devices by phandle makes things simpler when 'hard' binding is desired. + + Document LED properties that its consumers may define. + +select: true + +properties: + leds: + oneOf: + - type: object + - $ref: /schemas/types.yaml#/definitions/phandle-array + description: + A list of LED device(s) required by a particular consumer. + items: + maxItems: 1 + + led-names: + description: + A list of device name(s). Used to map LED devices to their respective + functions, when consumer requires more than one LED. + +additionalProperties: true + +examples: + - | + #include + #include + + leds { + compatible = "gpio-leds"; + + privacy_led: privacy-led { + color = ; + default-state = "off"; + function = LED_FUNCTION_INDICATOR; + gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>; + }; + }; + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + v4l2_node: camera@36 { + reg = <0x36>; + + leds = <&privacy_led>; + led-names = "privacy"; + }; + }; + +... From 22420da3662a69d8894ee624494213a5888a1e87 Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Wed, 10 Sep 2025 14:01:09 +0200 Subject: [PATCH 12/14] dt-bindings: leds: Unify 'leds' property A number of existing schemas use 'leds' property to provide phandle-array of LED(s) to the consumer. Additionally, with the upcoming privacy-led support in device-tree, v4l2 subnode could be a LED consumer, meaning that all camera sensors should support 'leds' and 'led-names' property via common 'video-interface-devices.yaml'. To avoid duplication, unify 'leds' property from existing schemas to newly introduced 'led-consumer.yaml'. Signed-off-by: Aleksandrs Vinarskis Reviewed-by: "Rob Herring (Arm)" Link: https://lore.kernel.org/r/20250910-leds-v5-2-bb90a0f897d5@vinarskis.com Signed-off-by: Lee Jones --- .../devicetree/bindings/leds/backlight/led-backlight.yaml | 6 +----- .../devicetree/bindings/leds/leds-group-multicolor.yaml | 5 +---- .../bindings/media/video-interface-devices.yaml | 8 ++++++++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml b/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml index f5554da6bc6c..8fc5af8f27f9 100644 --- a/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml +++ b/Documentation/devicetree/bindings/leds/backlight/led-backlight.yaml @@ -23,11 +23,7 @@ properties: compatible: const: led-backlight - leds: - description: A list of LED nodes - $ref: /schemas/types.yaml#/definitions/phandle-array - items: - maxItems: 1 + leds: true required: - compatible diff --git a/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml index 8ed059a5a724..5c9cfa39396b 100644 --- a/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml +++ b/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml @@ -17,10 +17,7 @@ properties: compatible: const: leds-group-multicolor - leds: - description: - An aray of monochromatic leds - $ref: /schemas/types.yaml#/definitions/phandle-array + leds: true required: - leds diff --git a/Documentation/devicetree/bindings/media/video-interface-devices.yaml b/Documentation/devicetree/bindings/media/video-interface-devices.yaml index cf7712ad297c..3ad1590b0496 100644 --- a/Documentation/devicetree/bindings/media/video-interface-devices.yaml +++ b/Documentation/devicetree/bindings/media/video-interface-devices.yaml @@ -17,6 +17,14 @@ properties: An array of phandles, each referring to a flash LED, a sub-node of the LED driver device node. + leds: + minItems: 1 + maxItems: 1 + + led-names: + enum: + - privacy + lens-focus: $ref: /schemas/types.yaml#/definitions/phandle description: From ef381e17930e9c5268a53f57187c87a85676d0f7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 Sep 2025 14:01:10 +0200 Subject: [PATCH 13/14] leds: led-class: Add Device Tree support to led_get() Add 'name' argument to of_led_get() such that it can lookup LEDs in devicetree by either name or index. And use this modified function to add devicetree support to the generic (non devicetree specific) [devm_]led_get() function. This uses the standard devicetree pattern of adding a -names string array to map names to the indexes for an array of resources. Reviewed-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Hans de Goede Signed-off-by: Aleksandrs Vinarskis Link: https://lore.kernel.org/r/20250910-leds-v5-3-bb90a0f897d5@vinarskis.com Signed-off-by: Lee Jones --- drivers/leds/led-class.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 15633fbf3c16..f3faf37f9a08 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -252,15 +252,23 @@ static const struct class leds_class = { * of_led_get() - request a LED device via the LED framework * @np: device node to get the LED device from * @index: the index of the LED + * @name: the name of the LED used to map it to its function, if present * * Returns the LED device parsed from the phandle specified in the "leds" * property of a device tree node or a negative error-code on failure. */ -static struct led_classdev *of_led_get(struct device_node *np, int index) +static struct led_classdev *of_led_get(struct device_node *np, int index, + const char *name) { struct device *led_dev; struct device_node *led_node; + /* + * For named LEDs, first look up the name in the "led-names" property. + * If it cannot be found, then of_parse_phandle() will propagate the error. + */ + if (name) + index = of_property_match_string(np, "led-names", name); led_node = of_parse_phandle(np, "leds", index); if (!led_node) return ERR_PTR(-ENOENT); @@ -324,7 +332,7 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, if (!dev) return ERR_PTR(-EINVAL); - led = of_led_get(dev->of_node, index); + led = of_led_get(dev->of_node, index, NULL); if (IS_ERR(led)) return led; @@ -342,9 +350,14 @@ EXPORT_SYMBOL_GPL(devm_of_led_get); struct led_classdev *led_get(struct device *dev, char *con_id) { struct led_lookup_data *lookup; + struct led_classdev *led_cdev; const char *provider = NULL; struct device *led_dev; + led_cdev = of_led_get(dev->of_node, -1, con_id); + if (!IS_ERR(led_cdev) || PTR_ERR(led_cdev) != -ENOENT) + return led_cdev; + mutex_lock(&leds_lookup_lock); list_for_each_entry(lookup, &leds_lookup_list, list) { if (!strcmp(lookup->dev_id, dev_name(dev)) && From 64826db1e2e177b58dcbc7cf1e1379527be2185a Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Tue, 16 Sep 2025 16:11:01 +0100 Subject: [PATCH 14/14] dt-bindings: leds: as3645: Convert to DT schema Convert the ams,as3645a.txt to DT Schema format. Signed-off-by: Harrison Carter Reviewed-by: "Rob Herring (Arm)" Signed-off-by: Lee Jones --- .../devicetree/bindings/leds/ams,as3645a.txt | 85 ------------ .../devicetree/bindings/leds/ams,as3645a.yaml | 130 ++++++++++++++++++ 2 files changed, 130 insertions(+), 85 deletions(-) delete mode 100644 Documentation/devicetree/bindings/leds/ams,as3645a.txt create mode 100644 Documentation/devicetree/bindings/leds/ams,as3645a.yaml diff --git a/Documentation/devicetree/bindings/leds/ams,as3645a.txt b/Documentation/devicetree/bindings/leds/ams,as3645a.txt deleted file mode 100644 index 4af2987b25e9..000000000000 --- a/Documentation/devicetree/bindings/leds/ams,as3645a.txt +++ /dev/null @@ -1,85 +0,0 @@ -Analog devices AS3645A device tree bindings - -The AS3645A flash LED controller can drive two LEDs, one high current -flash LED and one indicator LED. The high current flash LED can be -used in torch mode as well. - -Ranges below noted as [a, b] are closed ranges between a and b, i.e. a -and b are included in the range. - -Please also see common.txt in the same directory. - - -Required properties -=================== - -compatible : Must be "ams,as3645a". -reg : The I2C address of the device. Typically 0x30. -#address-cells : 1 -#size-cells : 0 - - -Required properties of the flash child node (0) -=============================================== - -reg: 0 -flash-timeout-us: Flash timeout in microseconds. The value must be in - the range [100000, 850000] and divisible by 50000. -flash-max-microamp: Maximum flash current in microamperes. Has to be - in the range between [200000, 500000] and - divisible by 20000. -led-max-microamp: Maximum torch (assist) current in microamperes. The - value must be in the range between [20000, 160000] and - divisible by 20000. -ams,input-max-microamp: Maximum flash controller input current. The - value must be in the range [1250000, 2000000] - and divisible by 50000. - - -Optional properties of the flash child node -=========================================== - -function : See Documentation/devicetree/bindings/leds/common.txt. -color : See Documentation/devicetree/bindings/leds/common.txt. -label : See Documentation/devicetree/bindings/leds/common.txt (deprecated). - - -Required properties of the indicator child node (1) -=================================================== - -reg: 1 -led-max-microamp: Maximum indicator current. The allowed values are - 2500, 5000, 7500 and 10000. - -Optional properties of the indicator child node -=============================================== - -function : See Documentation/devicetree/bindings/leds/common.txt. -color : See Documentation/devicetree/bindings/leds/common.txt. -label : See Documentation/devicetree/bindings/leds/common.txt (deprecated). - - -Example -======= - -#include - - as3645a@30 { - #address-cells = <1>; - #size-cells = <0>; - reg = <0x30>; - compatible = "ams,as3645a"; - led@0 { - reg = <0x0>; - flash-timeout-us = <150000>; - flash-max-microamp = <320000>; - led-max-microamp = <60000>; - ams,input-max-microamp = <1750000>; - function = LED_FUNCTION_FLASH; - }; - led@1 { - reg = <0x1>; - led-max-microamp = <10000>; - function = LED_FUNCTION_INDICATOR; - }; - }; diff --git a/Documentation/devicetree/bindings/leds/ams,as3645a.yaml b/Documentation/devicetree/bindings/leds/ams,as3645a.yaml new file mode 100644 index 000000000000..250a4b275d8a --- /dev/null +++ b/Documentation/devicetree/bindings/leds/ams,as3645a.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/ams,as3645a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AS3645A LED Controller + +maintainers: + - Sakari Ailus + +description: + The AS3645A flash LED controller can drive two LEDs, one + high current flash LED and one indicator LED. The high + current flash LED can be used in torch mode as well. + +properties: + compatible: + const: ams,as3645a + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + maxItems: 1 + + led@0: + description: led0 describes the 'flash' feature + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + const: 0 + + flash-timeout-us: + minimum: 100000 + maximum: 850000 + multipleOf: 50000 + + flash-max-microamp: + minimum: 200000 + maximum: 500000 + multipleOf: 20000 + + led-max-microamp: + minimum: 20000 + maximum: 160000 + multipleOf: 20000 + description: + Maximum current when in torch (assist) mode. + + ams,input-max-microamp: + minimum: 1250000 + maximum: 2000000 + multipleOf: 50000 + + required: + - reg + - flash-timeout-us + - flash-max-microamp + - led-max-microamp + - ams,input-max-microamp + + led@1: + description: led1 describes the 'indicator' feature + type: object + $ref: common.yaml# + unevaluatedProperties: false + + properties: + reg: + const: 1 + + led-max-microamp: + enum: + - 2500 + - 5000 + - 7500 + - 10000 + description: + Maximum indicator current. + + required: + - reg + - led-max-microamp + +required: + - compatible + - reg + - "#size-cells" + - "#address-cells" + +additionalProperties: false + +examples: + - | + #include + + i2c{ + #address-cells = <1>; + #size-cells = <0>; + + led-controller@30 { + compatible = "ams,as3645a"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x30>; + + led@0 { + reg = <0>; + flash-timeout-us = <150000>; + flash-max-microamp = <320000>; + led-max-microamp = <60000>; + ams,input-max-microamp = <1750000>; + function = LED_FUNCTION_FLASH; + }; + + led@1 { + reg = <1>; + led-max-microamp = <10000>; + function = LED_FUNCTION_INDICATOR; + }; + }; + }; +...