mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-20 03:24:03 +08:00
LED updates for 5.15-rc1. Usual driver changes, piece of documentation
that should hopefully get LED names standartized, and many fixes. -----BEGIN PGP SIGNATURE----- iF0EABECAB0WIQRPfPO7r0eAhk010v0w5/Bqldv68gUCYS5vtwAKCRAw5/Bqldv6 8oKyAJ4v9knZf1u86MIQxFzucZhPvjeoAACgpIkkT1U/MWbUaHE3X1YyzbKvy8A= =Zuad -----END PGP SIGNATURE----- Merge tag 'leds-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds Pull LED updates from Pavel Machek: "Usual driver changes, some documentation that should hopefully get LED names standartized, and many fixes" * tag 'leds-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds: (32 commits) leds: pca955x: Switch to i2c probe_new leds: pca955x: Let the core process the fwnode leds: pca955x: Implement the default-state property leds: pca955x: Add brightness_get function leds: pca955x: Clean up code formatting leds: leds-core: Implement the retain-state-shutdown property dt-bindings: leds: Add retain-state-shutdown boolean Documentation: leds: standartizing LED names leds: trigger: remove reference to obsolete CONFIG_IDE_GD_ATA leds: lp50xx: Fix chip name in KConfig leds: pwm: add support for default-state device property leds: move default_state read from fwnode to core leds: flash: Remove redundant initialization of variable ret leds: lgm-sso: Propagate error codes from callee to caller leds: trigger: audio: Add an activate callback to ensure the initial brightness is set leds: rt8515: Put fwnode in any case during ->probe() leds: lt3593: Put fwnode in any case during ->probe() leds: lm3697: Make error handling more robust leds: lm3697: Update header block to reflect reality leds: lm3692x: Correct headers (of*.h -> mod_devicetable.h) ...
This commit is contained in:
commit
a998a62be9
@ -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
|
||||
|
58
Documentation/leds/well-known-leds.txt
Normal file
58
Documentation/leds/well-known-leds.txt
Normal file
@ -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)
|
@ -2849,7 +2849,7 @@ AS3645A LED FLASH CONTROLLER DRIVER
|
||||
M: Sakari Ailus <sakari.ailus@iki.fi>
|
||||
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 <tian.shu.qiu@intel.com>
|
||||
|
@ -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
|
||||
@ -104,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
|
||||
@ -239,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
|
||||
@ -397,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
|
||||
@ -699,17 +671,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
|
||||
@ -741,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
|
||||
@ -913,14 +864,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
|
||||
|
@ -9,13 +9,11 @@ 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
|
||||
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
|
||||
@ -37,12 +35,10 @@ 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
|
||||
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
|
||||
@ -60,7 +56,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
|
||||
@ -82,7 +77,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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -624,15 +621,16 @@ __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;
|
||||
|
||||
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;
|
||||
@ -642,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(dev, "led: get gpio fail!\n");
|
||||
ret = dev_err_probe(dev, PTR_ERR(led->gpiod), "led: get gpio fail!\n");
|
||||
goto __dt_err;
|
||||
}
|
||||
|
||||
@ -662,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;
|
||||
@ -699,21 +700,20 @@ __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;
|
||||
}
|
||||
fwnode_handle_put(fw_ssoled);
|
||||
|
||||
return 0;
|
||||
__dt_err:
|
||||
fwnode_handle_put(fw_ssoled);
|
||||
/* unregister leds */
|
||||
list_for_each(p, &priv->led_list) {
|
||||
led = list_entry(p, struct sso_led, list);
|
||||
sso_led_shutdown(led);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
__dt_err:
|
||||
fwnode_handle_put(fwnode_child);
|
||||
/* unregister leds */
|
||||
list_for_each_entry(led, &priv->led_list, list)
|
||||
sso_led_shutdown(led);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sso_led_dt_parse(struct sso_led_priv *priv)
|
||||
@ -731,6 +731,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;
|
||||
}
|
||||
@ -841,14 +842,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);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,52 @@
|
||||
|
||||
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_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_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
|
||||
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
|
||||
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
|
||||
@ -24,4 +70,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
|
||||
|
@ -1,4 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
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
|
||||
obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o
|
||||
obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
/*
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
#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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -7,10 +7,9 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -2,11 +2,16 @@
|
||||
// TI LM3697 LED chip family driver
|
||||
// Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/leds-ti-lmu-common.h>
|
||||
|
||||
#define LM3697_REV 0x0
|
||||
@ -221,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;
|
||||
}
|
||||
|
||||
@ -259,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;
|
||||
}
|
||||
|
||||
@ -284,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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -127,9 +127,9 @@ struct pca955x_led {
|
||||
struct pca955x *pca955x;
|
||||
struct led_classdev led_cdev;
|
||||
int led_num; /* 0 .. 15 potentially */
|
||||
char name[32];
|
||||
u32 type;
|
||||
const char *default_trigger;
|
||||
int default_state;
|
||||
struct fwnode_handle *fwnode;
|
||||
};
|
||||
|
||||
struct pca955x_platform_data {
|
||||
@ -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);
|
||||
@ -236,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)
|
||||
{
|
||||
@ -371,6 +419,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;
|
||||
|
||||
@ -389,7 +438,7 @@ 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;
|
||||
|
||||
@ -397,17 +446,22 @@ 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];
|
||||
led->type = PCA955X_TYPE_LED;
|
||||
led->fwnode = child;
|
||||
fwnode_property_read_u32(child, "type", &led->type);
|
||||
|
||||
snprintf(pdata->leds[reg].name, sizeof(pdata->leds[reg].name),
|
||||
"%s", name);
|
||||
|
||||
pdata->leds[reg].type = PCA955X_TYPE_LED;
|
||||
fwnode_property_read_u32(child, "type", &pdata->leds[reg].type);
|
||||
fwnode_property_read_string(child, "linux,default-trigger",
|
||||
&pdata->leds[reg].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;
|
||||
@ -425,18 +479,38 @@ 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;
|
||||
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];
|
||||
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) {
|
||||
@ -449,13 +523,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 +545,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;
|
||||
|
||||
@ -482,6 +556,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;
|
||||
@ -495,35 +572,60 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
ngpios++;
|
||||
break;
|
||||
case PCA955X_TYPE_LED:
|
||||
led = &pca955x_led->led_cdev;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* Platform data can specify LED names and
|
||||
* default triggers
|
||||
* 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].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);
|
||||
|
||||
if (pdata->leds[i].default_trigger)
|
||||
pca955x_led->led_cdev.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;
|
||||
|
||||
err = devm_led_classdev_register(&client->dev,
|
||||
&pca955x_led->led_cdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Turn off LED */
|
||||
err = pca955x_led_set(&pca955x_led->led_cdev, LED_OFF);
|
||||
if (err)
|
||||
return err;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,10 +634,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);
|
||||
@ -581,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,
|
||||
};
|
||||
|
||||
|
@ -17,10 +17,12 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/slab.h>
|
||||
#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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -6,10 +6,33 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user