Merge tag 'leds-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds
Pull LED updates from Pavel Machek: "This contains usual small updates to drivers, and removal of PAGE_SIZE limits on /sys/class/leds/<led>/trigger. We should not be really having that many triggers; but with cpu activity triggers we do, and we'll eventually need to fix it, but... remove the limit for now" * tag 'leds-5.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds: (26 commits) leds: trigger: netdev: fix handling on interface rename leds: an30259a: add a check for devm_regmap_init_i2c leds: mlxreg: Fix possible buffer overflow leds: pca953x: Use of_device_get_match_data() leds: core: Fix leds.h structure documentation leds: core: Fix devm_classdev_match to reference correct structure leds: core: Remove extern from header leds: lm3601x: Convert class registration to device managed leds: flash: Add devm_* functions to the flash class leds: flash: Remove extern from the header file leds: flash: Convert non extended registration to inline leds: Kconfig: Be consistent with the usage of "LED" leds: remove PAGE_SIZE limit of /sys/class/leds/<led>/trigger leds: tlc591xx: update the maximum brightness leds: lm3692x: Use flags from LM3692X_BRT_CTRL leds: lm3692x: Use flags from LM3692X_BOOST_CTRL leds: lm3692x: Handle failure to probe the regulator leds: lm3692x: Don't overwrite return value in error path leds: lm3692x: Print error value on dev_err leds: tlc591xx: use devm_led_classdev_register_ext() ...
This commit is contained in:
commit
304220b56e
|
@ -0,0 +1,139 @@
|
||||||
|
What: /sys/class/leds/<led>/hw_pattern
|
||||||
|
Date: September 2019
|
||||||
|
KernelVersion: 5.5
|
||||||
|
Description:
|
||||||
|
Specify a hardware pattern for the EL15203000 LED.
|
||||||
|
The LEDs board supports only predefined patterns by firmware
|
||||||
|
for specific LEDs.
|
||||||
|
|
||||||
|
Breathing mode for Screen frame light tube:
|
||||||
|
"0 4000 1 4000"
|
||||||
|
|
||||||
|
^
|
||||||
|
|
|
||||||
|
Max-| ---
|
||||||
|
| / \
|
||||||
|
| / \
|
||||||
|
| / \ /
|
||||||
|
| / \ /
|
||||||
|
Min-|- ---
|
||||||
|
|
|
||||||
|
0------4------8--> time (sec)
|
||||||
|
|
||||||
|
Cascade mode for Pipe LED:
|
||||||
|
"1 800 2 800 4 800 8 800 16 800"
|
||||||
|
|
||||||
|
^
|
||||||
|
|
|
||||||
|
0 On -|----+ +----+ +---
|
||||||
|
| | | | |
|
||||||
|
Off-| +-------------------+ +-------------------+
|
||||||
|
|
|
||||||
|
1 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off |----+ +-------------------+ +------------------
|
||||||
|
|
|
||||||
|
2 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off-|---------+ +-------------------+ +-------------
|
||||||
|
|
|
||||||
|
3 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off-|--------------+ +-------------------+ +--------
|
||||||
|
|
|
||||||
|
4 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off-|-------------------+ +-------------------+ +---
|
||||||
|
|
|
||||||
|
0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
|
||||||
|
|
||||||
|
Inverted cascade mode for Pipe LED:
|
||||||
|
"30 800 29 800 27 800 23 800 15 800"
|
||||||
|
|
||||||
|
^
|
||||||
|
|
|
||||||
|
0 On -| +-------------------+ +-------------------+
|
||||||
|
| | | | |
|
||||||
|
Off-|----+ +----+ +---
|
||||||
|
|
|
||||||
|
1 On -|----+ +-------------------+ +------------------
|
||||||
|
| | | | |
|
||||||
|
Off | +----+ +----+
|
||||||
|
|
|
||||||
|
2 On -|---------+ +-------------------+ +-------------
|
||||||
|
| | | | |
|
||||||
|
Off-| +----+ +----+
|
||||||
|
|
|
||||||
|
3 On -|--------------+ +-------------------+ +--------
|
||||||
|
| | | | |
|
||||||
|
Off-| +----+ +----+
|
||||||
|
|
|
||||||
|
4 On -|-------------------+ +-------------------+ +---
|
||||||
|
| | | | |
|
||||||
|
Off-| +----+ +----+
|
||||||
|
|
|
||||||
|
0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
|
||||||
|
|
||||||
|
Bounce mode for Pipe LED:
|
||||||
|
"1 800 2 800 4 800 8 800 16 800 16 800 8 800 4 800 2 800 1 800"
|
||||||
|
|
||||||
|
^
|
||||||
|
|
|
||||||
|
0 On -|----+ +--------
|
||||||
|
| | |
|
||||||
|
Off-| +---------------------------------------+
|
||||||
|
|
|
||||||
|
1 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off |----+ +-----------------------------+ +--------
|
||||||
|
|
|
||||||
|
2 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off-|---------+ +-------------------+ +-------------
|
||||||
|
|
|
||||||
|
3 On -| +----+ +----+
|
||||||
|
| | | | |
|
||||||
|
Off-|--------------+ +---------+ +------------------
|
||||||
|
|
|
||||||
|
4 On -| +---------+
|
||||||
|
| | |
|
||||||
|
Off-|-------------------+ +-----------------------
|
||||||
|
|
|
||||||
|
0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
|
||||||
|
|
||||||
|
Inverted bounce mode for Pipe LED:
|
||||||
|
"30 800 29 800 27 800 23 800 15 800 15 800 23 800 27 800 29 800 30 800"
|
||||||
|
|
||||||
|
^
|
||||||
|
|
|
||||||
|
0 On -| +---------------------------------------+
|
||||||
|
| | |
|
||||||
|
Off-|----+ +--------
|
||||||
|
|
|
||||||
|
1 On -|----+ +-----------------------------+ +--------
|
||||||
|
| | | | |
|
||||||
|
Off | +----+ +----+
|
||||||
|
|
|
||||||
|
2 On -|---------+ +-------------------+ +-------------
|
||||||
|
| | | | |
|
||||||
|
Off-| +----+ +----+
|
||||||
|
|
|
||||||
|
3 On -|--------------+ +---------+ +------------------
|
||||||
|
| | | | |
|
||||||
|
Off-| +----+ +----+
|
||||||
|
|
|
||||||
|
4 On -|-------------------+ +-----------------------
|
||||||
|
| | |
|
||||||
|
Off-| +---------+
|
||||||
|
|
|
||||||
|
0---0.8--1.6--2.4--3.2---4---4.8--5.6--6.4--7.2---8--> time (sec)
|
||||||
|
|
||||||
|
What: /sys/class/leds/<led>/repeat
|
||||||
|
Date: September 2019
|
||||||
|
KernelVersion: 5.5
|
||||||
|
Description:
|
||||||
|
EL15203000 supports only indefinitely patterns,
|
||||||
|
so this file should always store -1.
|
||||||
|
|
||||||
|
For more info, please see:
|
||||||
|
Documentation/ABI/testing/sysfs-class-led-trigger-pattern
|
|
@ -0,0 +1,69 @@
|
||||||
|
Crane Merchandising System - EL15203000 LED driver
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
This LED Board (aka RED LEDs board) is widely used in
|
||||||
|
coffee vending machines produced by Crane Merchandising Systems.
|
||||||
|
The board manages 3 LEDs and supports predefined blinking patterns
|
||||||
|
for specific leds.
|
||||||
|
|
||||||
|
Vending area LED encoded with symbol 'V' (hex code 0x56).
|
||||||
|
Doesn't have any hardware blinking pattern.
|
||||||
|
|
||||||
|
Screen light tube LED which surrounds vending machine screen and
|
||||||
|
encoded with symbol 'S' (hex code 0x53). Supports blinking breathing pattern.
|
||||||
|
|
||||||
|
Water Pipe LED encoded with symbol 'P' (hex code 0x50) and
|
||||||
|
actually consists of 5 LEDs that exposed by protocol like one LED.
|
||||||
|
Supports next patterns:
|
||||||
|
- cascade pattern
|
||||||
|
- inversed cascade pattern
|
||||||
|
- bounce pattern
|
||||||
|
- inversed bounce pattern
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : "crane,el15203000"
|
||||||
|
- #address-cells : must be 1
|
||||||
|
- #size-cells : must be 0
|
||||||
|
|
||||||
|
Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||||
|
apply. In particular, "reg" and "spi-max-frequency" properties must be given.
|
||||||
|
|
||||||
|
Optional LED sub-node properties:
|
||||||
|
- function:
|
||||||
|
see Documentation/devicetree/bindings/leds/common.txt
|
||||||
|
- color:
|
||||||
|
see Documentation/devicetree/bindings/leds/common.txt
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
#include <dt-bindings/leds/common.h>
|
||||||
|
|
||||||
|
led-controller@0 {
|
||||||
|
compatible = "crane,el15203000";
|
||||||
|
reg = <0>;
|
||||||
|
spi-max-frequency = <50000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
/* water pipe */
|
||||||
|
led@50 {
|
||||||
|
reg = <0x50>;
|
||||||
|
function = "pipe";
|
||||||
|
color = <LED_COLOR_ID_RED>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* screen frame */
|
||||||
|
led@53 {
|
||||||
|
reg = <0x53>;
|
||||||
|
function = "screen";
|
||||||
|
color = <LED_COLOR_ID_RED>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* vending area */
|
||||||
|
led@56 {
|
||||||
|
reg = <0x56>;
|
||||||
|
function = "vend";
|
||||||
|
color = <LED_COLOR_ID_RED>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -17,7 +17,7 @@ if NEW_LEDS
|
||||||
config LEDS_CLASS
|
config LEDS_CLASS
|
||||||
tristate "LED Class Support"
|
tristate "LED Class Support"
|
||||||
help
|
help
|
||||||
This option enables the led sysfs class in /sys/class/leds. You'll
|
This option enables the LED sysfs class in /sys/class/leds. You'll
|
||||||
need this to do anything useful with LEDs. If unsure, say N.
|
need this to do anything useful with LEDs. If unsure, say N.
|
||||||
|
|
||||||
config LEDS_CLASS_FLASH
|
config LEDS_CLASS_FLASH
|
||||||
|
@ -35,7 +35,7 @@ config LEDS_BRIGHTNESS_HW_CHANGED
|
||||||
depends on LEDS_CLASS
|
depends on LEDS_CLASS
|
||||||
help
|
help
|
||||||
This option enables support for the brightness_hw_changed attribute
|
This option enables support for the brightness_hw_changed attribute
|
||||||
for led sysfs class devices under /sys/class/leds.
|
for LED sysfs class devices under /sys/class/leds.
|
||||||
|
|
||||||
See Documentation/ABI/testing/sysfs-class-led for details.
|
See Documentation/ABI/testing/sysfs-class-led for details.
|
||||||
|
|
||||||
|
@ -132,6 +132,19 @@ config LEDS_CR0014114
|
||||||
To compile this driver as a module, choose M here: the module
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called leds-cr0014114.
|
will be called leds-cr0014114.
|
||||||
|
|
||||||
|
config LEDS_EL15203000
|
||||||
|
tristate "LED Support for Crane EL15203000"
|
||||||
|
depends on LEDS_CLASS
|
||||||
|
depends on SPI
|
||||||
|
depends on OF
|
||||||
|
help
|
||||||
|
This option enables support for EL15203000 LED Board
|
||||||
|
(aka RED LED board) which is widely used in coffee vending
|
||||||
|
machines produced by Crane Merchandising Systems.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module
|
||||||
|
will be called leds-el15203000.
|
||||||
|
|
||||||
config LEDS_LM3530
|
config LEDS_LM3530
|
||||||
tristate "LCD Backlight driver for LM3530"
|
tristate "LCD Backlight driver for LM3530"
|
||||||
depends on LEDS_CLASS
|
depends on LEDS_CLASS
|
||||||
|
|
|
@ -89,6 +89,7 @@ obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o
|
||||||
# LED SPI Drivers
|
# LED SPI Drivers
|
||||||
obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
|
obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
|
||||||
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
|
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
|
||||||
|
obj-$(CONFIG_LEDS_EL15203000) += leds-el15203000.o
|
||||||
|
|
||||||
# LED Userspace Drivers
|
# LED Userspace Drivers
|
||||||
obj-$(CONFIG_LEDS_USER) += uleds.o
|
obj-$(CONFIG_LEDS_USER) += uleds.o
|
||||||
|
|
|
@ -327,6 +327,56 @@ void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(led_classdev_flash_unregister);
|
EXPORT_SYMBOL_GPL(led_classdev_flash_unregister);
|
||||||
|
|
||||||
|
static void devm_led_classdev_flash_release(struct device *dev, void *res)
|
||||||
|
{
|
||||||
|
led_classdev_flash_unregister(*(struct led_classdev_flash **)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
int devm_led_classdev_flash_register_ext(struct device *parent,
|
||||||
|
struct led_classdev_flash *fled_cdev,
|
||||||
|
struct led_init_data *init_data)
|
||||||
|
{
|
||||||
|
struct led_classdev_flash **dr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dr = devres_alloc(devm_led_classdev_flash_release, sizeof(*dr),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!dr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = led_classdev_flash_register_ext(parent, fled_cdev, init_data);
|
||||||
|
if (ret) {
|
||||||
|
devres_free(dr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dr = fled_cdev;
|
||||||
|
devres_add(parent, dr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_led_classdev_flash_register_ext);
|
||||||
|
|
||||||
|
static int devm_led_classdev_flash_match(struct device *dev,
|
||||||
|
void *res, void *data)
|
||||||
|
{
|
||||||
|
struct led_classdev_flash **p = res;
|
||||||
|
|
||||||
|
if (WARN_ON(!p || !*p))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return *p == data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void devm_led_classdev_flash_unregister(struct device *dev,
|
||||||
|
struct led_classdev_flash *fled_cdev)
|
||||||
|
{
|
||||||
|
WARN_ON(devres_release(dev,
|
||||||
|
devm_led_classdev_flash_release,
|
||||||
|
devm_led_classdev_flash_match, fled_cdev));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_led_classdev_flash_unregister);
|
||||||
|
|
||||||
static void led_clamp_align(struct led_flash_setting *s)
|
static void led_clamp_align(struct led_flash_setting *s)
|
||||||
{
|
{
|
||||||
u32 v, offset;
|
u32 v, offset;
|
||||||
|
|
|
@ -74,13 +74,13 @@ static ssize_t max_brightness_show(struct device *dev,
|
||||||
static DEVICE_ATTR_RO(max_brightness);
|
static DEVICE_ATTR_RO(max_brightness);
|
||||||
|
|
||||||
#ifdef CONFIG_LEDS_TRIGGERS
|
#ifdef CONFIG_LEDS_TRIGGERS
|
||||||
static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
|
static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0);
|
||||||
static struct attribute *led_trigger_attrs[] = {
|
static struct bin_attribute *led_trigger_bin_attrs[] = {
|
||||||
&dev_attr_trigger.attr,
|
&bin_attr_trigger,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static const struct attribute_group led_trigger_group = {
|
static const struct attribute_group led_trigger_group = {
|
||||||
.attrs = led_trigger_attrs,
|
.bin_attrs = led_trigger_bin_attrs,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext);
|
||||||
|
|
||||||
static int devm_led_classdev_match(struct device *dev, void *res, void *data)
|
static int devm_led_classdev_match(struct device *dev, void *res, void *data)
|
||||||
{
|
{
|
||||||
struct led_cdev **p = res;
|
struct led_classdev **p = res;
|
||||||
|
|
||||||
if (WARN_ON(!p || !*p))
|
if (WARN_ON(!p || !*p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <linux/leds.h>
|
#include <linux/leds.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
#include "leds.h"
|
#include "leds.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -26,9 +27,11 @@ LIST_HEAD(trigger_list);
|
||||||
|
|
||||||
/* Used by LED Class */
|
/* Used by LED Class */
|
||||||
|
|
||||||
ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
|
ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
|
||||||
const char *buf, size_t count)
|
struct bin_attribute *bin_attr, char *buf,
|
||||||
|
loff_t pos, size_t count)
|
||||||
{
|
{
|
||||||
|
struct device *dev = kobj_to_dev(kobj);
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||||
struct led_trigger *trig;
|
struct led_trigger *trig;
|
||||||
int ret = count;
|
int ret = count;
|
||||||
|
@ -64,39 +67,82 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
|
||||||
mutex_unlock(&led_cdev->led_access);
|
mutex_unlock(&led_cdev->led_access);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(led_trigger_store);
|
EXPORT_SYMBOL_GPL(led_trigger_write);
|
||||||
|
|
||||||
ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
|
__printf(3, 4)
|
||||||
char *buf)
|
static int led_trigger_snprintf(char *buf, ssize_t size, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
if (size <= 0)
|
||||||
|
i = vsnprintf(NULL, 0, fmt, args);
|
||||||
|
else
|
||||||
|
i = vscnprintf(buf, size, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int led_trigger_format(char *buf, size_t size,
|
||||||
|
struct led_classdev *led_cdev)
|
||||||
{
|
{
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_trigger *trig;
|
struct led_trigger *trig;
|
||||||
int len = 0;
|
int len = led_trigger_snprintf(buf, size, "%s",
|
||||||
|
led_cdev->trigger ? "none" : "[none]");
|
||||||
|
|
||||||
|
list_for_each_entry(trig, &trigger_list, next_trig) {
|
||||||
|
bool hit = led_cdev->trigger &&
|
||||||
|
!strcmp(led_cdev->trigger->name, trig->name);
|
||||||
|
|
||||||
|
len += led_trigger_snprintf(buf + len, size - len,
|
||||||
|
" %s%s%s", hit ? "[" : "",
|
||||||
|
trig->name, hit ? "]" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
len += led_trigger_snprintf(buf + len, size - len, "\n");
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It was stupid to create 10000 cpu triggers, but we are stuck with it now.
|
||||||
|
* Don't make that mistake again. We work around it here by creating binary
|
||||||
|
* attribute, which is not limited by length. This is _not_ good design, do not
|
||||||
|
* copy it.
|
||||||
|
*/
|
||||||
|
ssize_t led_trigger_read(struct file *filp, struct kobject *kobj,
|
||||||
|
struct bin_attribute *attr, char *buf,
|
||||||
|
loff_t pos, size_t count)
|
||||||
|
{
|
||||||
|
struct device *dev = kobj_to_dev(kobj);
|
||||||
|
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
||||||
|
void *data;
|
||||||
|
int len;
|
||||||
|
|
||||||
down_read(&triggers_list_lock);
|
down_read(&triggers_list_lock);
|
||||||
down_read(&led_cdev->trigger_lock);
|
down_read(&led_cdev->trigger_lock);
|
||||||
|
|
||||||
if (!led_cdev->trigger)
|
len = led_trigger_format(NULL, 0, led_cdev);
|
||||||
len += scnprintf(buf+len, PAGE_SIZE - len, "[none] ");
|
data = kvmalloc(len + 1, GFP_KERNEL);
|
||||||
else
|
if (!data) {
|
||||||
len += scnprintf(buf+len, PAGE_SIZE - len, "none ");
|
up_read(&led_cdev->trigger_lock);
|
||||||
|
up_read(&triggers_list_lock);
|
||||||
list_for_each_entry(trig, &trigger_list, next_trig) {
|
return -ENOMEM;
|
||||||
if (led_cdev->trigger && !strcmp(led_cdev->trigger->name,
|
|
||||||
trig->name))
|
|
||||||
len += scnprintf(buf+len, PAGE_SIZE - len, "[%s] ",
|
|
||||||
trig->name);
|
|
||||||
else
|
|
||||||
len += scnprintf(buf+len, PAGE_SIZE - len, "%s ",
|
|
||||||
trig->name);
|
|
||||||
}
|
}
|
||||||
|
len = led_trigger_format(data, len + 1, led_cdev);
|
||||||
|
|
||||||
up_read(&led_cdev->trigger_lock);
|
up_read(&led_cdev->trigger_lock);
|
||||||
up_read(&triggers_list_lock);
|
up_read(&triggers_list_lock);
|
||||||
|
|
||||||
len += scnprintf(len+buf, PAGE_SIZE - len, "\n");
|
len = memory_read_from_buffer(buf, count, &pos, data, len);
|
||||||
|
|
||||||
|
kvfree(data);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(led_trigger_show);
|
EXPORT_SYMBOL_GPL(led_trigger_read);
|
||||||
|
|
||||||
/* Caller must ensure led_cdev->trigger_lock held */
|
/* Caller must ensure led_cdev->trigger_lock held */
|
||||||
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
|
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
|
||||||
|
|
|
@ -305,6 +305,13 @@ static int an30259a_probe(struct i2c_client *client)
|
||||||
|
|
||||||
chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config);
|
chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config);
|
||||||
|
|
||||||
|
if (IS_ERR(chip->regmap)) {
|
||||||
|
err = PTR_ERR(chip->regmap);
|
||||||
|
dev_err(&client->dev, "Failed to allocate register map: %d\n",
|
||||||
|
err);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < chip->num_leds; i++) {
|
for (i = 0; i < chip->num_leds; i++) {
|
||||||
struct led_init_data init_data = {};
|
struct led_init_data init_data = {};
|
||||||
|
|
||||||
|
|
|
@ -346,16 +346,11 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
struct device_node *child;
|
struct device_node *child;
|
||||||
struct resource *mem_r;
|
|
||||||
void __iomem *mem;
|
void __iomem *mem;
|
||||||
spinlock_t *lock; /* memory lock */
|
spinlock_t *lock; /* memory lock */
|
||||||
unsigned long val, *blink_leds, *blink_delay;
|
unsigned long val, *blink_leds, *blink_delay;
|
||||||
|
|
||||||
mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (!mem_r)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
mem = devm_ioremap_resource(dev, mem_r);
|
|
||||||
if (IS_ERR(mem))
|
if (IS_ERR(mem))
|
||||||
return PTR_ERR(mem);
|
return PTR_ERR(mem);
|
||||||
|
|
||||||
|
|
|
@ -151,17 +151,12 @@ static int bcm6358_leds_probe(struct platform_device *pdev)
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct device_node *np = pdev->dev.of_node;
|
struct device_node *np = pdev->dev.of_node;
|
||||||
struct device_node *child;
|
struct device_node *child;
|
||||||
struct resource *mem_r;
|
|
||||||
void __iomem *mem;
|
void __iomem *mem;
|
||||||
spinlock_t *lock; /* memory lock */
|
spinlock_t *lock; /* memory lock */
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
u32 clk_div;
|
u32 clk_div;
|
||||||
|
|
||||||
mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (!mem_r)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
mem = devm_ioremap_resource(dev, mem_r);
|
|
||||||
if (IS_ERR(mem))
|
if (IS_ERR(mem))
|
||||||
return PTR_ERR(mem);
|
return PTR_ERR(mem);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,357 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Copyright (c) 2019 Crane Merchandising Systems. All rights reserved.
|
||||||
|
// Copyright (C) 2019 Oleh Kravchenko <oleg@kaa.org.ua>
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/leds.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EL15203000 SPI protocol description:
|
||||||
|
* +-----+---------+
|
||||||
|
* | LED | COMMAND |
|
||||||
|
* +-----+---------+
|
||||||
|
* | 1 | 1 |
|
||||||
|
* +-----+---------+
|
||||||
|
* (*) LEDs MCU board expects 20 msec delay per byte.
|
||||||
|
*
|
||||||
|
* LEDs:
|
||||||
|
* +----------+--------------+-------------------------------------------+
|
||||||
|
* | ID | NAME | DESCRIPTION |
|
||||||
|
* +----------+--------------+-------------------------------------------+
|
||||||
|
* | 'P' 0x50 | Pipe | Consists from 5 LEDs, controlled by board |
|
||||||
|
* +----------+--------------+-------------------------------------------+
|
||||||
|
* | 'S' 0x53 | Screen frame | Light tube around the screen |
|
||||||
|
* +----------+--------------+-------------------------------------------+
|
||||||
|
* | 'V' 0x56 | Vending area | Highlights a cup of coffee |
|
||||||
|
* +----------+--------------+-------------------------------------------+
|
||||||
|
*
|
||||||
|
* COMMAND:
|
||||||
|
* +----------+-----------------+--------------+--------------+
|
||||||
|
* | VALUES | PIPE | SCREEN FRAME | VENDING AREA |
|
||||||
|
* +----------+-----------------+--------------+--------------+
|
||||||
|
* | '0' 0x30 | Off |
|
||||||
|
* +----------+-----------------------------------------------+
|
||||||
|
* | '1' 0x31 | On |
|
||||||
|
* +----------+-----------------+--------------+--------------+
|
||||||
|
* | '2' 0x32 | Cascade | Breathing |
|
||||||
|
* +----------+-----------------+--------------+
|
||||||
|
* | '3' 0x33 | Inverse cascade |
|
||||||
|
* +----------+-----------------+
|
||||||
|
* | '4' 0x34 | Bounce |
|
||||||
|
* +----------+-----------------+
|
||||||
|
* | '5' 0x35 | Inverse bounce |
|
||||||
|
* +----------+-----------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* EL15203000 default settings */
|
||||||
|
#define EL_FW_DELAY_USEC 20000ul
|
||||||
|
#define EL_PATTERN_DELAY_MSEC 800u
|
||||||
|
#define EL_PATTERN_LEN 10u
|
||||||
|
#define EL_PATTERN_HALF_LEN (EL_PATTERN_LEN / 2)
|
||||||
|
|
||||||
|
enum el15203000_command {
|
||||||
|
/* for all LEDs */
|
||||||
|
EL_OFF = '0',
|
||||||
|
EL_ON = '1',
|
||||||
|
|
||||||
|
/* for Screen LED */
|
||||||
|
EL_SCREEN_BREATHING = '2',
|
||||||
|
|
||||||
|
/* for Pipe LED */
|
||||||
|
EL_PIPE_CASCADE = '2',
|
||||||
|
EL_PIPE_INV_CASCADE = '3',
|
||||||
|
EL_PIPE_BOUNCE = '4',
|
||||||
|
EL_PIPE_INV_BOUNCE = '5',
|
||||||
|
};
|
||||||
|
|
||||||
|
struct el15203000_led {
|
||||||
|
struct el15203000 *priv;
|
||||||
|
struct led_classdev ldev;
|
||||||
|
u32 reg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct el15203000 {
|
||||||
|
struct device *dev;
|
||||||
|
struct mutex lock;
|
||||||
|
struct spi_device *spi;
|
||||||
|
unsigned long delay;
|
||||||
|
size_t count;
|
||||||
|
struct el15203000_led leds[];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int el15203000_cmd(struct el15203000_led *led, u8 brightness)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 cmd[2];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
mutex_lock(&led->priv->lock);
|
||||||
|
|
||||||
|
dev_dbg(led->priv->dev, "Set brightness of 0x%02x(%c) to 0x%02x(%c)",
|
||||||
|
led->reg, led->reg, brightness, brightness);
|
||||||
|
|
||||||
|
/* to avoid SPI mistiming with firmware we should wait some time */
|
||||||
|
if (time_after(led->priv->delay, jiffies)) {
|
||||||
|
dev_dbg(led->priv->dev, "Wait %luus to sync",
|
||||||
|
EL_FW_DELAY_USEC);
|
||||||
|
|
||||||
|
usleep_range(EL_FW_DELAY_USEC,
|
||||||
|
EL_FW_DELAY_USEC + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd[0] = led->reg;
|
||||||
|
cmd[1] = brightness;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cmd); i++) {
|
||||||
|
if (i)
|
||||||
|
usleep_range(EL_FW_DELAY_USEC,
|
||||||
|
EL_FW_DELAY_USEC + 1);
|
||||||
|
|
||||||
|
ret = spi_write(led->priv->spi, &cmd[i], sizeof(cmd[i]));
|
||||||
|
if (ret) {
|
||||||
|
dev_err(led->priv->dev,
|
||||||
|
"spi_write() error %d", ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
led->priv->delay = jiffies + usecs_to_jiffies(EL_FW_DELAY_USEC);
|
||||||
|
|
||||||
|
mutex_unlock(&led->priv->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_set_blocking(struct led_classdev *ldev,
|
||||||
|
enum led_brightness brightness)
|
||||||
|
{
|
||||||
|
struct el15203000_led *led = container_of(ldev,
|
||||||
|
struct el15203000_led,
|
||||||
|
ldev);
|
||||||
|
|
||||||
|
return el15203000_cmd(led, brightness == LED_OFF ? EL_OFF : EL_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_pattern_set_S(struct led_classdev *ldev,
|
||||||
|
struct led_pattern *pattern,
|
||||||
|
u32 len, int repeat)
|
||||||
|
{
|
||||||
|
struct el15203000_led *led = container_of(ldev,
|
||||||
|
struct el15203000_led,
|
||||||
|
ldev);
|
||||||
|
|
||||||
|
if (repeat > 0 || len != 2 ||
|
||||||
|
pattern[0].delta_t != 4000 || pattern[0].brightness != 0 ||
|
||||||
|
pattern[1].delta_t != 4000 || pattern[1].brightness != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
dev_dbg(led->priv->dev, "Breathing mode for 0x%02x(%c)",
|
||||||
|
led->reg, led->reg);
|
||||||
|
|
||||||
|
return el15203000_cmd(led, EL_SCREEN_BREATHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_cascade(const struct led_pattern *pattern, u32 len,
|
||||||
|
bool inv, bool right)
|
||||||
|
{
|
||||||
|
int val, t;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
if (len != EL_PATTERN_HALF_LEN)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
val = right ? BIT(4) : BIT(0);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
t = inv ? ~val & GENMASK(4, 0) : val;
|
||||||
|
|
||||||
|
if (pattern[i].delta_t != EL_PATTERN_DELAY_MSEC ||
|
||||||
|
pattern[i].brightness != t)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
val = right ? val >> 1 : val << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_bounce(const struct led_pattern *pattern, u32 len, bool inv)
|
||||||
|
{
|
||||||
|
if (len != EL_PATTERN_LEN)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return is_cascade(pattern, EL_PATTERN_HALF_LEN, inv, false) &&
|
||||||
|
is_cascade(pattern + EL_PATTERN_HALF_LEN,
|
||||||
|
EL_PATTERN_HALF_LEN, inv, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_pattern_set_P(struct led_classdev *ldev,
|
||||||
|
struct led_pattern *pattern,
|
||||||
|
u32 len, int repeat)
|
||||||
|
{
|
||||||
|
u8 cmd;
|
||||||
|
struct el15203000_led *led = container_of(ldev,
|
||||||
|
struct el15203000_led,
|
||||||
|
ldev);
|
||||||
|
|
||||||
|
if (repeat > 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (is_cascade(pattern, len, false, false)) {
|
||||||
|
dev_dbg(led->priv->dev, "Cascade mode for 0x%02x(%c)",
|
||||||
|
led->reg, led->reg);
|
||||||
|
|
||||||
|
cmd = EL_PIPE_CASCADE;
|
||||||
|
} else if (is_cascade(pattern, len, true, false)) {
|
||||||
|
dev_dbg(led->priv->dev, "Inverse cascade mode for 0x%02x(%c)",
|
||||||
|
led->reg, led->reg);
|
||||||
|
|
||||||
|
cmd = EL_PIPE_INV_CASCADE;
|
||||||
|
} else if (is_bounce(pattern, len, false)) {
|
||||||
|
dev_dbg(led->priv->dev, "Bounce mode for 0x%02x(%c)",
|
||||||
|
led->reg, led->reg);
|
||||||
|
|
||||||
|
cmd = EL_PIPE_BOUNCE;
|
||||||
|
} else if (is_bounce(pattern, len, true)) {
|
||||||
|
dev_dbg(led->priv->dev, "Inverse bounce mode for 0x%02x(%c)",
|
||||||
|
led->reg, led->reg);
|
||||||
|
|
||||||
|
cmd = EL_PIPE_INV_BOUNCE;
|
||||||
|
} else {
|
||||||
|
dev_err(led->priv->dev, "Invalid hw_pattern for 0x%02x(%c)!",
|
||||||
|
led->reg, led->reg);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return el15203000_cmd(led, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_pattern_clear(struct led_classdev *ldev)
|
||||||
|
{
|
||||||
|
struct el15203000_led *led = container_of(ldev,
|
||||||
|
struct el15203000_led,
|
||||||
|
ldev);
|
||||||
|
|
||||||
|
return el15203000_cmd(led, EL_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_probe_dt(struct el15203000 *priv)
|
||||||
|
{
|
||||||
|
struct el15203000_led *led = priv->leds;
|
||||||
|
struct fwnode_handle *child;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
device_for_each_child_node(priv->dev, child) {
|
||||||
|
struct led_init_data init_data = {};
|
||||||
|
|
||||||
|
ret = fwnode_property_read_u32(child, "reg", &led->reg);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(priv->dev, "LED without ID number");
|
||||||
|
fwnode_handle_put(child);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (led->reg > U8_MAX) {
|
||||||
|
dev_err(priv->dev, "LED value %d is invalid", led->reg);
|
||||||
|
fwnode_handle_put(child);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwnode_property_read_string(child, "linux,default-trigger",
|
||||||
|
&led->ldev.default_trigger);
|
||||||
|
|
||||||
|
led->priv = priv;
|
||||||
|
led->ldev.max_brightness = LED_ON;
|
||||||
|
led->ldev.brightness_set_blocking = el15203000_set_blocking;
|
||||||
|
|
||||||
|
if (led->reg == 'S') {
|
||||||
|
led->ldev.pattern_set = el15203000_pattern_set_S;
|
||||||
|
led->ldev.pattern_clear = el15203000_pattern_clear;
|
||||||
|
} else if (led->reg == 'P') {
|
||||||
|
led->ldev.pattern_set = el15203000_pattern_set_P;
|
||||||
|
led->ldev.pattern_clear = el15203000_pattern_clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_data.fwnode = child;
|
||||||
|
ret = devm_led_classdev_register_ext(priv->dev, &led->ldev,
|
||||||
|
&init_data);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(priv->dev,
|
||||||
|
"failed to register LED device %s, err %d",
|
||||||
|
led->ldev.name, ret);
|
||||||
|
fwnode_handle_put(child);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
led++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_probe(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct el15203000 *priv;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
count = device_get_child_node_count(&spi->dev);
|
||||||
|
if (!count) {
|
||||||
|
dev_err(&spi->dev, "LEDs are not defined in device tree!");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&spi->dev, struct_size(priv, leds, count),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mutex_init(&priv->lock);
|
||||||
|
priv->count = count;
|
||||||
|
priv->dev = &spi->dev;
|
||||||
|
priv->spi = spi;
|
||||||
|
priv->delay = jiffies -
|
||||||
|
usecs_to_jiffies(EL_FW_DELAY_USEC);
|
||||||
|
|
||||||
|
spi_set_drvdata(spi, priv);
|
||||||
|
|
||||||
|
return el15203000_probe_dt(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int el15203000_remove(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct el15203000 *priv = spi_get_drvdata(spi);
|
||||||
|
|
||||||
|
mutex_destroy(&priv->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id el15203000_dt_ids[] = {
|
||||||
|
{ .compatible = "crane,el15203000", },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(of, el15203000_dt_ids);
|
||||||
|
|
||||||
|
static struct spi_driver el15203000_driver = {
|
||||||
|
.probe = el15203000_probe,
|
||||||
|
.remove = el15203000_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = KBUILD_MODNAME,
|
||||||
|
.of_match_table = el15203000_dt_ids,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_spi_driver(el15203000_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
|
||||||
|
MODULE_DESCRIPTION("el15203000 LED driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_ALIAS("spi:el15203000");
|
|
@ -350,8 +350,7 @@ static int lm3601x_register_leds(struct lm3601x_led *led,
|
||||||
init_data.devicename = led->client->name;
|
init_data.devicename = led->client->name;
|
||||||
init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ?
|
init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ?
|
||||||
"torch" : "infrared";
|
"torch" : "infrared";
|
||||||
|
return devm_led_classdev_flash_register_ext(&led->client->dev,
|
||||||
return led_classdev_flash_register_ext(&led->client->dev,
|
|
||||||
&led->fled_cdev, &init_data);
|
&led->fled_cdev, &init_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,7 +444,6 @@ static int lm3601x_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct lm3601x_led *led = i2c_get_clientdata(client);
|
struct lm3601x_led *led = i2c_get_clientdata(client);
|
||||||
|
|
||||||
led_classdev_flash_unregister(&led->fled_cdev);
|
|
||||||
mutex_destroy(&led->lock);
|
mutex_destroy(&led->lock);
|
||||||
|
|
||||||
return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
|
return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,
|
||||||
|
|
|
@ -174,19 +174,20 @@ static int lm3692x_brightness_set(struct led_classdev *led_cdev,
|
||||||
|
|
||||||
ret = lm3692x_fault_check(led);
|
ret = lm3692x_fault_check(led);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&led->client->dev, "Cannot read/clear faults\n");
|
dev_err(&led->client->dev, "Cannot read/clear faults: %d\n",
|
||||||
|
ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(led->regmap, LM3692X_BRT_MSB, brt_val);
|
ret = regmap_write(led->regmap, LM3692X_BRT_MSB, brt_val);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&led->client->dev, "Cannot write MSB\n");
|
dev_err(&led->client->dev, "Cannot write MSB: %d\n", ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_write(led->regmap, LM3692X_BRT_LSB, led_brightness_lsb);
|
ret = regmap_write(led->regmap, LM3692X_BRT_LSB, led_brightness_lsb);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&led->client->dev, "Cannot write LSB\n");
|
dev_err(&led->client->dev, "Cannot write LSB: %d\n", ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@ -197,13 +198,13 @@ static int lm3692x_brightness_set(struct led_classdev *led_cdev,
|
||||||
static int lm3692x_init(struct lm3692x_led *led)
|
static int lm3692x_init(struct lm3692x_led *led)
|
||||||
{
|
{
|
||||||
int enable_state;
|
int enable_state;
|
||||||
int ret;
|
int ret, reg_ret;
|
||||||
|
|
||||||
if (led->regulator) {
|
if (led->regulator) {
|
||||||
ret = regulator_enable(led->regulator);
|
ret = regulator_enable(led->regulator);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&led->client->dev,
|
dev_err(&led->client->dev,
|
||||||
"Failed to enable regulator\n");
|
"Failed to enable regulator: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +214,8 @@ static int lm3692x_init(struct lm3692x_led *led)
|
||||||
|
|
||||||
ret = lm3692x_fault_check(led);
|
ret = lm3692x_fault_check(led);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&led->client->dev, "Cannot read/clear faults\n");
|
dev_err(&led->client->dev, "Cannot read/clear faults: %d\n",
|
||||||
|
ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +250,9 @@ static int lm3692x_init(struct lm3692x_led *led)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = regmap_write(led->regmap, LM3692X_BOOST_CTRL,
|
ret = regmap_write(led->regmap, LM3692X_BOOST_CTRL,
|
||||||
LM3692X_BRHT_MODE_RAMP_MULTI |
|
LM3692X_BOOST_SW_1MHZ |
|
||||||
LM3692X_BL_ADJ_POL |
|
LM3692X_BOOST_SW_NO_SHIFT |
|
||||||
LM3692X_RAMP_RATE_250us);
|
LM3692X_OCP_PROT_1_5A);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -267,7 +269,7 @@ static int lm3692x_init(struct lm3692x_led *led)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = regmap_write(led->regmap, LM3692X_BRT_CTRL,
|
ret = regmap_write(led->regmap, LM3692X_BRT_CTRL,
|
||||||
LM3692X_BL_ADJ_POL | LM3692X_PWM_HYSTER_4LSB);
|
LM3692X_BL_ADJ_POL | LM3692X_RAMP_EN);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -311,14 +313,15 @@ static int lm3692x_init(struct lm3692x_led *led)
|
||||||
gpiod_direction_output(led->enable_gpio, 0);
|
gpiod_direction_output(led->enable_gpio, 0);
|
||||||
|
|
||||||
if (led->regulator) {
|
if (led->regulator) {
|
||||||
ret = regulator_disable(led->regulator);
|
reg_ret = regulator_disable(led->regulator);
|
||||||
if (ret)
|
if (reg_ret)
|
||||||
dev_err(&led->client->dev,
|
dev_err(&led->client->dev,
|
||||||
"Failed to disable regulator\n");
|
"Failed to disable regulator: %d\n", reg_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lm3692x_probe_dt(struct lm3692x_led *led)
|
static int lm3692x_probe_dt(struct lm3692x_led *led)
|
||||||
{
|
{
|
||||||
struct fwnode_handle *child = NULL;
|
struct fwnode_handle *child = NULL;
|
||||||
|
@ -334,9 +337,18 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
led->regulator = devm_regulator_get(&led->client->dev, "vled");
|
led->regulator = devm_regulator_get_optional(&led->client->dev, "vled");
|
||||||
if (IS_ERR(led->regulator))
|
if (IS_ERR(led->regulator)) {
|
||||||
|
ret = PTR_ERR(led->regulator);
|
||||||
|
if (ret != -ENODEV) {
|
||||||
|
if (ret != -EPROBE_DEFER)
|
||||||
|
dev_err(&led->client->dev,
|
||||||
|
"Failed to get vled regulator: %d\n",
|
||||||
|
ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
led->regulator = NULL;
|
led->regulator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
child = device_get_next_child_node(&led->client->dev, child);
|
child = device_get_next_child_node(&led->client->dev, child);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
|
@ -409,7 +421,8 @@ static int lm3692x_remove(struct i2c_client *client)
|
||||||
|
|
||||||
ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, 0);
|
ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&led->client->dev, "Failed to disable regulator\n");
|
dev_err(&led->client->dev, "Failed to disable regulator: %d\n",
|
||||||
|
ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +433,7 @@ static int lm3692x_remove(struct i2c_client *client)
|
||||||
ret = regulator_disable(led->regulator);
|
ret = regulator_disable(led->regulator);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(&led->client->dev,
|
dev_err(&led->client->dev,
|
||||||
"Failed to disable regulator\n");
|
"Failed to disable regulator: %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_destroy(&led->lock);
|
mutex_destroy(&led->lock);
|
||||||
|
|
|
@ -228,8 +228,8 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
|
||||||
brightness = LED_OFF;
|
brightness = LED_OFF;
|
||||||
led_data->base_color = MLXREG_LED_GREEN_SOLID;
|
led_data->base_color = MLXREG_LED_GREEN_SOLID;
|
||||||
}
|
}
|
||||||
sprintf(led_data->led_cdev_name, "%s:%s", "mlxreg",
|
snprintf(led_data->led_cdev_name, sizeof(led_data->led_cdev_name),
|
||||||
data->label);
|
"mlxreg:%s", data->label);
|
||||||
led_cdev->name = led_data->led_cdev_name;
|
led_cdev->name = led_data->led_cdev_name;
|
||||||
led_cdev->brightness = brightness;
|
led_cdev->brightness = brightness;
|
||||||
led_cdev->max_brightness = LED_ON;
|
led_cdev->max_brightness = LED_ON;
|
||||||
|
|
|
@ -467,16 +467,11 @@ pca9532_of_populate_pdata(struct device *dev, struct device_node *np)
|
||||||
{
|
{
|
||||||
struct pca9532_platform_data *pdata;
|
struct pca9532_platform_data *pdata;
|
||||||
struct device_node *child;
|
struct device_node *child;
|
||||||
const struct of_device_id *match;
|
|
||||||
int devid, maxleds;
|
int devid, maxleds;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
const char *state;
|
const char *state;
|
||||||
|
|
||||||
match = of_match_device(of_pca9532_leds_match, dev);
|
devid = (int)(uintptr_t)of_device_get_match_data(dev);
|
||||||
if (!match)
|
|
||||||
return ERR_PTR(-ENODEV);
|
|
||||||
|
|
||||||
devid = (int)(uintptr_t)match->data;
|
|
||||||
maxleds = pca9532_chip_info_tbl[devid].num_leds;
|
maxleds = pca9532_chip_info_tbl[devid].num_leds;
|
||||||
|
|
||||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||||
|
@ -509,7 +504,6 @@ static int pca9532_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
int devid;
|
int devid;
|
||||||
const struct of_device_id *of_id;
|
|
||||||
struct pca9532_data *data = i2c_get_clientdata(client);
|
struct pca9532_data *data = i2c_get_clientdata(client);
|
||||||
struct pca9532_platform_data *pca9532_pdata =
|
struct pca9532_platform_data *pca9532_pdata =
|
||||||
dev_get_platdata(&client->dev);
|
dev_get_platdata(&client->dev);
|
||||||
|
@ -525,11 +519,7 @@ static int pca9532_probe(struct i2c_client *client,
|
||||||
dev_err(&client->dev, "no platform data\n");
|
dev_err(&client->dev, "no platform data\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
of_id = of_match_device(of_pca9532_leds_match,
|
devid = (int)(uintptr_t)of_device_get_match_data(&client->dev);
|
||||||
&client->dev);
|
|
||||||
if (unlikely(!of_id))
|
|
||||||
return -EINVAL;
|
|
||||||
devid = (int)(uintptr_t) of_id->data;
|
|
||||||
} else {
|
} else {
|
||||||
devid = id->driver_data;
|
devid = id->driver_data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#define TLC591XX_MAX_LEDS 16
|
#define TLC591XX_MAX_LEDS 16
|
||||||
|
#define TLC591XX_MAX_BRIGHTNESS 256
|
||||||
|
|
||||||
#define TLC591XX_REG_MODE1 0x00
|
#define TLC591XX_REG_MODE1 0x00
|
||||||
#define MODE1_RESPON_ADDR_MASK 0xF0
|
#define MODE1_RESPON_ADDR_MASK 0xF0
|
||||||
|
@ -112,11 +113,11 @@ tlc591xx_brightness_set(struct led_classdev *led_cdev,
|
||||||
struct tlc591xx_priv *priv = led->priv;
|
struct tlc591xx_priv *priv = led->priv;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
switch (brightness) {
|
switch ((int)brightness) {
|
||||||
case 0:
|
case 0:
|
||||||
err = tlc591xx_set_ledout(priv, led, LEDOUT_OFF);
|
err = tlc591xx_set_ledout(priv, led, LEDOUT_OFF);
|
||||||
break;
|
break;
|
||||||
case LED_FULL:
|
case TLC591XX_MAX_BRIGHTNESS:
|
||||||
err = tlc591xx_set_ledout(priv, led, LEDOUT_ON);
|
err = tlc591xx_set_ledout(priv, led, LEDOUT_ON);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -128,51 +129,6 @@ tlc591xx_brightness_set(struct led_classdev *led_cdev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
tlc591xx_destroy_devices(struct tlc591xx_priv *priv, unsigned int j)
|
|
||||||
{
|
|
||||||
int i = j;
|
|
||||||
|
|
||||||
while (--i >= 0) {
|
|
||||||
if (priv->leds[i].active)
|
|
||||||
led_classdev_unregister(&priv->leds[i].ldev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
tlc591xx_configure(struct device *dev,
|
|
||||||
struct tlc591xx_priv *priv,
|
|
||||||
const struct tlc591xx *tlc591xx)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
tlc591xx_set_mode(priv->regmap, MODE2_DIM);
|
|
||||||
for (i = 0; i < TLC591XX_MAX_LEDS; i++) {
|
|
||||||
struct tlc591xx_led *led = &priv->leds[i];
|
|
||||||
|
|
||||||
if (!led->active)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
led->priv = priv;
|
|
||||||
led->led_no = i;
|
|
||||||
led->ldev.brightness_set_blocking = tlc591xx_brightness_set;
|
|
||||||
led->ldev.max_brightness = LED_FULL;
|
|
||||||
err = led_classdev_register(dev, &led->ldev);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(dev, "couldn't register LED %s\n",
|
|
||||||
led->ldev.name);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
tlc591xx_destroy_devices(priv, i);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct regmap_config tlc591xx_regmap = {
|
static const struct regmap_config tlc591xx_regmap = {
|
||||||
.reg_bits = 8,
|
.reg_bits = 8,
|
||||||
.val_bits = 8,
|
.val_bits = 8,
|
||||||
|
@ -225,7 +181,16 @@ tlc591xx_probe(struct i2c_client *client,
|
||||||
|
|
||||||
i2c_set_clientdata(client, priv);
|
i2c_set_clientdata(client, priv);
|
||||||
|
|
||||||
|
err = tlc591xx_set_mode(priv->regmap, MODE2_DIM);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
for_each_child_of_node(np, child) {
|
for_each_child_of_node(np, child) {
|
||||||
|
struct tlc591xx_led *led;
|
||||||
|
struct led_init_data init_data = {};
|
||||||
|
|
||||||
|
init_data.fwnode = of_fwnode_handle(child);
|
||||||
|
|
||||||
err = of_property_read_u32(child, "reg", ®);
|
err = of_property_read_u32(child, "reg", ®);
|
||||||
if (err) {
|
if (err) {
|
||||||
of_node_put(child);
|
of_node_put(child);
|
||||||
|
@ -236,22 +201,24 @@ tlc591xx_probe(struct i2c_client *client,
|
||||||
of_node_put(child);
|
of_node_put(child);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
priv->leds[reg].active = true;
|
led = &priv->leds[reg];
|
||||||
priv->leds[reg].ldev.name =
|
|
||||||
of_get_property(child, "label", NULL) ? : child->name;
|
led->active = true;
|
||||||
priv->leds[reg].ldev.default_trigger =
|
led->ldev.default_trigger =
|
||||||
of_get_property(child, "linux,default-trigger", NULL);
|
of_get_property(child, "linux,default-trigger", NULL);
|
||||||
|
|
||||||
|
led->priv = priv;
|
||||||
|
led->led_no = reg;
|
||||||
|
led->ldev.brightness_set_blocking = tlc591xx_brightness_set;
|
||||||
|
led->ldev.max_brightness = TLC591XX_MAX_BRIGHTNESS;
|
||||||
|
err = devm_led_classdev_register_ext(dev, &led->ldev,
|
||||||
|
&init_data);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "couldn't register LED %s\n",
|
||||||
|
led->ldev.name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return tlc591xx_configure(dev, priv, tlc591xx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
tlc591xx_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct tlc591xx_priv *priv = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
tlc591xx_destroy_devices(priv, TLC591XX_MAX_LEDS);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +235,6 @@ static struct i2c_driver tlc591xx_driver = {
|
||||||
.of_match_table = of_match_ptr(of_tlc591xx_leds_match),
|
.of_match_table = of_match_ptr(of_tlc591xx_leds_match),
|
||||||
},
|
},
|
||||||
.probe = tlc591xx_probe,
|
.probe = tlc591xx_probe,
|
||||||
.remove = tlc591xx_remove,
|
|
||||||
.id_table = tlc591xx_id,
|
.id_table = tlc591xx_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,12 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev,
|
||||||
enum led_brightness value);
|
enum led_brightness value);
|
||||||
void led_set_brightness_nosleep(struct led_classdev *led_cdev,
|
void led_set_brightness_nosleep(struct led_classdev *led_cdev,
|
||||||
enum led_brightness value);
|
enum led_brightness value);
|
||||||
|
ssize_t led_trigger_read(struct file *filp, struct kobject *kobj,
|
||||||
|
struct bin_attribute *attr, char *buf,
|
||||||
|
loff_t pos, size_t count);
|
||||||
|
ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
|
||||||
|
struct bin_attribute *bin_attr, char *buf,
|
||||||
|
loff_t pos, size_t count);
|
||||||
|
|
||||||
extern struct rw_semaphore leds_list_lock;
|
extern struct rw_semaphore leds_list_lock;
|
||||||
extern struct list_head leds_list;
|
extern struct list_head leds_list;
|
||||||
|
|
|
@ -302,10 +302,12 @@ static int netdev_trig_notify(struct notifier_block *nb,
|
||||||
container_of(nb, struct led_netdev_data, notifier);
|
container_of(nb, struct led_netdev_data, notifier);
|
||||||
|
|
||||||
if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
|
if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
|
||||||
&& evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
|
&& evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
|
||||||
|
&& evt != NETDEV_CHANGENAME)
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
if (!(dev == trigger_data->net_dev ||
|
if (!(dev == trigger_data->net_dev ||
|
||||||
|
(evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) ||
|
||||||
(evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
|
(evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
|
@ -315,6 +317,7 @@ static int netdev_trig_notify(struct notifier_block *nb,
|
||||||
|
|
||||||
clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
|
clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
|
||||||
switch (evt) {
|
switch (evt) {
|
||||||
|
case NETDEV_CHANGENAME:
|
||||||
case NETDEV_REGISTER:
|
case NETDEV_REGISTER:
|
||||||
if (trigger_data->net_dev)
|
if (trigger_data->net_dev)
|
||||||
dev_put(trigger_data->net_dev);
|
dev_put(trigger_data->net_dev);
|
||||||
|
|
|
@ -94,12 +94,15 @@ static inline struct led_classdev_flash *lcdev_to_flcdev(
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_classdev_flash_register_ext(struct device *parent,
|
int led_classdev_flash_register_ext(struct device *parent,
|
||||||
struct led_classdev_flash *fled_cdev,
|
struct led_classdev_flash *fled_cdev,
|
||||||
struct led_init_data *init_data);
|
struct led_init_data *init_data);
|
||||||
|
|
||||||
#define led_classdev_flash_register(parent, fled_cdev) \
|
static inline int led_classdev_flash_register(struct device *parent,
|
||||||
led_classdev_flash_register_ext(parent, fled_cdev, NULL)
|
struct led_classdev_flash *fled_cdev)
|
||||||
|
{
|
||||||
|
return led_classdev_flash_register_ext(parent, fled_cdev, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_classdev_flash_unregister - unregisters an object of led_classdev class
|
* led_classdev_flash_unregister - unregisters an object of led_classdev class
|
||||||
|
@ -108,7 +111,21 @@ extern int led_classdev_flash_register_ext(struct device *parent,
|
||||||
*
|
*
|
||||||
* Unregister a previously registered via led_classdev_flash_register object
|
* Unregister a previously registered via led_classdev_flash_register object
|
||||||
*/
|
*/
|
||||||
extern void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev);
|
void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev);
|
||||||
|
|
||||||
|
int devm_led_classdev_flash_register_ext(struct device *parent,
|
||||||
|
struct led_classdev_flash *fled_cdev,
|
||||||
|
struct led_init_data *init_data);
|
||||||
|
|
||||||
|
|
||||||
|
static inline int devm_led_classdev_flash_register(struct device *parent,
|
||||||
|
struct led_classdev_flash *fled_cdev)
|
||||||
|
{
|
||||||
|
return devm_led_classdev_flash_register_ext(parent, fled_cdev, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void devm_led_classdev_flash_unregister(struct device *parent,
|
||||||
|
struct led_classdev_flash *fled_cdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_set_flash_strobe - setup flash strobe
|
* led_set_flash_strobe - setup flash strobe
|
||||||
|
@ -156,8 +173,8 @@ static inline int led_get_flash_strobe(struct led_classdev_flash *fled_cdev,
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
|
int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
|
||||||
u32 brightness);
|
u32 brightness);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_update_flash_brightness - update flash LED brightness
|
* led_update_flash_brightness - update flash LED brightness
|
||||||
|
@ -168,7 +185,7 @@ extern int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_update_flash_brightness(struct led_classdev_flash *fled_cdev);
|
int led_update_flash_brightness(struct led_classdev_flash *fled_cdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_set_flash_timeout - set flash LED timeout
|
* led_set_flash_timeout - set flash LED timeout
|
||||||
|
@ -179,8 +196,7 @@ extern int led_update_flash_brightness(struct led_classdev_flash *fled_cdev);
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_set_flash_timeout(struct led_classdev_flash *fled_cdev,
|
int led_set_flash_timeout(struct led_classdev_flash *fled_cdev, u32 timeout);
|
||||||
u32 timeout);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_get_flash_fault - get the flash LED fault
|
* led_get_flash_fault - get the flash LED fault
|
||||||
|
@ -191,7 +207,6 @@ extern int led_set_flash_timeout(struct led_classdev_flash *fled_cdev,
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_get_flash_fault(struct led_classdev_flash *fled_cdev,
|
int led_get_flash_fault(struct led_classdev_flash *fled_cdev, u32 *fault);
|
||||||
u32 *fault);
|
|
||||||
|
|
||||||
#endif /* __LINUX_FLASH_LEDS_H_INCLUDED */
|
#endif /* __LINUX_FLASH_LEDS_H_INCLUDED */
|
||||||
|
|
|
@ -161,7 +161,7 @@ struct led_classdev {
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_classdev_register_ext(struct device *parent,
|
int led_classdev_register_ext(struct device *parent,
|
||||||
struct led_classdev *led_cdev,
|
struct led_classdev *led_cdev,
|
||||||
struct led_init_data *init_data);
|
struct led_init_data *init_data);
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ static inline int led_classdev_register(struct device *parent,
|
||||||
return led_classdev_register_ext(parent, led_cdev, NULL);
|
return led_classdev_register_ext(parent, led_cdev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int devm_led_classdev_register_ext(struct device *parent,
|
int devm_led_classdev_register_ext(struct device *parent,
|
||||||
struct led_classdev *led_cdev,
|
struct led_classdev *led_cdev,
|
||||||
struct led_init_data *init_data);
|
struct led_init_data *init_data);
|
||||||
|
|
||||||
|
@ -190,11 +190,11 @@ static inline int devm_led_classdev_register(struct device *parent,
|
||||||
{
|
{
|
||||||
return devm_led_classdev_register_ext(parent, led_cdev, NULL);
|
return devm_led_classdev_register_ext(parent, led_cdev, NULL);
|
||||||
}
|
}
|
||||||
extern void led_classdev_unregister(struct led_classdev *led_cdev);
|
void led_classdev_unregister(struct led_classdev *led_cdev);
|
||||||
extern void devm_led_classdev_unregister(struct device *parent,
|
void devm_led_classdev_unregister(struct device *parent,
|
||||||
struct led_classdev *led_cdev);
|
struct led_classdev *led_cdev);
|
||||||
extern void led_classdev_suspend(struct led_classdev *led_cdev);
|
void led_classdev_suspend(struct led_classdev *led_cdev);
|
||||||
extern void led_classdev_resume(struct led_classdev *led_cdev);
|
void led_classdev_resume(struct led_classdev *led_cdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_blink_set - set blinking with software fallback
|
* led_blink_set - set blinking with software fallback
|
||||||
|
@ -211,9 +211,8 @@ extern void led_classdev_resume(struct led_classdev *led_cdev);
|
||||||
* led_cdev->brightness_set() will not stop the blinking,
|
* led_cdev->brightness_set() will not stop the blinking,
|
||||||
* use led_classdev_brightness_set() instead.
|
* use led_classdev_brightness_set() instead.
|
||||||
*/
|
*/
|
||||||
extern void led_blink_set(struct led_classdev *led_cdev,
|
void led_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on,
|
||||||
unsigned long *delay_on,
|
unsigned long *delay_off);
|
||||||
unsigned long *delay_off);
|
|
||||||
/**
|
/**
|
||||||
* led_blink_set_oneshot - do a oneshot software blink
|
* led_blink_set_oneshot - do a oneshot software blink
|
||||||
* @led_cdev: the LED to start blinking
|
* @led_cdev: the LED to start blinking
|
||||||
|
@ -228,10 +227,9 @@ extern void led_blink_set(struct led_classdev *led_cdev,
|
||||||
* If invert is set, led blinks for delay_off first, then for
|
* If invert is set, led blinks for delay_off first, then for
|
||||||
* delay_on and leave the led on after the on-off cycle.
|
* delay_on and leave the led on after the on-off cycle.
|
||||||
*/
|
*/
|
||||||
extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
|
void led_blink_set_oneshot(struct led_classdev *led_cdev,
|
||||||
unsigned long *delay_on,
|
unsigned long *delay_on, unsigned long *delay_off,
|
||||||
unsigned long *delay_off,
|
int invert);
|
||||||
int invert);
|
|
||||||
/**
|
/**
|
||||||
* led_set_brightness - set LED brightness
|
* led_set_brightness - set LED brightness
|
||||||
* @led_cdev: the LED to set
|
* @led_cdev: the LED to set
|
||||||
|
@ -241,8 +239,8 @@ extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
|
||||||
* software blink timer that implements blinking when the
|
* software blink timer that implements blinking when the
|
||||||
* hardware doesn't. This function is guaranteed not to sleep.
|
* hardware doesn't. This function is guaranteed not to sleep.
|
||||||
*/
|
*/
|
||||||
extern void led_set_brightness(struct led_classdev *led_cdev,
|
void led_set_brightness(struct led_classdev *led_cdev,
|
||||||
enum led_brightness brightness);
|
enum led_brightness brightness);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_set_brightness_sync - set LED brightness synchronously
|
* led_set_brightness_sync - set LED brightness synchronously
|
||||||
|
@ -255,8 +253,8 @@ extern void led_set_brightness(struct led_classdev *led_cdev,
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_set_brightness_sync(struct led_classdev *led_cdev,
|
int led_set_brightness_sync(struct led_classdev *led_cdev,
|
||||||
enum led_brightness value);
|
enum led_brightness value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_update_brightness - update LED brightness
|
* led_update_brightness - update LED brightness
|
||||||
|
@ -267,7 +265,7 @@ extern int led_set_brightness_sync(struct led_classdev *led_cdev,
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_update_brightness(struct led_classdev *led_cdev);
|
int led_update_brightness(struct led_classdev *led_cdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_get_default_pattern - return default pattern
|
* led_get_default_pattern - return default pattern
|
||||||
|
@ -279,8 +277,7 @@ extern int led_update_brightness(struct led_classdev *led_cdev);
|
||||||
* Return: Allocated array of integers with default pattern from device tree
|
* Return: Allocated array of integers with default pattern from device tree
|
||||||
* or NULL. Caller is responsible for kfree().
|
* or NULL. Caller is responsible for kfree().
|
||||||
*/
|
*/
|
||||||
extern u32 *led_get_default_pattern(struct led_classdev *led_cdev,
|
u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size);
|
||||||
unsigned int *size);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_sysfs_disable - disable LED sysfs interface
|
* led_sysfs_disable - disable LED sysfs interface
|
||||||
|
@ -288,7 +285,7 @@ extern u32 *led_get_default_pattern(struct led_classdev *led_cdev,
|
||||||
*
|
*
|
||||||
* Disable the led_cdev's sysfs interface.
|
* Disable the led_cdev's sysfs interface.
|
||||||
*/
|
*/
|
||||||
extern void led_sysfs_disable(struct led_classdev *led_cdev);
|
void led_sysfs_disable(struct led_classdev *led_cdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_sysfs_enable - enable LED sysfs interface
|
* led_sysfs_enable - enable LED sysfs interface
|
||||||
|
@ -296,7 +293,7 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
|
||||||
*
|
*
|
||||||
* Enable the led_cdev's sysfs interface.
|
* Enable the led_cdev's sysfs interface.
|
||||||
*/
|
*/
|
||||||
extern void led_sysfs_enable(struct led_classdev *led_cdev);
|
void led_sysfs_enable(struct led_classdev *led_cdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_compose_name - compose LED class device name
|
* led_compose_name - compose LED class device name
|
||||||
|
@ -310,8 +307,8 @@ extern void led_sysfs_enable(struct led_classdev *led_cdev);
|
||||||
*
|
*
|
||||||
* Returns: 0 on success or negative error value on failure
|
* Returns: 0 on success or negative error value on failure
|
||||||
*/
|
*/
|
||||||
extern int led_compose_name(struct device *dev, struct led_init_data *init_data,
|
int led_compose_name(struct device *dev, struct led_init_data *init_data,
|
||||||
char *led_classdev_name);
|
char *led_classdev_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* led_sysfs_is_disabled - check if LED sysfs interface is disabled
|
* led_sysfs_is_disabled - check if LED sysfs interface is disabled
|
||||||
|
@ -360,33 +357,25 @@ struct led_trigger {
|
||||||
#define led_trigger_get_led(dev) ((struct led_classdev *)dev_get_drvdata((dev)))
|
#define led_trigger_get_led(dev) ((struct led_classdev *)dev_get_drvdata((dev)))
|
||||||
#define led_trigger_get_drvdata(dev) (led_get_trigger_data(led_trigger_get_led(dev)))
|
#define led_trigger_get_drvdata(dev) (led_get_trigger_data(led_trigger_get_led(dev)))
|
||||||
|
|
||||||
ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
|
|
||||||
const char *buf, size_t count);
|
|
||||||
ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
|
|
||||||
char *buf);
|
|
||||||
|
|
||||||
/* Registration functions for complex triggers */
|
/* Registration functions for complex triggers */
|
||||||
extern int led_trigger_register(struct led_trigger *trigger);
|
int led_trigger_register(struct led_trigger *trigger);
|
||||||
extern void led_trigger_unregister(struct led_trigger *trigger);
|
void led_trigger_unregister(struct led_trigger *trigger);
|
||||||
extern int devm_led_trigger_register(struct device *dev,
|
int devm_led_trigger_register(struct device *dev,
|
||||||
struct led_trigger *trigger);
|
struct led_trigger *trigger);
|
||||||
|
|
||||||
extern void led_trigger_register_simple(const char *name,
|
void led_trigger_register_simple(const char *name,
|
||||||
struct led_trigger **trigger);
|
struct led_trigger **trigger);
|
||||||
extern void led_trigger_unregister_simple(struct led_trigger *trigger);
|
void led_trigger_unregister_simple(struct led_trigger *trigger);
|
||||||
extern void led_trigger_event(struct led_trigger *trigger,
|
void led_trigger_event(struct led_trigger *trigger, enum led_brightness event);
|
||||||
enum led_brightness event);
|
void led_trigger_blink(struct led_trigger *trigger, unsigned long *delay_on,
|
||||||
extern void led_trigger_blink(struct led_trigger *trigger,
|
unsigned long *delay_off);
|
||||||
unsigned long *delay_on,
|
void led_trigger_blink_oneshot(struct led_trigger *trigger,
|
||||||
unsigned long *delay_off);
|
unsigned long *delay_on,
|
||||||
extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
|
unsigned long *delay_off,
|
||||||
unsigned long *delay_on,
|
int invert);
|
||||||
unsigned long *delay_off,
|
void led_trigger_set_default(struct led_classdev *led_cdev);
|
||||||
int invert);
|
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger);
|
||||||
extern void led_trigger_set_default(struct led_classdev *led_cdev);
|
void led_trigger_remove(struct led_classdev *led_cdev);
|
||||||
extern int led_trigger_set(struct led_classdev *led_cdev,
|
|
||||||
struct led_trigger *trigger);
|
|
||||||
extern void led_trigger_remove(struct led_classdev *led_cdev);
|
|
||||||
|
|
||||||
static inline void led_set_trigger_data(struct led_classdev *led_cdev,
|
static inline void led_set_trigger_data(struct led_classdev *led_cdev,
|
||||||
void *trigger_data)
|
void *trigger_data)
|
||||||
|
@ -414,8 +403,7 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
|
||||||
* This is meant to be used on triggers with statically
|
* This is meant to be used on triggers with statically
|
||||||
* allocated name.
|
* allocated name.
|
||||||
*/
|
*/
|
||||||
extern void led_trigger_rename_static(const char *name,
|
void led_trigger_rename_static(const char *name, struct led_trigger *trig);
|
||||||
struct led_trigger *trig);
|
|
||||||
|
|
||||||
#define module_led_trigger(__led_trigger) \
|
#define module_led_trigger(__led_trigger) \
|
||||||
module_driver(__led_trigger, led_trigger_register, \
|
module_driver(__led_trigger, led_trigger_register, \
|
||||||
|
@ -457,20 +445,20 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
|
||||||
|
|
||||||
/* Trigger specific functions */
|
/* Trigger specific functions */
|
||||||
#ifdef CONFIG_LEDS_TRIGGER_DISK
|
#ifdef CONFIG_LEDS_TRIGGER_DISK
|
||||||
extern void ledtrig_disk_activity(bool write);
|
void ledtrig_disk_activity(bool write);
|
||||||
#else
|
#else
|
||||||
static inline void ledtrig_disk_activity(bool write) {}
|
static inline void ledtrig_disk_activity(bool write) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_LEDS_TRIGGER_MTD
|
#ifdef CONFIG_LEDS_TRIGGER_MTD
|
||||||
extern void ledtrig_mtd_activity(void);
|
void ledtrig_mtd_activity(void);
|
||||||
#else
|
#else
|
||||||
static inline void ledtrig_mtd_activity(void) {}
|
static inline void ledtrig_mtd_activity(void) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE)
|
#if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE)
|
||||||
extern void ledtrig_flash_ctrl(bool on);
|
void ledtrig_flash_ctrl(bool on);
|
||||||
extern void ledtrig_torch_ctrl(bool on);
|
void ledtrig_torch_ctrl(bool on);
|
||||||
#else
|
#else
|
||||||
static inline void ledtrig_flash_ctrl(bool on) {}
|
static inline void ledtrig_flash_ctrl(bool on) {}
|
||||||
static inline void ledtrig_torch_ctrl(bool on) {}
|
static inline void ledtrig_torch_ctrl(bool on) {}
|
||||||
|
@ -550,7 +538,7 @@ enum cpu_led_event {
|
||||||
CPU_LED_HALTED, /* Machine shutdown */
|
CPU_LED_HALTED, /* Machine shutdown */
|
||||||
};
|
};
|
||||||
#ifdef CONFIG_LEDS_TRIGGER_CPU
|
#ifdef CONFIG_LEDS_TRIGGER_CPU
|
||||||
extern void ledtrig_cpu(enum cpu_led_event evt);
|
void ledtrig_cpu(enum cpu_led_event evt);
|
||||||
#else
|
#else
|
||||||
static inline void ledtrig_cpu(enum cpu_led_event evt)
|
static inline void ledtrig_cpu(enum cpu_led_event evt)
|
||||||
{
|
{
|
||||||
|
@ -559,7 +547,7 @@ static inline void ledtrig_cpu(enum cpu_led_event evt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
|
#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED
|
||||||
extern void led_classdev_notify_brightness_hw_changed(
|
void led_classdev_notify_brightness_hw_changed(
|
||||||
struct led_classdev *led_cdev, enum led_brightness brightness);
|
struct led_classdev *led_cdev, enum led_brightness brightness);
|
||||||
#else
|
#else
|
||||||
static inline void led_classdev_notify_brightness_hw_changed(
|
static inline void led_classdev_notify_brightness_hw_changed(
|
||||||
|
|
Loading…
Reference in New Issue