1
0
Fork 0

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()
  ...
alistair/sunxi64-5.5-dsi
Linus Torvalds 2019-12-01 16:09:28 -08:00
commit 304220b56e
20 changed files with 858 additions and 207 deletions

View File

@ -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

View File

@ -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>;
};
};

View File

@ -17,7 +17,7 @@ if NEW_LEDS
config LEDS_CLASS
tristate "LED Class Support"
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.
config LEDS_CLASS_FLASH
@ -35,7 +35,7 @@ config LEDS_BRIGHTNESS_HW_CHANGED
depends on LEDS_CLASS
help
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.
@ -132,6 +132,19 @@ config LEDS_CR0014114
To compile this driver as a module, choose M here: the module
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
tristate "LCD Backlight driver for LM3530"
depends on LEDS_CLASS

View File

@ -89,6 +89,7 @@ obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o
# LED SPI Drivers
obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
obj-$(CONFIG_LEDS_EL15203000) += leds-el15203000.o
# LED Userspace Drivers
obj-$(CONFIG_LEDS_USER) += uleds.o

View File

@ -327,6 +327,56 @@ void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
}
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)
{
u32 v, offset;

View File

@ -74,13 +74,13 @@ static ssize_t max_brightness_show(struct device *dev,
static DEVICE_ATTR_RO(max_brightness);
#ifdef CONFIG_LEDS_TRIGGERS
static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
static struct attribute *led_trigger_attrs[] = {
&dev_attr_trigger.attr,
static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0);
static struct bin_attribute *led_trigger_bin_attrs[] = {
&bin_attr_trigger,
NULL,
};
static const struct attribute_group led_trigger_group = {
.attrs = led_trigger_attrs,
.bin_attrs = led_trigger_bin_attrs,
};
#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)
{
struct led_cdev **p = res;
struct led_classdev **p = res;
if (WARN_ON(!p || !*p))
return 0;

View File

@ -16,6 +16,7 @@
#include <linux/rwsem.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include "leds.h"
/*
@ -26,9 +27,11 @@ LIST_HEAD(trigger_list);
/* Used by LED Class */
ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
const char *buf, 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)
{
struct device *dev = kobj_to_dev(kobj);
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct led_trigger *trig;
int ret = count;
@ -64,39 +67,82 @@ unlock:
mutex_unlock(&led_cdev->led_access);
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,
char *buf)
__printf(3, 4)
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;
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(&led_cdev->trigger_lock);
if (!led_cdev->trigger)
len += scnprintf(buf+len, PAGE_SIZE - len, "[none] ");
else
len += scnprintf(buf+len, PAGE_SIZE - len, "none ");
list_for_each_entry(trig, &trigger_list, next_trig) {
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(NULL, 0, led_cdev);
data = kvmalloc(len + 1, GFP_KERNEL);
if (!data) {
up_read(&led_cdev->trigger_lock);
up_read(&triggers_list_lock);
return -ENOMEM;
}
len = led_trigger_format(data, len + 1, led_cdev);
up_read(&led_cdev->trigger_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;
}
EXPORT_SYMBOL_GPL(led_trigger_show);
EXPORT_SYMBOL_GPL(led_trigger_read);
/* Caller must ensure led_cdev->trigger_lock held */
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)

View File

@ -305,6 +305,13 @@ static int an30259a_probe(struct i2c_client *client)
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++) {
struct led_init_data init_data = {};

View File

@ -346,16 +346,11 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
struct resource *mem_r;
void __iomem *mem;
spinlock_t *lock; /* memory lock */
unsigned long val, *blink_leds, *blink_delay;
mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_r)
return -EINVAL;
mem = devm_ioremap_resource(dev, mem_r);
mem = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem))
return PTR_ERR(mem);

View File

@ -151,17 +151,12 @@ static int bcm6358_leds_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
struct resource *mem_r;
void __iomem *mem;
spinlock_t *lock; /* memory lock */
unsigned long val;
u32 clk_div;
mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_r)
return -EINVAL;
mem = devm_ioremap_resource(dev, mem_r);
mem = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem))
return PTR_ERR(mem);

View File

@ -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");

View File

@ -350,8 +350,7 @@ static int lm3601x_register_leds(struct lm3601x_led *led,
init_data.devicename = led->client->name;
init_data.default_label = (led->led_mode == LM3601X_LED_TORCH) ?
"torch" : "infrared";
return led_classdev_flash_register_ext(&led->client->dev,
return devm_led_classdev_flash_register_ext(&led->client->dev,
&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);
led_classdev_flash_unregister(&led->fled_cdev);
mutex_destroy(&led->lock);
return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG,

View File

@ -174,19 +174,20 @@ static int lm3692x_brightness_set(struct led_classdev *led_cdev,
ret = lm3692x_fault_check(led);
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;
}
ret = regmap_write(led->regmap, LM3692X_BRT_MSB, brt_val);
if (ret) {
dev_err(&led->client->dev, "Cannot write MSB\n");
dev_err(&led->client->dev, "Cannot write MSB: %d\n", ret);
goto out;
}
ret = regmap_write(led->regmap, LM3692X_BRT_LSB, led_brightness_lsb);
if (ret) {
dev_err(&led->client->dev, "Cannot write LSB\n");
dev_err(&led->client->dev, "Cannot write LSB: %d\n", ret);
goto out;
}
out:
@ -197,13 +198,13 @@ out:
static int lm3692x_init(struct lm3692x_led *led)
{
int enable_state;
int ret;
int ret, reg_ret;
if (led->regulator) {
ret = regulator_enable(led->regulator);
if (ret) {
dev_err(&led->client->dev,
"Failed to enable regulator\n");
"Failed to enable regulator: %d\n", ret);
return ret;
}
}
@ -213,7 +214,8 @@ static int lm3692x_init(struct lm3692x_led *led)
ret = lm3692x_fault_check(led);
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;
}
@ -248,9 +250,9 @@ static int lm3692x_init(struct lm3692x_led *led)
goto out;
ret = regmap_write(led->regmap, LM3692X_BOOST_CTRL,
LM3692X_BRHT_MODE_RAMP_MULTI |
LM3692X_BL_ADJ_POL |
LM3692X_RAMP_RATE_250us);
LM3692X_BOOST_SW_1MHZ |
LM3692X_BOOST_SW_NO_SHIFT |
LM3692X_OCP_PROT_1_5A);
if (ret)
goto out;
@ -267,7 +269,7 @@ static int lm3692x_init(struct lm3692x_led *led)
goto out;
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)
goto out;
@ -311,14 +313,15 @@ out:
gpiod_direction_output(led->enable_gpio, 0);
if (led->regulator) {
ret = regulator_disable(led->regulator);
if (ret)
reg_ret = regulator_disable(led->regulator);
if (reg_ret)
dev_err(&led->client->dev,
"Failed to disable regulator\n");
"Failed to disable regulator: %d\n", reg_ret);
}
return ret;
}
static int lm3692x_probe_dt(struct lm3692x_led *led)
{
struct fwnode_handle *child = NULL;
@ -334,9 +337,18 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
return ret;
}
led->regulator = devm_regulator_get(&led->client->dev, "vled");
if (IS_ERR(led->regulator))
led->regulator = devm_regulator_get_optional(&led->client->dev, "vled");
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;
}
child = device_get_next_child_node(&led->client->dev, 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);
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;
}
@ -420,7 +433,7 @@ static int lm3692x_remove(struct i2c_client *client)
ret = regulator_disable(led->regulator);
if (ret)
dev_err(&led->client->dev,
"Failed to disable regulator\n");
"Failed to disable regulator: %d\n", ret);
}
mutex_destroy(&led->lock);

View File

@ -228,8 +228,8 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
brightness = LED_OFF;
led_data->base_color = MLXREG_LED_GREEN_SOLID;
}
sprintf(led_data->led_cdev_name, "%s:%s", "mlxreg",
data->label);
snprintf(led_data->led_cdev_name, sizeof(led_data->led_cdev_name),
"mlxreg:%s", data->label);
led_cdev->name = led_data->led_cdev_name;
led_cdev->brightness = brightness;
led_cdev->max_brightness = LED_ON;

View File

@ -467,16 +467,11 @@ pca9532_of_populate_pdata(struct device *dev, struct device_node *np)
{
struct pca9532_platform_data *pdata;
struct device_node *child;
const struct of_device_id *match;
int devid, maxleds;
int i = 0;
const char *state;
match = of_match_device(of_pca9532_leds_match, dev);
if (!match)
return ERR_PTR(-ENODEV);
devid = (int)(uintptr_t)match->data;
devid = (int)(uintptr_t)of_device_get_match_data(dev);
maxleds = pca9532_chip_info_tbl[devid].num_leds;
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)
{
int devid;
const struct of_device_id *of_id;
struct pca9532_data *data = i2c_get_clientdata(client);
struct pca9532_platform_data *pca9532_pdata =
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");
return -EINVAL;
}
of_id = of_match_device(of_pca9532_leds_match,
&client->dev);
if (unlikely(!of_id))
return -EINVAL;
devid = (int)(uintptr_t) of_id->data;
devid = (int)(uintptr_t)of_device_get_match_data(&client->dev);
} else {
devid = id->driver_data;
}

View File

@ -13,6 +13,7 @@
#include <linux/slab.h>
#define TLC591XX_MAX_LEDS 16
#define TLC591XX_MAX_BRIGHTNESS 256
#define TLC591XX_REG_MODE1 0x00
#define MODE1_RESPON_ADDR_MASK 0xF0
@ -112,11 +113,11 @@ tlc591xx_brightness_set(struct led_classdev *led_cdev,
struct tlc591xx_priv *priv = led->priv;
int err;
switch (brightness) {
switch ((int)brightness) {
case 0:
err = tlc591xx_set_ledout(priv, led, LEDOUT_OFF);
break;
case LED_FULL:
case TLC591XX_MAX_BRIGHTNESS:
err = tlc591xx_set_ledout(priv, led, LEDOUT_ON);
break;
default:
@ -128,51 +129,6 @@ tlc591xx_brightness_set(struct led_classdev *led_cdev,
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 = {
.reg_bits = 8,
.val_bits = 8,
@ -225,7 +181,16 @@ tlc591xx_probe(struct i2c_client *client,
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) {
struct tlc591xx_led *led;
struct led_init_data init_data = {};
init_data.fwnode = of_fwnode_handle(child);
err = of_property_read_u32(child, "reg", &reg);
if (err) {
of_node_put(child);
@ -236,22 +201,24 @@ tlc591xx_probe(struct i2c_client *client,
of_node_put(child);
return -EINVAL;
}
priv->leds[reg].active = true;
priv->leds[reg].ldev.name =
of_get_property(child, "label", NULL) ? : child->name;
priv->leds[reg].ldev.default_trigger =
led = &priv->leds[reg];
led->active = true;
led->ldev.default_trigger =
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;
}
@ -268,7 +235,6 @@ static struct i2c_driver tlc591xx_driver = {
.of_match_table = of_match_ptr(of_tlc591xx_leds_match),
},
.probe = tlc591xx_probe,
.remove = tlc591xx_remove,
.id_table = tlc591xx_id,
};

View File

@ -23,6 +23,12 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev,
enum led_brightness value);
void led_set_brightness_nosleep(struct led_classdev *led_cdev,
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 list_head leds_list;

View File

@ -302,10 +302,12 @@ static int netdev_trig_notify(struct notifier_block *nb,
container_of(nb, struct led_netdev_data, notifier);
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;
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))))
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);
switch (evt) {
case NETDEV_CHANGENAME:
case NETDEV_REGISTER:
if (trigger_data->net_dev)
dev_put(trigger_data->net_dev);

View File

@ -94,12 +94,15 @@ static inline struct led_classdev_flash *lcdev_to_flcdev(
*
* Returns: 0 on success or negative error value on failure
*/
extern int led_classdev_flash_register_ext(struct device *parent,
struct led_classdev_flash *fled_cdev,
struct led_init_data *init_data);
int led_classdev_flash_register_ext(struct device *parent,
struct led_classdev_flash *fled_cdev,
struct led_init_data *init_data);
#define led_classdev_flash_register(parent, fled_cdev) \
led_classdev_flash_register_ext(parent, fled_cdev, NULL)
static inline int led_classdev_flash_register(struct device *parent,
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
@ -108,7 +111,21 @@ extern int led_classdev_flash_register_ext(struct device *parent,
*
* 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
@ -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
*/
extern int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
u32 brightness);
int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
u32 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
*/
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
@ -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
*/
extern int led_set_flash_timeout(struct led_classdev_flash *fled_cdev,
u32 timeout);
int led_set_flash_timeout(struct led_classdev_flash *fled_cdev, u32 timeout);
/**
* 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
*/
extern int led_get_flash_fault(struct led_classdev_flash *fled_cdev,
u32 *fault);
int led_get_flash_fault(struct led_classdev_flash *fled_cdev, u32 *fault);
#endif /* __LINUX_FLASH_LEDS_H_INCLUDED */

View File

@ -161,7 +161,7 @@ struct led_classdev {
*
* 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_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);
}
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_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);
}
extern void led_classdev_unregister(struct led_classdev *led_cdev);
extern void devm_led_classdev_unregister(struct device *parent,
struct led_classdev *led_cdev);
extern void led_classdev_suspend(struct led_classdev *led_cdev);
extern void led_classdev_resume(struct led_classdev *led_cdev);
void led_classdev_unregister(struct led_classdev *led_cdev);
void devm_led_classdev_unregister(struct device *parent,
struct led_classdev *led_cdev);
void led_classdev_suspend(struct led_classdev *led_cdev);
void led_classdev_resume(struct led_classdev *led_cdev);
/**
* 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,
* use led_classdev_brightness_set() instead.
*/
extern void led_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off);
void led_blink_set(struct led_classdev *led_cdev, unsigned long *delay_on,
unsigned long *delay_off);
/**
* led_blink_set_oneshot - do a oneshot software blink
* @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
* delay_on and leave the led on after the on-off cycle.
*/
extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off,
int invert);
void led_blink_set_oneshot(struct led_classdev *led_cdev,
unsigned long *delay_on, unsigned long *delay_off,
int invert);
/**
* led_set_brightness - set LED brightness
* @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
* hardware doesn't. This function is guaranteed not to sleep.
*/
extern void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness);
void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness);
/**
* 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
*/
extern int led_set_brightness_sync(struct led_classdev *led_cdev,
enum led_brightness value);
int led_set_brightness_sync(struct led_classdev *led_cdev,
enum led_brightness value);
/**
* 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
*/
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
@ -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
* or NULL. Caller is responsible for kfree().
*/
extern u32 *led_get_default_pattern(struct led_classdev *led_cdev,
unsigned int *size);
u32 *led_get_default_pattern(struct led_classdev *led_cdev, unsigned int *size);
/**
* 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.
*/
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
@ -296,7 +293,7 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
*
* 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
@ -310,8 +307,8 @@ extern void led_sysfs_enable(struct led_classdev *led_cdev);
*
* Returns: 0 on success or negative error value on failure
*/
extern int led_compose_name(struct device *dev, struct led_init_data *init_data,
char *led_classdev_name);
int led_compose_name(struct device *dev, struct led_init_data *init_data,
char *led_classdev_name);
/**
* 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_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 */
extern int led_trigger_register(struct led_trigger *trigger);
extern void led_trigger_unregister(struct led_trigger *trigger);
extern int devm_led_trigger_register(struct device *dev,
int led_trigger_register(struct led_trigger *trigger);
void led_trigger_unregister(struct led_trigger *trigger);
int devm_led_trigger_register(struct device *dev,
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);
extern void led_trigger_unregister_simple(struct led_trigger *trigger);
extern void led_trigger_event(struct led_trigger *trigger,
enum led_brightness event);
extern void led_trigger_blink(struct led_trigger *trigger,
unsigned long *delay_on,
unsigned long *delay_off);
extern void led_trigger_blink_oneshot(struct led_trigger *trigger,
unsigned long *delay_on,
unsigned long *delay_off,
int invert);
extern void led_trigger_set_default(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);
void led_trigger_unregister_simple(struct led_trigger *trigger);
void led_trigger_event(struct led_trigger *trigger, enum led_brightness event);
void led_trigger_blink(struct led_trigger *trigger, unsigned long *delay_on,
unsigned long *delay_off);
void led_trigger_blink_oneshot(struct led_trigger *trigger,
unsigned long *delay_on,
unsigned long *delay_off,
int invert);
void led_trigger_set_default(struct led_classdev *led_cdev);
int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger);
void led_trigger_remove(struct led_classdev *led_cdev);
static inline void led_set_trigger_data(struct led_classdev *led_cdev,
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
* allocated name.
*/
extern void led_trigger_rename_static(const char *name,
struct led_trigger *trig);
void led_trigger_rename_static(const char *name, struct led_trigger *trig);
#define module_led_trigger(__led_trigger) \
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 */
#ifdef CONFIG_LEDS_TRIGGER_DISK
extern void ledtrig_disk_activity(bool write);
void ledtrig_disk_activity(bool write);
#else
static inline void ledtrig_disk_activity(bool write) {}
#endif
#ifdef CONFIG_LEDS_TRIGGER_MTD
extern void ledtrig_mtd_activity(void);
void ledtrig_mtd_activity(void);
#else
static inline void ledtrig_mtd_activity(void) {}
#endif
#if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE)
extern void ledtrig_flash_ctrl(bool on);
extern void ledtrig_torch_ctrl(bool on);
void ledtrig_flash_ctrl(bool on);
void ledtrig_torch_ctrl(bool on);
#else
static inline void ledtrig_flash_ctrl(bool on) {}
static inline void ledtrig_torch_ctrl(bool on) {}
@ -550,7 +538,7 @@ enum cpu_led_event {
CPU_LED_HALTED, /* Machine shutdown */
};
#ifdef CONFIG_LEDS_TRIGGER_CPU
extern void ledtrig_cpu(enum cpu_led_event evt);
void ledtrig_cpu(enum cpu_led_event evt);
#else
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
#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);
#else
static inline void led_classdev_notify_brightness_hw_changed(