From 293fee7f607841cc128c3f6df9b464e8abf99fb0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 28 May 2021 22:23:59 +0200 Subject: [PATCH 01/32] leds: aat1290: Move driver to flash subdirectory We created a subdirectory for LED drivers that depend on CONFIG_LEDS_CLASS_FLASH, and this driver does so let's move it there. Signed-off-by: Linus Walleij Acked-by: Jacek Anaszewski Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 10 ---------- drivers/leds/Makefile | 1 - drivers/leds/flash/Kconfig | 9 +++++++++ drivers/leds/flash/Makefile | 1 + drivers/leds/{ => flash}/leds-aat1290.c | 0 5 files changed, 10 insertions(+), 11 deletions(-) rename drivers/leds/{ => flash}/leds-aat1290.c (100%) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index bdf16180f5ff..a350d8fbb085 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -59,16 +59,6 @@ config LEDS_88PM860X This option enables support for on-chip LED drivers found on Marvell Semiconductor 88PM8606 PMIC. -config LEDS_AAT1290 - tristate "LED support for the AAT1290" - depends on LEDS_CLASS_FLASH - depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS - depends on GPIOLIB || COMPILE_TEST - depends on OF - depends on PINCTRL - help - This option enables support for the LEDs on the AAT1290. - config LEDS_AN30259A tristate "LED support for Panasonic AN30259A" depends on LEDS_CLASS && I2C && OF diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 7e604d3028c8..c7231975837a 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o # LED Platform Drivers (keep this sorted, M-| sort) obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o -obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o obj-$(CONFIG_LEDS_ACER_A500) += leds-acer-a500.o obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 3f49f3edbffb..736153b0bfd6 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -2,6 +2,15 @@ if LEDS_CLASS_FLASH +config LEDS_AAT1290 + tristate "LED support for the AAT1290" + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS + depends on GPIOLIB || COMPILE_TEST + depends on OF + depends on PINCTRL + help + This option enables support for the LEDs on the AAT1290. + config LEDS_RT4505 tristate "LED support for RT4505 flashlight controller" depends on I2C && OF diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index 09aee561f769..11bec5881d51 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/flash/leds-aat1290.c similarity index 100% rename from drivers/leds/leds-aat1290.c rename to drivers/leds/flash/leds-aat1290.c From f5d69f6290a37f5579ef24334d5bf8a59bb13ef4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 28 May 2021 22:24:00 +0200 Subject: [PATCH 02/32] leds: as3645a: Move driver to flash subdirectory We created a subdirectory for LED drivers that depend on CONFIG_LEDS_CLASS_FLASH, and this driver does so let's move it there. Signed-off-by: Linus Walleij Acked-by: Sakari Ailus Signed-off-by: Pavel Machek --- MAINTAINERS | 2 +- drivers/leds/Kconfig | 9 --------- drivers/leds/Makefile | 1 - drivers/leds/flash/Kconfig | 9 +++++++++ drivers/leds/flash/Makefile | 1 + drivers/leds/{ => flash}/leds-as3645a.c | 0 6 files changed, 11 insertions(+), 11 deletions(-) rename drivers/leds/{ => flash}/leds-as3645a.c (100%) diff --git a/MAINTAINERS b/MAINTAINERS index a61f4f3b78a9..7169a6bb8d91 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2841,7 +2841,7 @@ AS3645A LED FLASH CONTROLLER DRIVER M: Sakari Ailus L: linux-leds@vger.kernel.org S: Maintained -F: drivers/leds/leds-as3645a.c +F: drivers/leds/flash/leds-as3645a.c ASAHI KASEI AK7375 LENS VOICE COIL DRIVER M: Tianshu Qiu diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index a350d8fbb085..cfa6b8194b6b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -94,15 +94,6 @@ config LEDS_ARIEL Say Y to if your machine is a Dell Wyse 3020 thin client. -config LEDS_AS3645A - tristate "AS3645A and LM3555 LED flash controllers support" - depends on I2C && LEDS_CLASS_FLASH - depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS - help - Enable LED flash class support for AS3645A LED flash - controller. V4L2 flash API is provided as well if - CONFIG_V4L2_FLASH_API is enabled. - config LEDS_AW2013 tristate "LED support for Awinic AW2013" depends on LEDS_CLASS && I2C && OF diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index c7231975837a..a3a6fda8ab99 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o obj-$(CONFIG_LEDS_APU) += leds-apu.o obj-$(CONFIG_LEDS_ARIEL) += leds-ariel.o -obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o obj-$(CONFIG_LEDS_AW2013) += leds-aw2013.o obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 736153b0bfd6..1126ad3954b6 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -11,6 +11,15 @@ config LEDS_AAT1290 help This option enables support for the LEDs on the AAT1290. +config LEDS_AS3645A + tristate "AS3645A and LM3555 LED flash controllers support" + depends on I2C + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS + help + Enable LED flash class support for AS3645A LED flash + controller. V4L2 flash API is provided as well if + CONFIG_V4L2_FLASH_API is enabled. + config LEDS_RT4505 tristate "LED support for RT4505 flashlight controller" depends on I2C && OF diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index 11bec5881d51..9bb2fccee047 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o +obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/flash/leds-as3645a.c similarity index 100% rename from drivers/leds/leds-as3645a.c rename to drivers/leds/flash/leds-as3645a.c From eb5a4422e448a8200ddaafef0cc16db3f45ec1f8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 28 May 2021 22:24:01 +0200 Subject: [PATCH 03/32] leds: max77693: Move driver to flash subdirectory We created a subdirectory for LED drivers that depend on CONFIG_LEDS_CLASS_FLASH, and this driver does so let's move it there. Signed-off-by: Linus Walleij Acked-by: Jacek Anaszewski Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 11 ----------- drivers/leds/Makefile | 1 - drivers/leds/flash/Kconfig | 10 ++++++++++ drivers/leds/flash/Makefile | 1 + drivers/leds/{ => flash}/leds-max77693.c | 0 5 files changed, 11 insertions(+), 12 deletions(-) rename drivers/leds/{ => flash}/leds-max77693.c (100%) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index cfa6b8194b6b..723de0d30039 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -680,17 +680,6 @@ config LEDS_MAX77650 help LEDs driver for MAX77650 family of PMICs from Maxim Integrated. -config LEDS_MAX77693 - tristate "LED support for MAX77693 Flash" - depends on LEDS_CLASS_FLASH - depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS - depends on MFD_MAX77693 - depends on OF - help - This option enables support for the flash part of the MAX77693 - multifunction device. It has build in control for two leds in flash - and torch mode. - config LEDS_MAX8997 tristate "LED support for MAX8997 PMIC" depends on LEDS_CLASS && MFD_MAX8997 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a3a6fda8ab99..6f4aa0e6e355 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -58,7 +58,6 @@ obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o -obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 1126ad3954b6..6401af23947f 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -20,6 +20,16 @@ config LEDS_AS3645A controller. V4L2 flash API is provided as well if CONFIG_V4L2_FLASH_API is enabled. +config LEDS_MAX77693 + tristate "LED support for MAX77693 Flash" + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS + depends on MFD_MAX77693 + depends on OF + help + This option enables support for the flash part of the MAX77693 + multifunction device. It has build in control for two leds in flash + and torch mode. + config LEDS_RT4505 tristate "LED support for RT4505 flashlight controller" depends on I2C && OF diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index 9bb2fccee047..c2a5e530261d 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o +obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/flash/leds-max77693.c similarity index 100% rename from drivers/leds/leds-max77693.c rename to drivers/leds/flash/leds-max77693.c From 9a7c066f6a1dfff2f30e697fe494a669428fc9f4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 28 May 2021 22:24:02 +0200 Subject: [PATCH 04/32] leds: sgm3140: Move driver to flash subdirectory We created a subdirectory for LED drivers that depend on CONFIG_LEDS_CLASS_FLASH, and this driver does so let's move it there. Cc: Luca Weiss Signed-off-by: Linus Walleij Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 8 -------- drivers/leds/Makefile | 1 - drivers/leds/flash/Kconfig | 7 +++++++ drivers/leds/flash/Makefile | 1 + drivers/leds/{ => flash}/leds-sgm3140.c | 0 5 files changed, 8 insertions(+), 9 deletions(-) rename drivers/leds/{ => flash}/leds-sgm3140.c (100%) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 723de0d30039..171ccfd4de1b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -883,14 +883,6 @@ config LEDS_IP30 To compile this driver as a module, choose M here: the module will be called leds-ip30. -config LEDS_SGM3140 - tristate "LED support for the SGM3140" - depends on LEDS_CLASS_FLASH - depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS - help - This option enables support for the SGM3140 500mA Buck/Boost Charge - Pump LED Driver. - config LEDS_ACER_A500 tristate "Power button LED support for Acer Iconia Tab A500" depends on LEDS_CLASS && MFD_ACER_A500_EC diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 6f4aa0e6e355..5e804f72b8e5 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -79,7 +79,6 @@ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o -obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 6401af23947f..788d698587a7 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -52,4 +52,11 @@ config LEDS_RT8515 To compile this driver as a module, choose M here: the module will be called leds-rt8515. +config LEDS_SGM3140 + tristate "LED support for the SGM3140" + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS + help + This option enables support for the SGM3140 500mA Buck/Boost Charge + Pump LED Driver. + endif # LEDS_CLASS_FLASH diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index c2a5e530261d..2f9153e78717 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o +obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o diff --git a/drivers/leds/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c similarity index 100% rename from drivers/leds/leds-sgm3140.c rename to drivers/leds/flash/leds-sgm3140.c From 61fa67a4e538f70bb4e6b3e7f3555402c1713654 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 28 May 2021 22:24:03 +0200 Subject: [PATCH 05/32] leds: lm3601x: Move driver to flash subdirectory We created a subdirectory for LED drivers that depend on CONFIG_LEDS_CLASS_FLASH, and this driver does so let's move it there. Cc: Dan Murphy Signed-off-by: Linus Walleij Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 9 --------- drivers/leds/Makefile | 1 - drivers/leds/flash/Kconfig | 8 ++++++++ drivers/leds/flash/Makefile | 1 + drivers/leds/{ => flash}/leds-lm3601x.c | 0 5 files changed, 9 insertions(+), 10 deletions(-) rename drivers/leds/{ => flash}/leds-lm3601x.c (100%) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 171ccfd4de1b..1671aa2f90b5 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -220,15 +220,6 @@ config LEDS_LM3692X This option enables support for the TI LM3692x family of white LED string drivers used for backlighting. -config LEDS_LM3601X - tristate "LED support for LM3601x Chips" - depends on LEDS_CLASS && I2C - depends on LEDS_CLASS_FLASH - select REGMAP_I2C - help - This option enables support for the TI LM3601x family - of flash, torch and indicator classes. - config LEDS_LOCOMO tristate "LED Support for Locomo device" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 5e804f72b8e5..6d5c23afaf98 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o obj-$(CONFIG_LEDS_LM3532) += leds-lm3532.o obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o -obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o obj-$(CONFIG_LEDS_LM3642) += leds-lm3642.o obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 788d698587a7..6cb6600555f0 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -20,6 +20,14 @@ config LEDS_AS3645A controller. V4L2 flash API is provided as well if CONFIG_V4L2_FLASH_API is enabled. +config LEDS_LM3601X + tristate "LED support for LM3601x Chips" + depends on LEDS_CLASS && I2C + select REGMAP_I2C + help + This option enables support for the TI LM3601x family + of flash, torch and indicator classes. + config LEDS_MAX77693 tristate "LED support for MAX77693 Flash" depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index 2f9153e78717..67556329441e 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o +obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o diff --git a/drivers/leds/leds-lm3601x.c b/drivers/leds/flash/leds-lm3601x.c similarity index 100% rename from drivers/leds/leds-lm3601x.c rename to drivers/leds/flash/leds-lm3601x.c From 51f3b2c3d511c7753f039176bbce08e8d53a0845 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 28 May 2021 22:24:04 +0200 Subject: [PATCH 06/32] leds: ktd2692: Move driver to flash subdirectory We created a subdirectory for LED drivers that depend on CONFIG_LEDS_CLASS_FLASH, and this driver does so let's move it there. Cc: Ingi Kim Signed-off-by: Linus Walleij Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 10 ---------- drivers/leds/Makefile | 1 - drivers/leds/flash/Kconfig | 10 ++++++++++ drivers/leds/flash/Makefile | 1 + drivers/leds/{ => flash}/leds-ktd2692.c | 0 5 files changed, 11 insertions(+), 11 deletions(-) rename drivers/leds/{ => flash}/leds-ktd2692.c (100%) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1671aa2f90b5..da7773dc8670 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -702,16 +702,6 @@ config LEDS_MENF21BMC This driver can also be built as a module. If so the module will be called leds-menf21bmc. -config LEDS_KTD2692 - tristate "LED support for KTD2692 flash LED controller" - depends on LEDS_CLASS_FLASH && OF - depends on GPIOLIB || COMPILE_TEST - help - This option enables support for KTD2692 LED flash connected - through ExpressWire interface. - - Say Y to enable this driver. - config LEDS_IS31FL319X tristate "LED Support for ISSI IS31FL319x I2C LED controller family" depends on LEDS_CLASS && I2C && OF diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 6d5c23afaf98..c636ec069612 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -35,7 +35,6 @@ obj-$(CONFIG_LEDS_IP30) += leds-ip30.o obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o -obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o obj-$(CONFIG_LEDS_LM3532) += leds-lm3532.o obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig index 6cb6600555f0..b230f3d65eb0 100644 --- a/drivers/leds/flash/Kconfig +++ b/drivers/leds/flash/Kconfig @@ -20,6 +20,16 @@ config LEDS_AS3645A controller. V4L2 flash API is provided as well if CONFIG_V4L2_FLASH_API is enabled. +config LEDS_KTD2692 + tristate "LED support for Kinetic KTD2692 flash LED controller" + depends on OF + depends on GPIOLIB || COMPILE_TEST + help + This option enables support for Kinetic KTD2692 LED flash connected + through ExpressWire interface. + + Say Y to enable this driver. + config LEDS_LM3601X tristate "LED support for LM3601x Chips" depends on LEDS_CLASS && I2C diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile index 67556329441e..ebea42f9c37e 100644 --- a/drivers/leds/flash/Makefile +++ b/drivers/leds/flash/Makefile @@ -2,6 +2,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_MAX77693) += leds-max77693.o obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/flash/leds-ktd2692.c similarity index 100% rename from drivers/leds/leds-ktd2692.c rename to drivers/leds/flash/leds-ktd2692.c From e642197562cd9781453f835e1406cfe0feeb917e Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Tue, 1 Jun 2021 19:09:03 +0800 Subject: [PATCH 07/32] leds: is31fl32xx: Fix missing error code in is31fl32xx_parse_dt() The error code is missing in this code scenario, add the error code '-EINVAL' to the return value 'ret'. Eliminate the follow smatch warning: drivers/leds/leds-is31fl32xx.c:388 is31fl32xx_parse_dt() warn: missing error code 'ret'. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Fixes: 9d7cffaf99f5 ("leds: Add driver for the ISSI IS31FL32xx family of LED controllers") Acked-by: David Rivshin Signed-off-by: Pavel Machek --- drivers/leds/leds-is31fl32xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c index 3b55af9a8c58..22c092a4394a 100644 --- a/drivers/leds/leds-is31fl32xx.c +++ b/drivers/leds/leds-is31fl32xx.c @@ -386,6 +386,7 @@ static int is31fl32xx_parse_dt(struct device *dev, dev_err(dev, "Node %pOF 'reg' conflicts with another LED\n", child); + ret = -EINVAL; goto err; } From e06ba23b0518875e56e385500613b8651f541742 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:25 +0300 Subject: [PATCH 08/32] leds: el15203000: Correct headers (of*.h -> mod_devicetable.h) There is no user of of*.h headers, but mod_devicetable.h. Update header block accordingly. Signed-off-by: Andy Shevchenko Reviewed-by: Oleh Kravchenko Signed-off-by: Pavel Machek --- drivers/leds/leds-el15203000.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c index 76b455e87574..f9eb59a25570 100644 --- a/drivers/leds/leds-el15203000.c +++ b/drivers/leds/leds-el15203000.c @@ -4,8 +4,9 @@ #include #include +#include #include -#include +#include #include /* From 9999908ca1abee7aa518a4f6a3739517c137acbf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:26 +0300 Subject: [PATCH 09/32] leds: lgm-sso: Put fwnode in any case during ->probe() fwnode_get_next_child_node() bumps a reference counting of a returned variable. We have to balance it whenever we return to the caller. All the same in fwnode_for_each_child_node() case. Fixes: c3987cd2bca3 ("leds: lgm: Add LED controller driver for LGM SoC") Cc: Amireddy Mallikarjuna reddy Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/blink/leds-lgm-sso.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index 7eb2f44f16be..62ce83cea553 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -631,8 +631,10 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) fwnode_for_each_child_node(fw_ssoled, fwnode_child) { led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); - if (!led) - return -ENOMEM; + if (!led) { + ret = -ENOMEM; + goto __dt_err; + } INIT_LIST_HEAD(&led->list); led->priv = priv; @@ -702,11 +704,11 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) if (sso_create_led(priv, led, fwnode_child)) goto __dt_err; } - fwnode_handle_put(fw_ssoled); return 0; + __dt_err: - fwnode_handle_put(fw_ssoled); + fwnode_handle_put(fwnode_child); /* unregister leds */ list_for_each(p, &priv->led_list) { led = list_entry(p, struct sso_led, list); @@ -731,6 +733,7 @@ static int sso_led_dt_parse(struct sso_led_priv *priv) fw_ssoled = fwnode_get_named_child_node(fwnode, "ssoled"); if (fw_ssoled) { ret = __sso_led_dt_parse(priv, fw_ssoled); + fwnode_handle_put(fw_ssoled); if (ret) return ret; } From 1ed4d05e0a0b23ba15e0affcff4008dd537ae3ee Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:27 +0300 Subject: [PATCH 10/32] leds: lgm-sso: Don't spam logs when probe is deferred When requesting GPIO line the probe can be deferred. In such case don't spam logs with an error message. This can be achieved by switching to dev_err_probe(). Fixes: c3987cd2bca3 ("leds: lgm: Add LED controller driver for LGM SoC") Cc: Amireddy Mallikarjuna reddy Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/blink/leds-lgm-sso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index 62ce83cea553..ca9f88996819 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -644,7 +644,7 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) fwnode_child, GPIOD_ASIS, NULL); if (IS_ERR(led->gpiod)) { - dev_err(dev, "led: get gpio fail!\n"); + dev_err_probe(dev, PTR_ERR(led->gpiod), "led: get gpio fail!\n"); goto __dt_err; } From c31ef7004ee1fd417dd9448ba4a43f42090d27fe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:28 +0300 Subject: [PATCH 11/32] leds: lgm-sso: Remove explicit managed GPIO resource cleanup The idea of managed resources is that they will be cleaned up automatically and in the proper order. Remove explicit GPIO cleanup. Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/blink/leds-lgm-sso.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index ca9f88996819..5c012ffeeaa8 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -611,9 +611,6 @@ static void sso_led_shutdown(struct sso_led *led) if (led->desc.hw_trig) regmap_update_bits(priv->mmap, SSO_CON3, BIT(led->desc.pin), 0); - if (led->gpiod) - devm_gpiod_put(priv->dev, led->gpiod); - led->priv = NULL; } From 3dd34dfb09ae814922dd833cad11b215b238a1ba Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:29 +0300 Subject: [PATCH 12/32] leds: lgm-sso: Convert to use list_for_each_entry*() API Convert to use list_for_each_entry*() API insted of open coded variants. It saves few lines of code and makes iteasier to read and maintain. Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/blink/leds-lgm-sso.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index 5c012ffeeaa8..e47c47e421d6 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -621,7 +621,6 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) struct device *dev = priv->dev; struct sso_led_desc *desc; struct sso_led *led; - struct list_head *p; const char *tmp; u32 prop; int ret; @@ -707,10 +706,8 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) __dt_err: fwnode_handle_put(fwnode_child); /* unregister leds */ - list_for_each(p, &priv->led_list) { - led = list_entry(p, struct sso_led, list); + list_for_each_entry(led, &priv->led_list, list) sso_led_shutdown(led); - } return -EINVAL; } @@ -841,14 +838,12 @@ static int intel_sso_led_probe(struct platform_device *pdev) static int intel_sso_led_remove(struct platform_device *pdev) { struct sso_led_priv *priv; - struct list_head *pos, *n; - struct sso_led *led; + struct sso_led *led, *n; priv = platform_get_drvdata(pdev); - list_for_each_safe(pos, n, &priv->led_list) { - list_del(pos); - led = list_entry(pos, struct sso_led, list); + list_for_each_entry_safe(led, n, &priv->led_list, list) { + list_del(&led->list); sso_led_shutdown(led); } From 690e4f3ad363ae5ad27222214509855d40d569a7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:30 +0300 Subject: [PATCH 13/32] leds: lm3692x: Correct headers (of*.h -> mod_devicetable.h) There is no user of of*.h headers, but mod_devicetable.h. Update header block accordingly. Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/leds-lm3692x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index a02756d7ed8f..afe6fb297855 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -7,10 +7,9 @@ #include #include #include +#include #include #include -#include -#include #include #include #include From 3a923639d36b1c54866236c2f53d112b797b0101 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:31 +0300 Subject: [PATCH 14/32] leds: lm3697: Update header block to reflect reality Currently the headers to be included look rather like a random set. Update them a bit to reflect the reality. While at it, drop unneeded dependcy to OF. Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/leds-lm3697.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 970a4f34791b..292d64b2eeab 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -2,11 +2,16 @@ // TI LM3697 LED chip family driver // Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/ +#include #include #include -#include -#include +#include +#include +#include +#include #include +#include + #include #define LM3697_REV 0x0 From d299ae942e0201ce3419501f523fbaac989dd036 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:32 +0300 Subject: [PATCH 15/32] leds: lm3697: Make error handling more robust It's easy to miss necessary clean up, e.g. firmware node reference counting, during error path in ->probe(). Make it more robust by moving to a single point of return. Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/leds-lm3697.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 292d64b2eeab..a8c9322558cc 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -226,14 +226,12 @@ static int lm3697_probe_dt(struct lm3697 *priv) ret = fwnode_property_read_u32(child, "reg", &control_bank); if (ret) { dev_err(dev, "reg property missing\n"); - fwnode_handle_put(child); goto child_out; } if (control_bank > LM3697_CONTROL_B) { dev_err(dev, "reg property is invalid\n"); ret = -EINVAL; - fwnode_handle_put(child); goto child_out; } @@ -264,7 +262,6 @@ static int lm3697_probe_dt(struct lm3697 *priv) led->num_leds); if (ret) { dev_err(dev, "led-sources property missing\n"); - fwnode_handle_put(child); goto child_out; } @@ -289,14 +286,16 @@ static int lm3697_probe_dt(struct lm3697 *priv) &init_data); if (ret) { dev_err(dev, "led register err: %d\n", ret); - fwnode_handle_put(child); goto child_out; } i++; } + return ret; + child_out: + fwnode_handle_put(child); return ret; } From 7e1baaaa2407a642ea19b58e214fab9a69cda1d7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:33 +0300 Subject: [PATCH 16/32] leds: lt3593: Put fwnode in any case during ->probe() device_get_next_child_node() bumps a reference counting of a returned variable. We have to balance it whenever we return to the caller. Fixes: 8cd7d6daba93 ("leds: lt3593: Add device tree probing glue") Cc: Daniel Mack Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/leds-lt3593.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 3bb52d3165d9..d0160fde0f94 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -97,10 +97,9 @@ static int lt3593_led_probe(struct platform_device *pdev) init_data.default_label = ":"; ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data); - if (ret < 0) { - fwnode_handle_put(child); + fwnode_handle_put(child); + if (ret < 0) return ret; - } platform_set_drvdata(pdev, led_data); From 8aa41952ef245449df79100e1942b5e6288b098a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 29 May 2021 14:19:34 +0300 Subject: [PATCH 17/32] leds: rt8515: Put fwnode in any case during ->probe() fwnode_get_next_available_child_node() bumps a reference counting of a returned variable. We have to balance it whenever we return to the caller. Fixes: e1c6edcbea13 ("leds: rt8515: Add Richtek RT8515 LED driver") Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek Reviewed-by: Linus Walleij --- drivers/leds/flash/leds-rt8515.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/leds/flash/leds-rt8515.c b/drivers/leds/flash/leds-rt8515.c index 590bfa180d10..44904fdee3cc 100644 --- a/drivers/leds/flash/leds-rt8515.c +++ b/drivers/leds/flash/leds-rt8515.c @@ -343,8 +343,9 @@ static int rt8515_probe(struct platform_device *pdev) ret = devm_led_classdev_flash_register_ext(dev, fled, &init_data); if (ret) { - dev_err(dev, "can't register LED %s\n", led->name); + fwnode_handle_put(child); mutex_destroy(&rt->lock); + dev_err(dev, "can't register LED %s\n", led->name); return ret; } @@ -362,6 +363,7 @@ static int rt8515_probe(struct platform_device *pdev) */ } + fwnode_handle_put(child); return 0; } From 64f67b5240db79eceb0bd57dae8e591fd3103ba0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 21 Feb 2021 12:52:08 +0100 Subject: [PATCH 18/32] leds: trigger: audio: Add an activate callback to ensure the initial brightness is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some 2-in-1s with a detachable (USB) keyboard(dock) have mute-LEDs in the speaker- and/or mic-mute keys on the keyboard. Examples of this are the Lenovo Thinkpad10 tablet (with its USB kbd-dock) and the HP x2 10 series. The detachable nature of these keyboards means that the keyboard and thus the mute LEDs may show up after the user (or userspace restoring old mixer settings) has muted the speaker and/or mic. Current LED-class devices with a default_trigger of "audio-mute" or "audio-micmute" initialize the brightness member of led_classdev with ledtrig_audio_get() before registering the LED. This makes the software state after attaching the keyboard match the actual audio mute state, e.g. cat /sys/class/leds/foo/brightness will show the right value. But before this commit nothing was actually calling the led_classdev's brightness_set[_blocking] callback so the value returned by ledtrig_audio_get() was never actually being sent to the hw, leading to the mute LEDs staying in their default power-on state, after attaching the keyboard, even if ledtrig_audio_get() returned a different state. This could be fixed by having the individual LED drivers call brightness_set[_blocking] themselves after registering the LED, but this really is something which should be done by a led-trigger activate callback. Add an activate callback for this, fixing the issue of the mute LEDs being out of sync after (re)attaching the keyboard. Cc: Takashi Iwai Fixes: faa2541f5b1a ("leds: trigger: Introduce audio mute LED trigger") Reviewed-by: Marek Behún Signed-off-by: Hans de Goede Signed-off-by: Pavel Machek --- drivers/leds/trigger/ledtrig-audio.c | 37 ++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-audio.c b/drivers/leds/trigger/ledtrig-audio.c index f76621e88482..c6b437e6369b 100644 --- a/drivers/leds/trigger/ledtrig-audio.c +++ b/drivers/leds/trigger/ledtrig-audio.c @@ -6,10 +6,33 @@ #include #include #include +#include "../leds.h" -static struct led_trigger *ledtrig_audio[NUM_AUDIO_LEDS]; static enum led_brightness audio_state[NUM_AUDIO_LEDS]; +static int ledtrig_audio_mute_activate(struct led_classdev *led_cdev) +{ + led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MUTE]); + return 0; +} + +static int ledtrig_audio_micmute_activate(struct led_classdev *led_cdev) +{ + led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MICMUTE]); + return 0; +} + +static struct led_trigger ledtrig_audio[NUM_AUDIO_LEDS] = { + [LED_AUDIO_MUTE] = { + .name = "audio-mute", + .activate = ledtrig_audio_mute_activate, + }, + [LED_AUDIO_MICMUTE] = { + .name = "audio-micmute", + .activate = ledtrig_audio_micmute_activate, + }, +}; + enum led_brightness ledtrig_audio_get(enum led_audio type) { return audio_state[type]; @@ -19,24 +42,22 @@ EXPORT_SYMBOL_GPL(ledtrig_audio_get); void ledtrig_audio_set(enum led_audio type, enum led_brightness state) { audio_state[type] = state; - led_trigger_event(ledtrig_audio[type], state); + led_trigger_event(&ledtrig_audio[type], state); } EXPORT_SYMBOL_GPL(ledtrig_audio_set); static int __init ledtrig_audio_init(void) { - led_trigger_register_simple("audio-mute", - &ledtrig_audio[LED_AUDIO_MUTE]); - led_trigger_register_simple("audio-micmute", - &ledtrig_audio[LED_AUDIO_MICMUTE]); + led_trigger_register(&ledtrig_audio[LED_AUDIO_MUTE]); + led_trigger_register(&ledtrig_audio[LED_AUDIO_MICMUTE]); return 0; } module_init(ledtrig_audio_init); static void __exit ledtrig_audio_exit(void) { - led_trigger_unregister_simple(ledtrig_audio[LED_AUDIO_MUTE]); - led_trigger_unregister_simple(ledtrig_audio[LED_AUDIO_MICMUTE]); + led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MUTE]); + led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MICMUTE]); } module_exit(ledtrig_audio_exit); From 9cbc861095375793a69858f91f3ac4e817f320f0 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Aug 2021 14:26:19 +0300 Subject: [PATCH 19/32] leds: lgm-sso: Propagate error codes from callee to caller The one of the latest change to the driver reveals the problem that the error codes from callee aren't propagated to the caller of __sso_led_dt_parse(). Fix this accordingly. Fixes: 9999908ca1ab ("leds: lgm-sso: Put fwnode in any case during ->probe()") Fixes: c3987cd2bca3 ("leds: lgm: Add LED controller driver for LGM SoC") Reported-by: kernel test robot Signed-off-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/blink/leds-lgm-sso.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/leds/blink/leds-lgm-sso.c b/drivers/leds/blink/leds-lgm-sso.c index e47c47e421d6..fd8b7573285a 100644 --- a/drivers/leds/blink/leds-lgm-sso.c +++ b/drivers/leds/blink/leds-lgm-sso.c @@ -640,7 +640,7 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) fwnode_child, GPIOD_ASIS, NULL); if (IS_ERR(led->gpiod)) { - dev_err_probe(dev, PTR_ERR(led->gpiod), "led: get gpio fail!\n"); + ret = dev_err_probe(dev, PTR_ERR(led->gpiod), "led: get gpio fail!\n"); goto __dt_err; } @@ -660,8 +660,11 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) desc->panic_indicator = 1; ret = fwnode_property_read_u32(fwnode_child, "reg", &prop); - if (ret != 0 || prop >= SSO_LED_MAX_NUM) { + if (ret) + goto __dt_err; + if (prop >= SSO_LED_MAX_NUM) { dev_err(dev, "invalid LED pin:%u\n", prop); + ret = -EINVAL; goto __dt_err; } desc->pin = prop; @@ -697,7 +700,8 @@ __sso_led_dt_parse(struct sso_led_priv *priv, struct fwnode_handle *fw_ssoled) desc->brightness = LED_FULL; } - if (sso_create_led(priv, led, fwnode_child)) + ret = sso_create_led(priv, led, fwnode_child); + if (ret) goto __dt_err; } @@ -709,7 +713,7 @@ __dt_err: list_for_each_entry(led, &priv->led_list, list) sso_led_shutdown(led); - return -EINVAL; + return ret; } static int sso_led_dt_parse(struct sso_led_priv *priv) From 654933ae7d32f278eecd0bb0f175785574ac4775 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 16 Aug 2021 08:47:08 +0200 Subject: [PATCH 20/32] leds: flash: Remove redundant initialization of variable ret Adjust initialization not to trigger Coverity warnings. Reported-by: Colin Ian King Signed-off-by: Pavel Machek --- drivers/leds/led-class-flash.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c index 6eeb9effcf65..185e17055317 100644 --- a/drivers/leds/led-class-flash.c +++ b/drivers/leds/led-class-flash.c @@ -92,14 +92,12 @@ static ssize_t flash_strobe_store(struct device *dev, struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev); unsigned long state; - ssize_t ret = -EINVAL; + ssize_t ret = -EBUSY; mutex_lock(&led_cdev->led_access); - if (led_sysfs_is_disabled(led_cdev)) { - ret = -EBUSY; + if (led_sysfs_is_disabled(led_cdev)) goto unlock; - } ret = kstrtoul(buf, 10, &state); if (ret) From 791bc41163c51f870972d6c6b82d971ce951096c Mon Sep 17 00:00:00 2001 From: Denis Osterland-Heim Date: Tue, 8 Jun 2021 08:35:53 +0200 Subject: [PATCH 21/32] leds: move default_state read from fwnode to core This patch introduces a new function to read initial default_state from fwnode. Suggested-by: Pavel Machek Signed-off-by: Denis Osterland-Heim Signed-off-by: Pavel Machek --- drivers/leds/led-core.c | 15 +++++++++++++++ drivers/leds/leds-gpio.c | 12 ++---------- drivers/leds/leds.h | 1 + include/linux/leds.h | 12 +++++++++--- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index 8eb8054ef9c6..4a97cb745788 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -477,3 +477,18 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data, return 0; } EXPORT_SYMBOL_GPL(led_compose_name); + +enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode) +{ + const char *state = NULL; + + if (!fwnode_property_read_string(fwnode, "default-state", &state)) { + if (!strcmp(state, "keep")) + return LEDS_DEFSTATE_KEEP; + if (!strcmp(state, "on")) + return LEDS_DEFSTATE_ON; + } + + return LEDS_DEFSTATE_OFF; +} +EXPORT_SYMBOL_GPL(led_init_default_state_get); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index b5d5e22d2d1e..092eb59a7d32 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -16,6 +16,7 @@ #include #include #include +#include "leds.h" struct gpio_led_data { struct led_classdev cdev; @@ -144,7 +145,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) device_for_each_child_node(dev, child) { struct gpio_led_data *led_dat = &priv->leds[priv->num_leds]; struct gpio_led led = {}; - const char *state = NULL; /* * Acquire gpiod from DT with uninitialized label, which @@ -161,15 +161,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) led_dat->gpiod = led.gpiod; - if (!fwnode_property_read_string(child, "default-state", - &state)) { - if (!strcmp(state, "keep")) - led.default_state = LEDS_GPIO_DEFSTATE_KEEP; - else if (!strcmp(state, "on")) - led.default_state = LEDS_GPIO_DEFSTATE_ON; - else - led.default_state = LEDS_GPIO_DEFSTATE_OFF; - } + led.default_state = led_init_default_state_get(child); if (fwnode_property_present(child, "retain-state-suspended")) led.retain_state_suspended = 1; diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 345062ccabda..aa64757a4d89 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -27,6 +27,7 @@ ssize_t led_trigger_read(struct file *filp, struct kobject *kobj, ssize_t led_trigger_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count); +enum led_default_state led_init_default_state_get(struct fwnode_handle *fwnode); extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; diff --git a/include/linux/leds.h b/include/linux/leds.h index 329fd914cf24..a0b730be40ad 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -33,6 +33,12 @@ enum led_brightness { LED_FULL = 255, }; +enum led_default_state { + LEDS_DEFSTATE_OFF = 0, + LEDS_DEFSTATE_ON = 1, + LEDS_DEFSTATE_KEEP = 2, +}; + struct led_init_data { /* device fwnode handle */ struct fwnode_handle *fwnode; @@ -520,9 +526,9 @@ struct gpio_led { /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ struct gpio_desc *gpiod; }; -#define LEDS_GPIO_DEFSTATE_OFF 0 -#define LEDS_GPIO_DEFSTATE_ON 1 -#define LEDS_GPIO_DEFSTATE_KEEP 2 +#define LEDS_GPIO_DEFSTATE_OFF LEDS_DEFSTATE_OFF +#define LEDS_GPIO_DEFSTATE_ON LEDS_DEFSTATE_ON +#define LEDS_GPIO_DEFSTATE_KEEP LEDS_DEFSTATE_KEEP struct gpio_led_platform_data { int num_leds; From 3d3d65bd27645830a6f23af29d0f9ebe5cc8bcb2 Mon Sep 17 00:00:00 2001 From: Denis Osterland-Heim Date: Tue, 8 Jun 2021 08:35:54 +0200 Subject: [PATCH 22/32] leds: pwm: add support for default-state device property This patch adds support for "default-state" devicetree property, which allows to defer pwm init to first use of led. This allows to configure the PWM early in bootloader to let the LED blink until an application in Linux userspace sets something different. Signed-off-by: Denis Osterland-Heim Signed-off-by: Pavel Machek --- drivers/leds/leds-pwm.c | 49 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index d71e9fa5c8de..6832180c1c54 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -17,10 +17,12 @@ #include #include #include +#include "leds.h" struct led_pwm { const char *name; u8 active_low; + u8 default_state; unsigned int max_brightness; }; @@ -77,7 +79,38 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, led_data->cdev.brightness_set_blocking = led_pwm_set; - pwm_init_state(led_data->pwm, &led_data->pwmstate); + /* init PWM state */ + switch (led->default_state) { + case LEDS_DEFSTATE_KEEP: + pwm_get_state(led_data->pwm, &led_data->pwmstate); + if (led_data->pwmstate.period) + break; + led->default_state = LEDS_DEFSTATE_OFF; + dev_warn(dev, + "failed to read period for %s, default to off", + led->name); + fallthrough; + default: + pwm_init_state(led_data->pwm, &led_data->pwmstate); + break; + } + + /* set brightness */ + switch (led->default_state) { + case LEDS_DEFSTATE_ON: + led_data->cdev.brightness = led->max_brightness; + break; + case LEDS_DEFSTATE_KEEP: + { + uint64_t brightness; + + brightness = led->max_brightness; + brightness *= led_data->pwmstate.duty_cycle; + do_div(brightness, led_data->pwmstate.period); + led_data->cdev.brightness = brightness; + } + break; + } ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data); if (ret) { @@ -86,11 +119,13 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, return ret; } - ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness); - if (ret) { - dev_err(dev, "failed to set led PWM value for %s: %d", - led->name, ret); - return ret; + if (led->default_state != LEDS_DEFSTATE_KEEP) { + ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness); + if (ret) { + dev_err(dev, "failed to set led PWM value for %s: %d", + led->name, ret); + return ret; + } } priv->num_leds++; @@ -120,6 +155,8 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv) fwnode_property_read_u32(fwnode, "max-brightness", &led.max_brightness); + led.default_state = led_init_default_state_get(fwnode); + ret = led_pwm_add(dev, priv, &led, fwnode); if (ret) goto err_child_out; From 8b624007e72f448df91e3bd4a9f23ad516599040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Fri, 30 Jul 2021 23:59:11 +0200 Subject: [PATCH 23/32] leds: lp50xx: Fix chip name in KConfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 9-channel one is called LP5009, not LP509. Signed-off-by: Jan Kundrát Reviewed-by: Andy Shevchenko Signed-off-by: Pavel Machek --- drivers/leds/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index da7773dc8670..ed800f5da7d8 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -369,7 +369,7 @@ config LEDS_LP3952 module will be called leds-lp3952. config LEDS_LP50XX - tristate "LED Support for TI LP5036/30/24/18/12/9 LED driver chip" + tristate "LED Support for TI LP5036/30/24/18/12/09 LED driver chip" depends on LEDS_CLASS && REGMAP_I2C depends on LEDS_CLASS_MULTICOLOR || !LEDS_CLASS_MULTICOLOR help From 5358680e675744962a8adc99263adf59adfa8960 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 4 Aug 2021 14:34:25 +0200 Subject: [PATCH 24/32] leds: trigger: remove reference to obsolete CONFIG_IDE_GD_ATA Commit b7fb14d3ac63 ("ide: remove the legacy ide driver") removes the definition of the config IDE_GD_ATA. So, remove the obsolete reference in ./drivers/leds/trigger/Kconfig. Signed-off-by: Lukas Bulwahn Signed-off-by: Pavel Machek --- drivers/leds/trigger/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index b77a01bd27f4..1f1d57288085 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -34,7 +34,7 @@ config LEDS_TRIGGER_ONESHOT config LEDS_TRIGGER_DISK bool "LED Disk Trigger" - depends on IDE_GD_ATA || ATA + depends on ATA help This allows LEDs to be controlled by disk activity. If unsure, say Y. From 09f1273064eea23ec41fb206f6eccc2bf79d1fa1 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 20 Aug 2021 10:26:24 +0200 Subject: [PATCH 25/32] Documentation: leds: standartizing LED names We have a list of valid functions, but LED names in sysfs are still far from being consistent. Create list of "well known" LED names so we nudge people towards using same LED names (except color) for same functionality. Signed-off-by: Pavel Machek --- Documentation/leds/well-known-leds.txt | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Documentation/leds/well-known-leds.txt diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt new file mode 100644 index 000000000000..4a8b9dc4bf52 --- /dev/null +++ b/Documentation/leds/well-known-leds.txt @@ -0,0 +1,58 @@ +-*- org -*- + +It is somehow important to provide consistent interface to the +userland. LED devices have one problem there, and that is naming of +directories in /sys/class/leds. It would be nice if userland would +just know right "name" for given LED function, but situation got more +complex. + +Anyway, if backwards compatibility is not an issue, new code should +use one of the "good" names from this list, and you should extend the +list where applicable. + +Legacy names are listed, too; in case you are writing application that +wants to use particular feature, you should probe for good name, first, +but then try the legacy ones, too. + +Notice there's a list of functions in include/dt-bindings/leds/common.h . + +* Keyboards + +Good: "input*:*:capslock" +Good: "input*:*:scrolllock" +Good: "input*:*:numlock" +Legacy: "shift-key-light" (Motorola Droid 4, capslock) + +Set of common keyboard LEDs, going back to PC AT or so. + +Legacy: "tpacpi::thinklight" (IBM/Lenovo Thinkpads) +Legacy: "lp5523:kb{1,2,3,4,5,6}" (Nokia N900) + +Frontlight/backlight of main keyboard. + +Legacy: "button-backlight" (Motorola Droid 4) + +Some phones have touch buttons below screen; it is different from main +keyboard. And this is their backlight. + +* Sound subsystem + +Good: "platform:*:mute" +Good: "platform:*:micmute" + +LEDs on notebook body, indicating that sound input / output is muted. + +* System notification + +Legacy: "status-led:{red,green,blue}" (Motorola Droid 4) +Legacy: "lp5523:{r,g,b}" (Nokia N900) + +Phones usually have multi-color status LED. + +* Power management + +Good: "platform:*:charging" (allwinner sun50i) + +* Screen + +Good: ":backlight" (Motorola Droid 4) From 5d823d6d69853ae07786ddf786f7693b57e76beb Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:25 -0500 Subject: [PATCH 26/32] dt-bindings: leds: Add retain-state-shutdown boolean Document the retain-state-shutdown property that indicates that a LED should not be turned off or changed during system shutdown. Signed-off-by: Eddie James Acked-by: Rob Herring Signed-off-by: Pavel Machek --- Documentation/devicetree/bindings/leds/common.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/leds/common.yaml b/Documentation/devicetree/bindings/leds/common.yaml index b1f363747a62..697102707703 100644 --- a/Documentation/devicetree/bindings/leds/common.yaml +++ b/Documentation/devicetree/bindings/leds/common.yaml @@ -128,6 +128,12 @@ properties: as a panic indicator. type: boolean + retain-state-shutdown: + description: + This property specifies that the LED should not be turned off or changed + when the system shuts down. + type: boolean + trigger-sources: description: | List of devices which should be used as a source triggering this LED From 419066324e19a47b98cdcf5defda42de555a8957 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:26 -0500 Subject: [PATCH 27/32] leds: leds-core: Implement the retain-state-shutdown property Read the retain-state-shutdown device tree property to set the existing LED_RETAIN_AT_SHUTDOWN flag. Then check the flag when unregistering, and if set, don't set the brightness to OFF. This is useful for systems that want to keep the HW state of the LED across reboots. Signed-off-by: Eddie James Signed-off-by: Pavel Machek --- drivers/leds/led-class.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index f704391d57a8..f4bb02f6e042 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -350,10 +350,15 @@ int led_classdev_register_ext(struct device *parent, if (ret < 0) return ret; - if (init_data->fwnode) + if (init_data->fwnode) { fwnode_property_read_string(init_data->fwnode, "linux,default-trigger", &led_cdev->default_trigger); + + if (fwnode_property_present(init_data->fwnode, + "retain-state-shutdown")) + led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN; + } } else { proposed_name = led_cdev->name; } @@ -444,7 +449,8 @@ void led_classdev_unregister(struct led_classdev *led_cdev) /* Stop blinking */ led_stop_software_blink(led_cdev); - led_set_brightness(led_cdev, LED_OFF); + if (!(led_cdev->flags & LED_RETAIN_AT_SHUTDOWN)) + led_set_brightness(led_cdev, LED_OFF); flush_work(&led_cdev->set_brightness_work); From 2420ae02ce0a926819ebe18f809a57bff3edeac2 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:27 -0500 Subject: [PATCH 28/32] leds: pca955x: Clean up code formatting Format the code. Add some variables to help shorten lines. Signed-off-by: Eddie James Signed-off-by: Pavel Machek --- drivers/leds/leds-pca955x.c | 63 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 7087ca4592fc..f0d841cb59fc 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -166,11 +166,10 @@ static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state) static int pca955x_write_psc(struct i2c_client *client, int n, u8 val) { struct pca955x *pca955x = i2c_get_clientdata(client); + u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + (2 * n); int ret; - ret = i2c_smbus_write_byte_data(client, - pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n, - val); + ret = i2c_smbus_write_byte_data(client, cmd, val); if (ret < 0) dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", __func__, n, val, ret); @@ -187,11 +186,10 @@ static int pca955x_write_psc(struct i2c_client *client, int n, u8 val) static int pca955x_write_pwm(struct i2c_client *client, int n, u8 val) { struct pca955x *pca955x = i2c_get_clientdata(client); + u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n); int ret; - ret = i2c_smbus_write_byte_data(client, - pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n, - val); + ret = i2c_smbus_write_byte_data(client, cmd, val); if (ret < 0) dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", __func__, n, val, ret); @@ -205,11 +203,10 @@ static int pca955x_write_pwm(struct i2c_client *client, int n, u8 val) static int pca955x_write_ls(struct i2c_client *client, int n, u8 val) { struct pca955x *pca955x = i2c_get_clientdata(client); + u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n; int ret; - ret = i2c_smbus_write_byte_data(client, - pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n, - val); + ret = i2c_smbus_write_byte_data(client, cmd, val); if (ret < 0) dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", __func__, n, val, ret); @@ -223,10 +220,10 @@ static int pca955x_write_ls(struct i2c_client *client, int n, u8 val) static int pca955x_read_ls(struct i2c_client *client, int n, u8 *val) { struct pca955x *pca955x = i2c_get_clientdata(client); + u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n; int ret; - ret = i2c_smbus_read_byte_data(client, - pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n); + ret = i2c_smbus_read_byte_data(client, cmd); if (ret < 0) { dev_err(&client->dev, "%s: reg 0x%x, err %d\n", __func__, n, ret); @@ -371,6 +368,7 @@ static struct pca955x_platform_data * pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) { struct pca955x_platform_data *pdata; + struct pca955x_led *led; struct fwnode_handle *child; int count; @@ -401,13 +399,13 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) if ((res != 0) && is_of_node(child)) name = to_of_node(child)->name; - snprintf(pdata->leds[reg].name, sizeof(pdata->leds[reg].name), - "%s", name); + led = &pdata->leds[reg]; + snprintf(led->name, sizeof(led->name), "%s", name); - pdata->leds[reg].type = PCA955X_TYPE_LED; - fwnode_property_read_u32(child, "type", &pdata->leds[reg].type); + led->type = PCA955X_TYPE_LED; + fwnode_property_read_u32(child, "type", &led->type); fwnode_property_read_string(child, "linux,default-trigger", - &pdata->leds[reg].default_trigger); + &led->default_trigger); } pdata->num_leds = chip->bits; @@ -426,11 +424,12 @@ static const struct of_device_id of_pca955x_match[] = { MODULE_DEVICE_TABLE(of, of_pca955x_match); static int pca955x_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct pca955x *pca955x; struct pca955x_led *pca955x_led; struct pca955x_chipdef *chip; + struct led_classdev *led; struct i2c_adapter *adapter; int i, err; struct pca955x_platform_data *pdata; @@ -449,13 +448,13 @@ static int pca955x_probe(struct i2c_client *client, if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) != chip->slv_addr) { dev_err(&client->dev, "invalid slave address %02x\n", - client->addr); + client->addr); return -ENODEV; } dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at " - "slave address 0x%02x\n", - client->name, chip->bits, client->addr); + "slave address 0x%02x\n", client->name, chip->bits, + client->addr); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; @@ -471,8 +470,8 @@ static int pca955x_probe(struct i2c_client *client, if (!pca955x) return -ENOMEM; - pca955x->leds = devm_kcalloc(&client->dev, - chip->bits, sizeof(*pca955x_led), GFP_KERNEL); + pca955x->leds = devm_kcalloc(&client->dev, chip->bits, + sizeof(*pca955x_led), GFP_KERNEL); if (!pca955x->leds) return -ENOMEM; @@ -501,27 +500,25 @@ static int pca955x_probe(struct i2c_client *client, */ if (pdata->leds[i].name[0] == '\0') snprintf(pdata->leds[i].name, - sizeof(pdata->leds[i].name), "%d", i); + sizeof(pdata->leds[i].name), "%d", i); - snprintf(pca955x_led->name, - sizeof(pca955x_led->name), "pca955x:%s", - pdata->leds[i].name); + snprintf(pca955x_led->name, sizeof(pca955x_led->name), + "pca955x:%s", pdata->leds[i].name); + led = &pca955x_led->led_cdev; if (pdata->leds[i].default_trigger) - pca955x_led->led_cdev.default_trigger = + led->default_trigger = pdata->leds[i].default_trigger; - pca955x_led->led_cdev.name = pca955x_led->name; - pca955x_led->led_cdev.brightness_set_blocking = - pca955x_led_set; + led->name = pca955x_led->name; + led->brightness_set_blocking = pca955x_led_set; - err = devm_led_classdev_register(&client->dev, - &pca955x_led->led_cdev); + err = devm_led_classdev_register(&client->dev, led); if (err) return err; /* Turn off LED */ - err = pca955x_led_set(&pca955x_led->led_cdev, LED_OFF); + err = pca955x_led_set(led, LED_OFF); if (err) return err; } From 7086625fde6538b2c0623eb767ad23c7ac3d7f3a Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:28 -0500 Subject: [PATCH 29/32] leds: pca955x: Add brightness_get function Add a function to fetch the state of the hardware LED. Signed-off-by: Eddie James Signed-off-by: Pavel Machek --- drivers/leds/leds-pca955x.c | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index f0d841cb59fc..e47ba7c3b7c7 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -233,6 +233,57 @@ static int pca955x_read_ls(struct i2c_client *client, int n, u8 *val) return 0; } +static int pca955x_read_pwm(struct i2c_client *client, int n, u8 *val) +{ + struct pca955x *pca955x = i2c_get_clientdata(client); + u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n); + int ret; + + ret = i2c_smbus_read_byte_data(client, cmd); + if (ret < 0) { + dev_err(&client->dev, "%s: reg 0x%x, err %d\n", + __func__, n, ret); + return ret; + } + *val = (u8)ret; + return 0; +} + +static enum led_brightness pca955x_led_get(struct led_classdev *led_cdev) +{ + struct pca955x_led *pca955x_led = container_of(led_cdev, + struct pca955x_led, + led_cdev); + struct pca955x *pca955x = pca955x_led->pca955x; + u8 ls, pwm; + int ret; + + ret = pca955x_read_ls(pca955x->client, pca955x_led->led_num / 4, &ls); + if (ret) + return ret; + + ls = (ls >> ((pca955x_led->led_num % 4) << 1)) & 0x3; + switch (ls) { + case PCA955X_LS_LED_ON: + ret = LED_FULL; + break; + case PCA955X_LS_LED_OFF: + ret = LED_OFF; + break; + case PCA955X_LS_BLINK0: + ret = LED_HALF; + break; + case PCA955X_LS_BLINK1: + ret = pca955x_read_pwm(pca955x->client, 1, &pwm); + if (ret) + return ret; + ret = 255 - pwm; + break; + } + + return ret; +} + static int pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value) { @@ -512,6 +563,7 @@ static int pca955x_probe(struct i2c_client *client, led->name = pca955x_led->name; led->brightness_set_blocking = pca955x_led_set; + led->brightness_get = pca955x_led_get; err = devm_led_classdev_register(&client->dev, led); if (err) From e46cb6d0c760a5b15e38138845fad99628fafcb8 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:29 -0500 Subject: [PATCH 30/32] leds: pca955x: Implement the default-state property In order to retain the LED state after a system reboot, check the documented default-state device tree property during initialization. Modify the behavior of the probe according to the property. Signed-off-by: Eddie James Signed-off-by: Pavel Machek --- drivers/leds/leds-pca955x.c | 54 +++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index e47ba7c3b7c7..fa1d77d86ef6 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -129,6 +129,7 @@ struct pca955x_led { int led_num; /* 0 .. 15 potentially */ char name[32]; u32 type; + int default_state; const char *default_trigger; }; @@ -439,6 +440,7 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) device_for_each_child_node(&client->dev, child) { const char *name; + const char *state; u32 reg; int res; @@ -457,6 +459,18 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) fwnode_property_read_u32(child, "type", &led->type); fwnode_property_read_string(child, "linux,default-trigger", &led->default_trigger); + + if (!fwnode_property_read_string(child, "default-state", + &state)) { + if (!strcmp(state, "keep")) + led->default_state = LEDS_GPIO_DEFSTATE_KEEP; + else if (!strcmp(state, "on")) + led->default_state = LEDS_GPIO_DEFSTATE_ON; + else + led->default_state = LEDS_GPIO_DEFSTATE_OFF; + } else { + led->default_state = LEDS_GPIO_DEFSTATE_OFF; + } } pdata->num_leds = chip->bits; @@ -485,6 +499,7 @@ static int pca955x_probe(struct i2c_client *client, int i, err; struct pca955x_platform_data *pdata; int ngpios = 0; + bool keep_pwm = false; chip = &pca955x_chipdefs[id->driver_data]; adapter = client->adapter; @@ -565,14 +580,35 @@ static int pca955x_probe(struct i2c_client *client, led->brightness_set_blocking = pca955x_led_set; led->brightness_get = pca955x_led_get; + if (pdata->leds[i].default_state == + LEDS_GPIO_DEFSTATE_OFF) { + err = pca955x_led_set(led, LED_OFF); + if (err) + return err; + } else if (pdata->leds[i].default_state == + LEDS_GPIO_DEFSTATE_ON) { + err = pca955x_led_set(led, LED_FULL); + if (err) + return err; + } + err = devm_led_classdev_register(&client->dev, led); if (err) return err; - /* Turn off LED */ - err = pca955x_led_set(led, LED_OFF); - if (err) - return err; + /* + * For default-state == "keep", let the core update the + * brightness from the hardware, then check the + * brightness to see if it's using PWM1. If so, PWM1 + * should not be written below. + */ + if (pdata->leds[i].default_state == + LEDS_GPIO_DEFSTATE_KEEP) { + if (led->brightness != LED_FULL && + led->brightness != LED_OFF && + led->brightness != LED_HALF) + keep_pwm = true; + } } } @@ -581,10 +617,12 @@ static int pca955x_probe(struct i2c_client *client, if (err) return err; - /* PWM1 is used for variable brightness, default to OFF */ - err = pca955x_write_pwm(client, 1, 0); - if (err) - return err; + if (!keep_pwm) { + /* PWM1 is used for variable brightness, default to OFF */ + err = pca955x_write_pwm(client, 1, 0); + if (err) + return err; + } /* Set to fast frequency so we do not see flashing */ err = pca955x_write_psc(client, 0, 0); From 7c4815929276b2e223eb6f2e49afe5071d4294a5 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:30 -0500 Subject: [PATCH 31/32] leds: pca955x: Let the core process the fwnode Much of the fwnode processing in the PCA955x driver is now in the LEDs core driver, so pass the fwnode in the init data when registering the LED device. In order to preserve the existing naming scheme, check for an empty name and set it to the LED number. Signed-off-by: Eddie James Signed-off-by: Pavel Machek --- drivers/leds/leds-pca955x.c | 58 +++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index fa1d77d86ef6..a6aa4b9abde8 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -127,10 +127,9 @@ struct pca955x_led { struct pca955x *pca955x; struct led_classdev led_cdev; int led_num; /* 0 .. 15 potentially */ - char name[32]; u32 type; int default_state; - const char *default_trigger; + struct fwnode_handle *fwnode; }; struct pca955x_platform_data { @@ -439,7 +438,6 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) return ERR_PTR(-ENOMEM); device_for_each_child_node(&client->dev, child) { - const char *name; const char *state; u32 reg; int res; @@ -448,17 +446,10 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) if ((res != 0) || (reg >= chip->bits)) continue; - res = fwnode_property_read_string(child, "label", &name); - if ((res != 0) && is_of_node(child)) - name = to_of_node(child)->name; - led = &pdata->leds[reg]; - snprintf(led->name, sizeof(led->name), "%s", name); - led->type = PCA955X_TYPE_LED; + led->fwnode = child; fwnode_property_read_u32(child, "type", &led->type); - fwnode_property_read_string(child, "linux,default-trigger", - &led->default_trigger); if (!fwnode_property_read_string(child, "default-state", &state)) { @@ -495,11 +486,14 @@ static int pca955x_probe(struct i2c_client *client, struct pca955x_led *pca955x_led; struct pca955x_chipdef *chip; struct led_classdev *led; + struct led_init_data init_data; struct i2c_adapter *adapter; int i, err; struct pca955x_platform_data *pdata; int ngpios = 0; + bool set_default_label = false; bool keep_pwm = false; + char default_label[8]; chip = &pca955x_chipdefs[id->driver_data]; adapter = client->adapter; @@ -547,6 +541,9 @@ static int pca955x_probe(struct i2c_client *client, pca955x->client = client; pca955x->chipdef = chip; + init_data.devname_mandatory = false; + init_data.devicename = "pca955x"; + for (i = 0; i < chip->bits; i++) { pca955x_led = &pca955x->leds[i]; pca955x_led->led_num = i; @@ -560,23 +557,7 @@ static int pca955x_probe(struct i2c_client *client, ngpios++; break; case PCA955X_TYPE_LED: - /* - * Platform data can specify LED names and - * default triggers - */ - if (pdata->leds[i].name[0] == '\0') - snprintf(pdata->leds[i].name, - sizeof(pdata->leds[i].name), "%d", i); - - snprintf(pca955x_led->name, sizeof(pca955x_led->name), - "pca955x:%s", pdata->leds[i].name); - led = &pca955x_led->led_cdev; - if (pdata->leds[i].default_trigger) - led->default_trigger = - pdata->leds[i].default_trigger; - - led->name = pca955x_led->name; led->brightness_set_blocking = pca955x_led_set; led->brightness_get = pca955x_led_get; @@ -592,7 +573,28 @@ static int pca955x_probe(struct i2c_client *client, return err; } - err = devm_led_classdev_register(&client->dev, led); + init_data.fwnode = pdata->leds[i].fwnode; + + if (is_of_node(init_data.fwnode)) { + if (to_of_node(init_data.fwnode)->name[0] == + '\0') + set_default_label = true; + else + set_default_label = false; + } else { + set_default_label = true; + } + + if (set_default_label) { + snprintf(default_label, sizeof(default_label), + "%d", i); + init_data.default_label = default_label; + } else { + init_data.default_label = NULL; + } + + err = devm_led_classdev_register_ext(&client->dev, led, + &init_data); if (err) return err; From 239f32b4f161c1584cd4b386d6ab8766432a6ede Mon Sep 17 00:00:00 2001 From: Eddie James Date: Fri, 16 Jul 2021 17:03:31 -0500 Subject: [PATCH 32/32] leds: pca955x: Switch to i2c probe_new The deprecated i2c probe functionality doesn't work with OF compatible strings, as it only checks for the i2c device id. Switch to the new way of probing and grab the match data to select the chip type. Signed-off-by: Eddie James Signed-off-by: Pavel Machek --- drivers/leds/leds-pca955x.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index a6aa4b9abde8..a6b5699aeae4 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -479,8 +479,7 @@ static const struct of_device_id of_pca955x_match[] = { }; MODULE_DEVICE_TABLE(of, of_pca955x_match); -static int pca955x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int pca955x_probe(struct i2c_client *client) { struct pca955x *pca955x; struct pca955x_led *pca955x_led; @@ -494,8 +493,24 @@ static int pca955x_probe(struct i2c_client *client, bool set_default_label = false; bool keep_pwm = false; char default_label[8]; + enum pca955x_type chip_type; + const void *md = device_get_match_data(&client->dev); - chip = &pca955x_chipdefs[id->driver_data]; + if (md) { + chip_type = (enum pca955x_type)md; + } else { + const struct i2c_device_id *id = i2c_match_id(pca955x_id, + client); + + if (id) { + chip_type = (enum pca955x_type)id->driver_data; + } else { + dev_err(&client->dev, "unknown chip\n"); + return -ENODEV; + } + } + + chip = &pca955x_chipdefs[chip_type]; adapter = client->adapter; pdata = dev_get_platdata(&client->dev); if (!pdata) { @@ -670,7 +685,7 @@ static struct i2c_driver pca955x_driver = { .name = "leds-pca955x", .of_match_table = of_pca955x_match, }, - .probe = pca955x_probe, + .probe_new = pca955x_probe, .id_table = pca955x_id, };