mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Changes for 5.11-rc1. Small cleanups/fixes mostly thanks to Marek,
nothing major made it in this time. -----BEGIN PGP SIGNATURE----- iF0EABECAB0WIQRPfPO7r0eAhk010v0w5/Bqldv68gUCX9oo1gAKCRAw5/Bqldv6 8nrCAKCZAnzevI69ivQujVm1yVpyt4sJKQCfRM/yEm+G+OFVV+IFUthfGictxFo= =ZcdU -----END PGP SIGNATURE----- Merge tag 'leds-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds Pull LED updates from Pavel Machek: "Small cleanups/fixes mostly thanks to Marek, nothing major made it in this time" * tag 'leds-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds: leds: turris-omnia: check for LED_COLOR_ID_RGB instead LED_COLOR_ID_MULTI leds: turris-omnia: fix checkpatch warning leds: turris-omnia: wrap to 80 columns leds: turris-omnia: use constants instead of macros for color command dt-bindings: leds: Convert pwm to yaml leds: lp50xx: Fix an error handling path in 'lp50xx_probe_dt()' leds: netxbig: add missing put_device() call in netxbig_leds_get_of_pdata() Documentation: leds: remove invalidated information
This commit is contained in:
commit
945433be36
@ -1,50 +0,0 @@
|
|||||||
LED connected to PWM
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible : should be "pwm-leds".
|
|
||||||
|
|
||||||
Each LED is represented as a sub-node of the pwm-leds device. Each
|
|
||||||
node's name represents the name of the corresponding LED.
|
|
||||||
|
|
||||||
LED sub-node properties:
|
|
||||||
- pwms : PWM property to point to the PWM device (phandle)/port (id) and to
|
|
||||||
specify the period time to be used: <&phandle id period_ns>;
|
|
||||||
- pwm-names : (optional) Name to be used by the PWM subsystem for the PWM device
|
|
||||||
For the pwms and pwm-names property please refer to:
|
|
||||||
Documentation/devicetree/bindings/pwm/pwm.txt
|
|
||||||
- max-brightness : Maximum brightness possible for the LED
|
|
||||||
- active-low : (optional) For PWMs where the LED is wired to supply
|
|
||||||
rather than ground.
|
|
||||||
- label : (optional)
|
|
||||||
see Documentation/devicetree/bindings/leds/common.txt
|
|
||||||
- linux,default-trigger : (optional)
|
|
||||||
see Documentation/devicetree/bindings/leds/common.txt
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
twl_pwm: pwm {
|
|
||||||
/* provides two PWMs (id 0, 1 for PWM1 and PWM2) */
|
|
||||||
compatible = "ti,twl6030-pwm";
|
|
||||||
#pwm-cells = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
twl_pwmled: pwmled {
|
|
||||||
/* provides one PWM (id 0 for Charing indicator LED) */
|
|
||||||
compatible = "ti,twl6030-pwmled";
|
|
||||||
#pwm-cells = <2>;
|
|
||||||
};
|
|
||||||
|
|
||||||
pwmleds {
|
|
||||||
compatible = "pwm-leds";
|
|
||||||
kpad {
|
|
||||||
label = "omap4::keypad";
|
|
||||||
pwms = <&twl_pwm 0 7812500>;
|
|
||||||
max-brightness = <127>;
|
|
||||||
};
|
|
||||||
|
|
||||||
charging {
|
|
||||||
label = "omap4:green:chrg";
|
|
||||||
pwms = <&twl_pwmled 0 7812500>;
|
|
||||||
max-brightness = <255>;
|
|
||||||
};
|
|
||||||
};
|
|
70
Documentation/devicetree/bindings/leds/leds-pwm.yaml
Normal file
70
Documentation/devicetree/bindings/leds/leds-pwm.yaml
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/leds/leds-pwm.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: LEDs connected to PWM
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Pavel Machek <pavel@ucw.cz>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Each LED is represented as a sub-node of the pwm-leds device. Each
|
||||||
|
node's name represents the name of the corresponding LED.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: pwm-leds
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^led(-[0-9a-f]+)?$":
|
||||||
|
type: object
|
||||||
|
|
||||||
|
$ref: common.yaml#
|
||||||
|
|
||||||
|
properties:
|
||||||
|
pwms:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
pwm-names: true
|
||||||
|
|
||||||
|
max-brightness:
|
||||||
|
description:
|
||||||
|
Maximum brightness possible for the LED
|
||||||
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
|
|
||||||
|
active-low:
|
||||||
|
description:
|
||||||
|
For PWMs where the LED is wired to supply rather than ground.
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
required:
|
||||||
|
- pwms
|
||||||
|
- max-brightness
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
|
||||||
|
#include <dt-bindings/leds/common.h>
|
||||||
|
|
||||||
|
led-controller {
|
||||||
|
compatible = "pwm-leds";
|
||||||
|
|
||||||
|
led-1 {
|
||||||
|
label = "omap4::keypad";
|
||||||
|
pwms = <&twl_pwm 0 7812500>;
|
||||||
|
max-brightness = <127>;
|
||||||
|
};
|
||||||
|
|
||||||
|
led-2 {
|
||||||
|
color = <LED_COLOR_ID_GREEN>;
|
||||||
|
function = LED_FUNCTION_CHARGING;
|
||||||
|
pwms = <&twl_pwmled 0 7812500>;
|
||||||
|
max-brightness = <255>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -177,13 +177,3 @@ The LED Trigger core cannot be a module as the simple trigger functions
|
|||||||
would cause nightmare dependency issues. I see this as a minor issue
|
would cause nightmare dependency issues. I see this as a minor issue
|
||||||
compared to the benefits the simple trigger functionality brings. The
|
compared to the benefits the simple trigger functionality brings. The
|
||||||
rest of the LED subsystem can be modular.
|
rest of the LED subsystem can be modular.
|
||||||
|
|
||||||
|
|
||||||
Future Development
|
|
||||||
==================
|
|
||||||
|
|
||||||
At the moment, a trigger can't be created specifically for a single LED.
|
|
||||||
There are a number of cases where a trigger might only be mappable to a
|
|
||||||
particular LED (ACPI?). The addition of triggers provided by the LED driver
|
|
||||||
should cover this option and be possible to add without breaking the
|
|
||||||
current interface.
|
|
||||||
|
@ -487,8 +487,10 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
|
|||||||
*/
|
*/
|
||||||
mc_led_info = devm_kcalloc(priv->dev, LP50XX_LEDS_PER_MODULE,
|
mc_led_info = devm_kcalloc(priv->dev, LP50XX_LEDS_PER_MODULE,
|
||||||
sizeof(*mc_led_info), GFP_KERNEL);
|
sizeof(*mc_led_info), GFP_KERNEL);
|
||||||
if (!mc_led_info)
|
if (!mc_led_info) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto child_out;
|
||||||
|
}
|
||||||
|
|
||||||
fwnode_for_each_child_node(child, led_node) {
|
fwnode_for_each_child_node(child, led_node) {
|
||||||
ret = fwnode_property_read_u32(led_node, "color",
|
ret = fwnode_property_read_u32(led_node, "color",
|
||||||
|
@ -448,31 +448,39 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
|
|||||||
gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL);
|
gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL);
|
||||||
if (!gpio_ext) {
|
if (!gpio_ext) {
|
||||||
of_node_put(gpio_ext_np);
|
of_node_put(gpio_ext_np);
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto put_device;
|
||||||
}
|
}
|
||||||
ret = netxbig_gpio_ext_get(dev, gpio_ext_dev, gpio_ext);
|
ret = netxbig_gpio_ext_get(dev, gpio_ext_dev, gpio_ext);
|
||||||
of_node_put(gpio_ext_np);
|
of_node_put(gpio_ext_np);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto put_device;
|
||||||
pdata->gpio_ext = gpio_ext;
|
pdata->gpio_ext = gpio_ext;
|
||||||
|
|
||||||
/* Timers (optional) */
|
/* Timers (optional) */
|
||||||
ret = of_property_count_u32_elems(np, "timers");
|
ret = of_property_count_u32_elems(np, "timers");
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
if (ret % 3)
|
if (ret % 3) {
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto put_device;
|
||||||
|
}
|
||||||
|
|
||||||
num_timers = ret / 3;
|
num_timers = ret / 3;
|
||||||
timers = devm_kcalloc(dev, num_timers, sizeof(*timers),
|
timers = devm_kcalloc(dev, num_timers, sizeof(*timers),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!timers)
|
if (!timers) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto put_device;
|
||||||
|
}
|
||||||
for (i = 0; i < num_timers; i++) {
|
for (i = 0; i < num_timers; i++) {
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
of_property_read_u32_index(np, "timers", 3 * i,
|
of_property_read_u32_index(np, "timers", 3 * i,
|
||||||
&timers[i].mode);
|
&timers[i].mode);
|
||||||
if (timers[i].mode >= NETXBIG_LED_MODE_NUM)
|
if (timers[i].mode >= NETXBIG_LED_MODE_NUM) {
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto put_device;
|
||||||
|
}
|
||||||
of_property_read_u32_index(np, "timers",
|
of_property_read_u32_index(np, "timers",
|
||||||
3 * i + 1, &tmp);
|
3 * i + 1, &tmp);
|
||||||
timers[i].delay_on = tmp;
|
timers[i].delay_on = tmp;
|
||||||
@ -488,12 +496,15 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
|
|||||||
num_leds = of_get_available_child_count(np);
|
num_leds = of_get_available_child_count(np);
|
||||||
if (!num_leds) {
|
if (!num_leds) {
|
||||||
dev_err(dev, "No LED subnodes found in DT\n");
|
dev_err(dev, "No LED subnodes found in DT\n");
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto put_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
leds = devm_kcalloc(dev, num_leds, sizeof(*leds), GFP_KERNEL);
|
leds = devm_kcalloc(dev, num_leds, sizeof(*leds), GFP_KERNEL);
|
||||||
if (!leds)
|
if (!leds) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto put_device;
|
||||||
|
}
|
||||||
|
|
||||||
led = leds;
|
led = leds;
|
||||||
for_each_available_child_of_node(np, child) {
|
for_each_available_child_of_node(np, child) {
|
||||||
@ -574,6 +585,8 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
|
|||||||
|
|
||||||
err_node_put:
|
err_node_put:
|
||||||
of_node_put(child);
|
of_node_put(child);
|
||||||
|
put_device:
|
||||||
|
put_device(gpio_ext_dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,14 +27,6 @@
|
|||||||
#define CMD_LED_SET_BRIGHTNESS 7
|
#define CMD_LED_SET_BRIGHTNESS 7
|
||||||
#define CMD_LED_GET_BRIGHTNESS 8
|
#define CMD_LED_GET_BRIGHTNESS 8
|
||||||
|
|
||||||
#define OMNIA_CMD 0
|
|
||||||
|
|
||||||
#define OMNIA_CMD_LED_COLOR_LED 1
|
|
||||||
#define OMNIA_CMD_LED_COLOR_R 2
|
|
||||||
#define OMNIA_CMD_LED_COLOR_G 3
|
|
||||||
#define OMNIA_CMD_LED_COLOR_B 4
|
|
||||||
#define OMNIA_CMD_LED_COLOR_LEN 5
|
|
||||||
|
|
||||||
struct omnia_led {
|
struct omnia_led {
|
||||||
struct led_classdev_mc mc_cdev;
|
struct led_classdev_mc mc_cdev;
|
||||||
struct mc_subled subled_info[OMNIA_LED_NUM_CHANNELS];
|
struct mc_subled subled_info[OMNIA_LED_NUM_CHANNELS];
|
||||||
@ -55,21 +47,21 @@ static int omnia_led_brightness_set_blocking(struct led_classdev *cdev,
|
|||||||
struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
|
struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
|
||||||
struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent);
|
struct omnia_leds *leds = dev_get_drvdata(cdev->dev->parent);
|
||||||
struct omnia_led *led = to_omnia_led(mc_cdev);
|
struct omnia_led *led = to_omnia_led(mc_cdev);
|
||||||
u8 buf[OMNIA_CMD_LED_COLOR_LEN], state;
|
u8 buf[5], state;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&leds->lock);
|
mutex_lock(&leds->lock);
|
||||||
|
|
||||||
led_mc_calc_color_components(&led->mc_cdev, brightness);
|
led_mc_calc_color_components(&led->mc_cdev, brightness);
|
||||||
|
|
||||||
buf[OMNIA_CMD] = CMD_LED_COLOR;
|
buf[0] = CMD_LED_COLOR;
|
||||||
buf[OMNIA_CMD_LED_COLOR_LED] = led->reg;
|
buf[1] = led->reg;
|
||||||
buf[OMNIA_CMD_LED_COLOR_R] = mc_cdev->subled_info[0].brightness;
|
buf[2] = mc_cdev->subled_info[0].brightness;
|
||||||
buf[OMNIA_CMD_LED_COLOR_G] = mc_cdev->subled_info[1].brightness;
|
buf[3] = mc_cdev->subled_info[1].brightness;
|
||||||
buf[OMNIA_CMD_LED_COLOR_B] = mc_cdev->subled_info[2].brightness;
|
buf[4] = mc_cdev->subled_info[2].brightness;
|
||||||
|
|
||||||
state = CMD_LED_STATE_LED(led->reg);
|
state = CMD_LED_STATE_LED(led->reg);
|
||||||
if (buf[OMNIA_CMD_LED_COLOR_R] || buf[OMNIA_CMD_LED_COLOR_G] || buf[OMNIA_CMD_LED_COLOR_B])
|
if (buf[2] || buf[3] || buf[4])
|
||||||
state |= CMD_LED_STATE_ON;
|
state |= CMD_LED_STATE_ON;
|
||||||
|
|
||||||
ret = i2c_smbus_write_byte_data(leds->client, CMD_LED_STATE, state);
|
ret = i2c_smbus_write_byte_data(leds->client, CMD_LED_STATE, state);
|
||||||
@ -98,9 +90,9 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "color", &color);
|
ret = of_property_read_u32(np, "color", &color);
|
||||||
if (ret || color != LED_COLOR_ID_MULTI) {
|
if (ret || color != LED_COLOR_ID_RGB) {
|
||||||
dev_warn(dev,
|
dev_warn(dev,
|
||||||
"Node %pOF: must contain 'color' property with value LED_COLOR_ID_MULTI\n",
|
"Node %pOF: must contain 'color' property with value LED_COLOR_ID_RGB\n",
|
||||||
np);
|
np);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -126,18 +118,21 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led,
|
|||||||
CMD_LED_MODE_LED(led->reg) |
|
CMD_LED_MODE_LED(led->reg) |
|
||||||
CMD_LED_MODE_USER);
|
CMD_LED_MODE_USER);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "Cannot set LED %pOF to software mode: %i\n", np, ret);
|
dev_err(dev, "Cannot set LED %pOF to software mode: %i\n", np,
|
||||||
|
ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable the LED */
|
/* disable the LED */
|
||||||
ret = i2c_smbus_write_byte_data(client, CMD_LED_STATE, CMD_LED_STATE_LED(led->reg));
|
ret = i2c_smbus_write_byte_data(client, CMD_LED_STATE,
|
||||||
|
CMD_LED_STATE_LED(led->reg));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "Cannot set LED %pOF brightness: %i\n", np, ret);
|
dev_err(dev, "Cannot set LED %pOF brightness: %i\n", np, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_led_classdev_multicolor_register_ext(dev, &led->mc_cdev, &init_data);
|
ret = devm_led_classdev_multicolor_register_ext(dev, &led->mc_cdev,
|
||||||
|
&init_data);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "Cannot register LED %pOF: %i\n", np, ret);
|
dev_err(dev, "Cannot register LED %pOF: %i\n", np, ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -157,7 +152,8 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led,
|
|||||||
* file lives in the device directory of the LED controller, not an individual
|
* file lives in the device directory of the LED controller, not an individual
|
||||||
* LED, so it should not confuse users.
|
* LED, so it should not confuse users.
|
||||||
*/
|
*/
|
||||||
static ssize_t brightness_show(struct device *dev, struct device_attribute *a, char *buf)
|
static ssize_t brightness_show(struct device *dev, struct device_attribute *a,
|
||||||
|
char *buf)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct omnia_leds *leds = i2c_get_clientdata(client);
|
struct omnia_leds *leds = i2c_get_clientdata(client);
|
||||||
@ -173,22 +169,23 @@ static ssize_t brightness_show(struct device *dev, struct device_attribute *a, c
|
|||||||
return sprintf(buf, "%d\n", ret);
|
return sprintf(buf, "%d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t brightness_store(struct device *dev, struct device_attribute *a, const char *buf,
|
static ssize_t brightness_store(struct device *dev, struct device_attribute *a,
|
||||||
size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct omnia_leds *leds = i2c_get_clientdata(client);
|
struct omnia_leds *leds = i2c_get_clientdata(client);
|
||||||
unsigned int brightness;
|
unsigned long brightness;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (sscanf(buf, "%u", &brightness) != 1)
|
if (kstrtoul(buf, 10, &brightness))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (brightness > 100)
|
if (brightness > 100)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&leds->lock);
|
mutex_lock(&leds->lock);
|
||||||
ret = i2c_smbus_write_byte_data(client, CMD_LED_SET_BRIGHTNESS, (u8) brightness);
|
ret = i2c_smbus_write_byte_data(client, CMD_LED_SET_BRIGHTNESS,
|
||||||
|
(u8)brightness);
|
||||||
mutex_unlock(&leds->lock);
|
mutex_unlock(&leds->lock);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -250,18 +247,18 @@ static int omnia_leds_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
static int omnia_leds_remove(struct i2c_client *client)
|
static int omnia_leds_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
u8 buf[OMNIA_CMD_LED_COLOR_LEN];
|
u8 buf[5];
|
||||||
|
|
||||||
/* put all LEDs into default (HW triggered) mode */
|
/* put all LEDs into default (HW triggered) mode */
|
||||||
i2c_smbus_write_byte_data(client, CMD_LED_MODE,
|
i2c_smbus_write_byte_data(client, CMD_LED_MODE,
|
||||||
CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
|
CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
|
||||||
|
|
||||||
/* set all LEDs color to [255, 255, 255] */
|
/* set all LEDs color to [255, 255, 255] */
|
||||||
buf[OMNIA_CMD] = CMD_LED_COLOR;
|
buf[0] = CMD_LED_COLOR;
|
||||||
buf[OMNIA_CMD_LED_COLOR_LED] = OMNIA_BOARD_LEDS;
|
buf[1] = OMNIA_BOARD_LEDS;
|
||||||
buf[OMNIA_CMD_LED_COLOR_R] = 255;
|
buf[2] = 255;
|
||||||
buf[OMNIA_CMD_LED_COLOR_G] = 255;
|
buf[3] = 255;
|
||||||
buf[OMNIA_CMD_LED_COLOR_B] = 255;
|
buf[4] = 255;
|
||||||
|
|
||||||
i2c_master_send(client, buf, 5);
|
i2c_master_send(client, buf, 5);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user