LED class device naming pattern included devicename section, which had
unpleasant effect of varying userspace interface dependent on underlaying
hardware. Moreover, this information was redundant in the LED name, since
the LED controller name could have been obtained from sysfs device group
This patch set introduces a led_compose_name() function in the LED core,
which unifies and simplifies LED class device name composition. This
change is accompanied by the improvements in the common LED DT bindings
where two new properties are introduced: "function" and "color" . The two
deprecate the old "label" property which was leaving too much room for
interpretation, leading to inconsistent LED naming.
There are also changes in LED DT node naming, which are in line with
DT maintainer's request from [0].
Since some DT LED naming unification, related to not including devicename
section in "label" DT property, is being requested during reviews of new
LED class drivers for almost a year now, then those drivers are the first
candidates for optimalization and the first users of the new
led_compose_name() API. The modifications were tested with Qemu,
by stubbing the driver internals where hardware interaction was needed
for proper probing.
Thanks,
Jacek Anaszewski
[0] https://lore.kernel.org/patchwork/patch/858993/
Jacek Anaszewski (24):
leds: class: Improve LED and LED flash class registration API
leds: core: Add support for composing LED class device names
leds: dt-bindings: Add LED_FUNCTION definitions
dt-bindings: leds: Add function and color properties
dt-bindings: sc27xx-blt: Add function and color properties
leds: sc27xx-blt: Use led_compose_name()
dt-bindings: lt3593: Add function and color properties
leds: lt3593: Use led_compose_name()
dt-bindings: lp8860: Add function and color properties
leds: lp8860: Use led_compose_name()
dt-bindings: lm3692x: Add function and color properties
leds: lm3692x: Use led_compose_name()
dt-bindings: lm36010: Add function and color properties
leds: lm3601x: Use led_compose_name()
dt-bindings: cr0014114: Add function and color properties
leds: cr0014114: Use led_compose_name()
dt-bindings: aat1290: Add function and color properties
leds: aat1290: Use led_compose_name()
dt-bindings: as3645a: Add function and color properties
leds: as3645a: Use led_compose_name()
dt-bindings: leds-gpio: Add function and color properties
leds: gpio: Use led_compose_name()
dt-bindings: an30259a: Add function and color properties
leds: an30259a: Use led_compose_name()
.../devicetree/bindings/leds/ams,as3645a.txt | 22 +++--
Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++--
.../devicetree/bindings/leds/leds-aat1290.txt | 12 ++-
.../devicetree/bindings/leds/leds-an30259a.txt | 22 ++++-
.../devicetree/bindings/leds/leds-cr0014114.txt | 26 ++++--
.../devicetree/bindings/leds/leds-gpio.txt | 22 +++--
.../devicetree/bindings/leds/leds-lm3601x.txt | 10 +-
.../devicetree/bindings/leds/leds-lm3692x.txt | 9 +-
.../devicetree/bindings/leds/leds-lp8860.txt | 9 +-
.../devicetree/bindings/leds/leds-lt3593.txt | 11 ++-
.../devicetree/bindings/leds/leds-sc27xx-bltc.txt | 10 +-
Documentation/leds/leds-class.txt | 2 +-
drivers/leds/led-class-flash.c | 9 +-
drivers/leds/led-class.c | 34 ++++---
drivers/leds/led-core.c | 71 +++++++++++++++
drivers/leds/leds-aat1290.c | 17 ++--
drivers/leds/leds-an30259a.c | 26 +++---
drivers/leds/leds-as3645a.c | 65 ++++++-------
drivers/leds/leds-cr0014114.c | 30 ++----
drivers/leds/leds-gpio.c | 27 +++---
drivers/leds/leds-lm3601x.c | 45 ++++-----
drivers/leds/leds-lm3692x.c | 39 ++++----
drivers/leds/leds-lp8860.c | 38 ++++----
drivers/leds/leds-lt3593.c | 19 ++--
drivers/leds/leds-sc27xx-bltc.c | 23 ++---
include/dt-bindings/leds/functions.h | 101 +++++++++++++++++++++
include/linux/led-class-flash.h | 13 ++-
include/linux/leds.h | 61 +++++++++++--
28 files changed, 571 insertions(+), 254 deletions(-)
create mode 100644 include/dt-bindings/leds/functions.h
--
2.1.4
Add common LED function definitions for use in Device Tree.
The function names were extracted from existing dts files
after eliminating oddities.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Baolin Wang <[email protected]>
Cc: Daniel Mack <[email protected]>
Cc: Dan Murphy <[email protected]>
Cc: Linus Walleij <[email protected]>
Cc: Oleh Kravchenko <[email protected]>
Cc: Sakari Ailus <[email protected]>
Cc: Simon Shields <[email protected]>
Cc: Xiaotong Lu <[email protected]>
---
include/dt-bindings/leds/functions.h | 101 +++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
create mode 100644 include/dt-bindings/leds/functions.h
diff --git a/include/dt-bindings/leds/functions.h b/include/dt-bindings/leds/functions.h
new file mode 100644
index 0000000..3f94e09
--- /dev/null
+++ b/include/dt-bindings/leds/functions.h
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define LED_FUNCTION_2G "2g"
+#define LED_FUNCTION_ACTIVITY "activity"
+#define LED_FUNCTION_ADSL "adsl"
+#define LED_FUNCTION_ALARM "alarm"
+#define LED_FUNCTION_ALIVE "alive"
+#define LED_FUNCTION_ALL "all"
+#define LED_FUNCTION_APP "app"
+#define LED_FUNCTION_AUX "aux"
+#define LED_FUNCTION_BACKUP "backup"
+#define LED_FUNCTION_BACKLIGHT "backlight"
+#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
+#define LED_FUNCTION_BEEP "beep"
+#define LED_FUNCTION_BLUETOOTH "bluetooth"
+#define LED_FUNCTION_BOOT "boot"
+#define LED_FUNCTION_BOTTOM "bottom"
+#define LED_FUNCTION_BRICK_STATUS "brick-status"
+#define LED_FUNCTION_CEL "cel"
+#define LED_FUNCTION_CEL_PWR "cel-pwr"
+#define LED_FUNCTION_CEL_RESET "cel-reset"
+#define LED_FUNCTION_CHRG "chrg"
+#define LED_FUNCTION_COM "com"
+#define LED_FUNCTION_COPY "copy"
+#define LED_FUNCTION_CPU "cpu"
+#define LED_FUNCTION_DEBUG "debug"
+#define LED_FUNCTION_DIA "dia"
+#define LED_FUNCTION_DISK "disk"
+#define LED_FUNCTION_DISPLAY_CLUSTER "display_cluster"
+#define LED_FUNCTION_DOWN "down"
+#define LED_FUNCTION_DSL "dsl"
+#define LED_FUNCTION_ENOCEAN "enocean"
+#define LED_FUNCTION_ENTER "enter"
+#define LED_FUNCTION_ERROR "error"
+#define LED_FUNCTION_ESATA "esata"
+#define LED_FUNCTION_ETHERNET_STATUS "ethernet-status"
+#define LED_FUNCTION_FAIL "fail"
+#define LED_FUNCTION_FAULT "fault"
+#define LED_FUNCTION_FLASH "flash"
+#define LED_FUNCTION_FRONT "front"
+#define LED_FUNCTION_FUNC "func"
+#define LED_FUNCTION_GPIO "gpio"
+#define LED_FUNCTION_GSM "gsm"
+#define LED_FUNCTION_HD "hd"
+#define LED_FUNCTION_HDD "hdd"
+#define LED_FUNCTION_HDDERR "hdderr"
+#define LED_FUNCTION_HEALTH "health"
+#define LED_FUNCTION_HEARTBEAT "heartbeat"
+#define LED_FUNCTION_HOME "home"
+#define LED_FUNCTION_INDICATOR "indicator"
+#define LED_FUNCTION_INET "inet"
+#define LED_FUNCTION_INFO "info"
+#define LED_FUNCTION_INTERNET "internet"
+#define LED_FUNCTION_KEYPAD "keypad"
+#define LED_FUNCTION_LAN "lan"
+#define LED_FUNCTION_LEFT "left"
+#define LED_FUNCTION_LIVE "live"
+#define LED_FUNCTION_MICROSD "microsd"
+#define LED_FUNCTION_MISC "misc"
+#define LED_FUNCTION_MMC "mmc"
+#define LED_FUNCTION_NAND "nand"
+#define LED_FUNCTION_NETWORK "network"
+#define LED_FUNCTION_ON "on"
+#define LED_FUNCTION_OS "os"
+#define LED_FUNCTION_PANEL "panel"
+#define LED_FUNCTION_PMU_STAT "pmu_stat"
+#define LED_FUNCTION_PROG "prog"
+#define LED_FUNCTION_PROGRAMMING "programming"
+#define LED_FUNCTION_PULSE "pulse"
+#define LED_FUNCTION_PWR "pwr"
+#define LED_FUNCTION_QSS "qss"
+#define LED_FUNCTION_REAR "rear"
+#define LED_FUNCTION_REBUILD "rebuild"
+#define LED_FUNCTION_RIGHT "right"
+#define LED_FUNCTION_ROUTER "router"
+#define LED_FUNCTION_RS "rs"
+#define LED_FUNCTION_RX "rx"
+#define LED_FUNCTION_SATA "sata"
+#define LED_FUNCTION_SD "sd"
+#define LED_FUNCTION_SLEEP "sleep"
+#define LED_FUNCTION_STANDBY "standby"
+#define LED_FUNCTION_STATUS "status"
+#define LED_FUNCTION_SW "sw"
+#define LED_FUNCTION_SWRDY "swrdy"
+#define LED_FUNCTION_SYSTEM "system"
+#define LED_FUNCTION_TEL "tel"
+#define LED_FUNCTION_TOP "top"
+#define LED_FUNCTION_TORCH "torch"
+#define LED_FUNCTION_TV "tv"
+#define LED_FUNCTION_TX "tx"
+#define LED_FUNCTION_UP "up"
+#define LED_FUNCTION_USB "usb"
+#define LED_FUNCTION_USB_COPY "usb_copy"
+#define LED_FUNCTION_USER "user"
+#define LED_FUNCTION_USR "usr"
+#define LED_FUNCTION_WAN "wan"
+#define LED_FUNCTION_WIFI "wifi"
+#define LED_FUNCTION_WIRELESS "wireless"
+#define LED_FUNCTION_WLAN "wlan"
+#define LED_FUNCTION_WMODE "wmode"
+#define LED_FUNCTION_WPS "wps"
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Signed-off-by: Dan Murphy <[email protected]>
---
drivers/leds/leds-lp8860.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c
index 39c72a9..7c12ccd 100644
--- a/drivers/leds/leds-lp8860.c
+++ b/drivers/leds/leds-lp8860.c
@@ -22,7 +22,6 @@
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
-#include <uapi/linux/uleds.h>
#define LP8860_DISP_CL1_BRT_MSB 0x00
#define LP8860_DISP_CL1_BRT_LSB 0x01
@@ -87,6 +86,8 @@
#define LP8860_CLEAR_FAULTS 0x01
+#define LP8860_NAME "lp8860"
+
/**
* struct lp8860_led -
* @lock - Lock for reading/writing the device
@@ -96,7 +97,6 @@
* @eeprom_regmap - EEPROM register map
* @enable_gpio - VDDIO/EN gpio to enable communication interface
* @regulator - LED supply regulator pointer
- * @label - LED label
*/
struct lp8860_led {
struct mutex lock;
@@ -106,7 +106,6 @@ struct lp8860_led {
struct regmap *eeprom_regmap;
struct gpio_desc *enable_gpio;
struct regulator *regulator;
- char label[LED_MAX_NAME_SIZE];
};
struct lp8860_eeprom_reg {
@@ -387,25 +386,26 @@ static int lp8860_probe(struct i2c_client *client,
struct lp8860_led *led;
struct device_node *np = client->dev.of_node;
struct device_node *child_node;
- const char *name;
+ struct led_init_data init_data;
led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
- for_each_available_child_of_node(np, child_node) {
- led->led_dev.default_trigger = of_get_property(child_node,
- "linux,default-trigger",
- NULL);
-
- ret = of_property_read_string(child_node, "label", &name);
- if (!ret)
- snprintf(led->label, sizeof(led->label), "%s:%s",
- id->name, name);
- else
- snprintf(led->label, sizeof(led->label),
- "%s::display_cluster", id->name);
- }
+ child_node = of_get_next_available_child(np, NULL);
+ if (!child_node)
+ return -EINVAL;
+
+ init_data.fwnode = of_fwnode_handle(child_node),
+
+ led->led_dev.default_trigger = of_get_property(child_node,
+ "linux,default-trigger",
+ NULL);
+
+ ret = led_compose_name(init_data.fwnode, LP8860_NAME,
+ ":display_cluster", init_data.name);
+ if (ret)
+ return ret;
led->enable_gpio = devm_gpiod_get_optional(&client->dev,
"enable", GPIOD_OUT_LOW);
@@ -420,7 +420,6 @@ static int lp8860_probe(struct i2c_client *client,
led->regulator = NULL;
led->client = client;
- led->led_dev.name = led->label;
led->led_dev.brightness_set_blocking = lp8860_brightness_set;
mutex_init(&led->lock);
@@ -447,7 +446,8 @@ static int lp8860_probe(struct i2c_client *client,
if (ret)
return ret;
- ret = devm_led_classdev_register(&client->dev, &led->led_dev);
+ ret = devm_led_classdev_register_ext(&client->dev, &led->led_dev,
+ &init_data);
if (ret) {
dev_err(&client->dev, "led register err: %d\n", ret);
return ret;
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Simon Shields <[email protected]>
---
.../devicetree/bindings/leds/leds-an30259a.txt | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-an30259a.txt b/Documentation/devicetree/bindings/leds/leds-an30259a.txt
index 6ffb861..43da93b 100644
--- a/Documentation/devicetree/bindings/leds/leds-an30259a.txt
+++ b/Documentation/devicetree/bindings/leds/leds-an30259a.txt
@@ -15,10 +15,19 @@ Required sub-node properties:
- reg: Pin that the LED is connected to. Must be 1, 2, or 3.
Optional sub-node properties:
- - label: see Documentation/devicetree/bindings/leds/common.txt
- - linux,default-trigger: see Documentation/devicetree/bindings/leds/common.txt
+ - function :
+ see Documentation/devicetree/bindings/leds/common.txt
+ - color :
+ see Documentation/devicetree/bindings/leds/common.txt
+ - label :
+ see Documentation/devicetree/bindings/leds/common.txt (deprecated)
+ - linux,default-trigger :
+ see Documentation/devicetree/bindings/leds/common.txt
Example:
+
+#include <dt-bindings/leds/functions.h>
+
led-controller@30 {
compatible = "panasonic,an30259a";
reg = <0x30>;
@@ -28,16 +37,19 @@ led-controller@30 {
led@1 {
reg = <1>;
linux,default-trigger = "heartbeat";
- label = "red:indicator";
+ function = LED_FUNCTION_INDICATOR;
+ color = "red";
};
led@2 {
reg = <2>;
- label = "green:indicator";
+ function = LED_FUNCTION_INDICATOR;
+ color = "green";
};
led@3 {
reg = <3>;
- label = "blue:indicator";
+ function = LED_FUNCTION_INDICATOR;
+ color = "blue";
};
};
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Linus Walleij <[email protected]>
---
drivers/leds/leds-gpio.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index c87fbd3..69a3cde 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -77,11 +77,19 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
static int create_gpio_led(const struct gpio_led *template,
struct gpio_led_data *led_dat, struct device *parent,
- struct device_node *np, gpio_blink_set_t blink_set)
+ struct fwnode_handle *fwnode, gpio_blink_set_t blink_set)
{
+ struct led_init_data init_data = { fwnode };
int ret, state;
- led_dat->cdev.name = template->name;
+ if (template->name) {
+ led_dat->cdev.name = template->name;
+ } else {
+ ret = led_compose_name(fwnode, NULL, NULL, init_data.name);
+ if (ret)
+ return ret;
+ }
+
led_dat->cdev.default_trigger = template->default_trigger;
led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
if (!led_dat->can_sleep)
@@ -112,7 +120,8 @@ static int create_gpio_led(const struct gpio_led *template,
if (ret < 0)
return ret;
- return devm_led_classdev_register(parent, &led_dat->cdev);
+ return devm_led_classdev_register_ext(parent, &led_dat->cdev,
+ &init_data);
}
struct gpio_leds_priv {
@@ -145,15 +154,6 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
struct gpio_led_data *led_dat = &priv->leds[priv->num_leds];
struct gpio_led led = {};
const char *state = NULL;
- struct device_node *np = to_of_node(child);
-
- ret = fwnode_property_read_string(child, "label", &led.name);
- if (ret && IS_ENABLED(CONFIG_OF) && np)
- led.name = np->name;
- if (!led.name) {
- fwnode_handle_put(child);
- return ERR_PTR(-EINVAL);
- }
led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,
GPIOD_ASIS,
@@ -183,12 +183,11 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1;
- ret = create_gpio_led(&led, led_dat, dev, np, NULL);
+ ret = create_gpio_led(&led, led_dat, dev, child, NULL);
if (ret < 0) {
fwnode_handle_put(child);
return ERR_PTR(ret);
}
- led_dat->cdev.dev->of_node = np;
priv->num_leds++;
}
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Linus Walleij <[email protected]>
---
.../devicetree/bindings/leds/leds-gpio.txt | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-gpio.txt b/Documentation/devicetree/bindings/leds/leds-gpio.txt
index a48dda2..c34cb64 100644
--- a/Documentation/devicetree/bindings/leds/leds-gpio.txt
+++ b/Documentation/devicetree/bindings/leds/leds-gpio.txt
@@ -10,8 +10,12 @@ LED sub-node properties:
- gpios : Should specify the LED's GPIO, see "gpios property" in
Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs should be
indicated using flags in the GPIO specifier.
-- label : (optional)
+- function : (optional)
+ see Documentation/devicetree/bindings/leds/common.txt
+- color : (optional)
see Documentation/devicetree/bindings/leds/common.txt
+- label : (optional)
+ see Documentation/devicetree/bindings/leds/common.txt (deprecated)
- linux,default-trigger : (optional)
see Documentation/devicetree/bindings/leds/common.txt
- default-state: (optional) The initial state of the LED.
@@ -30,27 +34,30 @@ Examples:
leds {
compatible = "gpio-leds";
- hdd {
- label = "Disk Activity";
+ led@0 {
gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "disk-activity";
+ function = LED_FUNCTION_HDD;
};
- fault {
+ led@1 {
gpios = <&mcu_pio 1 GPIO_ACTIVE_HIGH>;
/* Keep LED on if BIOS detected hardware fault */
default-state = "keep";
+ function = LED_FUNCTION_FAULT;
};
};
run-control {
compatible = "gpio-leds";
- red {
+ led@0 {
gpios = <&mpc8572 6 GPIO_ACTIVE_HIGH>;
+ color = "red";
default-state = "off";
};
- green {
+ led@1 {
gpios = <&mpc8572 7 GPIO_ACTIVE_HIGH>;
+ color = "green";
default-state = "on";
};
};
@@ -58,9 +65,10 @@ run-control {
leds {
compatible = "gpio-leds";
- charger-led {
+ led@0 {
gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "max8903-charger-charging";
retain-state-suspended;
+ function = LED_FUNCTION_CHRG;
};
};
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Also, fix malformed syntax of address-cells and size-cells
in the example.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Sakari Ailus <[email protected]>
---
.../devicetree/bindings/leds/ams,as3645a.txt | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/ams,as3645a.txt b/Documentation/devicetree/bindings/leds/ams,as3645a.txt
index fdc40e3..a259850 100644
--- a/Documentation/devicetree/bindings/leds/ams,as3645a.txt
+++ b/Documentation/devicetree/bindings/leds/ams,as3645a.txt
@@ -39,7 +39,9 @@ ams,input-max-microamp: Maximum flash controller input current. The
Optional properties of the flash child node
===========================================
-label : The label of the flash LED.
+function : See Documentation/devicetree/bindings/leds/common.txt.
+color : See Documentation/devicetree/bindings/leds/common.txt.
+label : See Documentation/devicetree/bindings/leds/common.txt (deprecated).
Required properties of the indicator child node (1)
@@ -52,28 +54,32 @@ led-max-microamp: Maximum indicator current. The allowed values are
Optional properties of the indicator child node
===============================================
-label : The label of the indicator LED.
+function : See Documentation/devicetree/bindings/leds/common.txt.
+color : See Documentation/devicetree/bindings/leds/common.txt.
+label : See Documentation/devicetree/bindings/leds/common.txt (deprecated).
Example
=======
+#include <dt-bindings/leds/functions.h>
+
as3645a@30 {
- #address-cells: 1
- #size-cells: 0
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0x30>;
compatible = "ams,as3645a";
- flash@0 {
+ led@0 {
reg = <0x0>;
flash-timeout-us = <150000>;
flash-max-microamp = <320000>;
led-max-microamp = <60000>;
ams,input-max-microamp = <1750000>;
- label = "as3645a:flash";
+ function = LED_FUNCTION_FLASH;
};
- indicator@1 {
+ led@1 {
reg = <0x1>;
led-max-microamp = <10000>;
- label = "as3645a:indicator";
+ function = LED_FUNCTION_INDICATOR;
};
};
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
---
drivers/leds/leds-aat1290.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
index 43bd8a4..9132a6e 100644
--- a/drivers/leds/leds-aat1290.c
+++ b/drivers/leds/leds-aat1290.c
@@ -45,6 +45,8 @@
#define AAT1290_FLASH_TM_NUM_LEVELS 16
#define AAT1290_MM_CURRENT_SCALE_SIZE 15
+#define AAT1290_NAME "aat1290"
+
struct aat1290_led_config_data {
/* maximum LED current in movie mode */
@@ -78,7 +80,6 @@ struct aat1290_led {
int *mm_current_scale;
/* device mode */
bool movie_mode;
-
/* brightness cache */
unsigned int torch_brightness;
};
@@ -218,7 +219,6 @@ static int aat1290_led_parse_dt(struct aat1290_led *led,
struct aat1290_led_config_data *cfg,
struct device_node **sub_node)
{
- struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
struct device *dev = &led->pdev->dev;
struct device_node *child_node;
#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
@@ -257,9 +257,6 @@ static int aat1290_led_parse_dt(struct aat1290_led *led,
return -EINVAL;
}
- led_cdev->name = of_get_property(child_node, "label", NULL) ? :
- child_node->name;
-
ret = of_property_read_u32(child_node, "led-max-microamp",
&cfg->max_mm_current);
/*
@@ -469,6 +466,7 @@ static int aat1290_led_probe(struct platform_device *pdev)
struct aat1290_led *led;
struct led_classdev *led_cdev;
struct led_classdev_flash *fled_cdev;
+ struct led_init_data init_data;
struct aat1290_led_config_data led_cfg = {};
struct v4l2_flash_config v4l2_sd_cfg = {};
int ret;
@@ -488,6 +486,12 @@ static int aat1290_led_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
+ init_data.fwnode = of_fwnode_handle(sub_node);
+ ret = led_compose_name(init_data.fwnode, AAT1290_NAME, NULL,
+ init_data.name);
+ if (ret < 0)
+ return ret;
+
mutex_init(&led->lock);
/* Initialize LED Flash class device */
@@ -498,7 +502,8 @@ static int aat1290_led_probe(struct platform_device *pdev)
aat1290_init_flash_timeout(led, &led_cfg);
/* Register LED Flash class device */
- ret = led_classdev_flash_register(&pdev->dev, fled_cdev);
+ ret = led_classdev_flash_register_ext(&pdev->dev, fled_cdev,
+ &init_data);
if (ret < 0)
goto err_flash_register;
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
---
Documentation/devicetree/bindings/leds/leds-aat1290.txt | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-aat1290.txt b/Documentation/devicetree/bindings/leds/leds-aat1290.txt
index 85c0c58..baa33d1 100644
--- a/Documentation/devicetree/bindings/leds/leds-aat1290.txt
+++ b/Documentation/devicetree/bindings/leds/leds-aat1290.txt
@@ -32,15 +32,18 @@ Required properties of the LED child node:
formula: T = 8.82 * 10^9 * Ct.
Optional properties of the LED child node:
-- label : see Documentation/devicetree/bindings/leds/common.txt
+- function : see Documentation/devicetree/bindings/leds/common.txt
+- color : see Documentation/devicetree/bindings/leds/common.txt
+- label : see Documentation/devicetree/bindings/leds/common.txt (deprecated)
Example (by Ct = 220nF, Rset = 160kohm and exynos4412-trats2 board with
a switch that allows for routing strobe signal either from the host or from
the camera sensor):
#include "exynos4412.dtsi"
+#include <dt-bindings/leds/functions.h>
-aat1290 {
+led-controller {
compatible = "skyworks,aat1290";
flen-gpios = <&gpj1 1 GPIO_ACTIVE_HIGH>;
enset-gpios = <&gpj1 2 GPIO_ACTIVE_HIGH>;
@@ -50,8 +53,9 @@ aat1290 {
pinctrl-1 = <&camera_flash_host>;
pinctrl-2 = <&camera_flash_isp>;
- camera_flash: flash-led {
- label = "aat1290-flash";
+ camera_flash: led {
+ function = LED_FUNCTION_FLASH;
+ color = "white";
led-max-microamp = <520833>;
flash-max-microamp = <1012500>;
flash-max-timeout-us = <1940000>;
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Oleh Kravchenko <[email protected]>
---
.../devicetree/bindings/leds/leds-cr0014114.txt | 26 ++++++++++++++++------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-cr0014114.txt b/Documentation/devicetree/bindings/leds/leds-cr0014114.txt
index 4255b19..4c65c56 100644
--- a/Documentation/devicetree/bindings/leds/leds-cr0014114.txt
+++ b/Documentation/devicetree/bindings/leds/leds-cr0014114.txt
@@ -11,14 +11,20 @@ Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
apply. In particular, "reg" and "spi-max-frequency" properties must be given.
LED sub-node properties:
-- label :
+- function :
+ see Documentation/devicetree/bindings/leds/common.txt
+- color :
see Documentation/devicetree/bindings/leds/common.txt
+- label :
+ see Documentation/devicetree/bindings/leds/common.txt (deprecated)
- linux,default-trigger : (optional)
see Documentation/devicetree/bindings/leds/common.txt
Example
-------
+#include <dt-bindings/leds/functions.h>
+
led-controller@0 {
compatible = "crane,cr0014114";
reg = <0>;
@@ -28,27 +34,33 @@ led-controller@0 {
led@0 {
reg = <0>;
- label = "red:coin";
+ function = "coin";
+ color = "red";
};
led@1 {
reg = <1>;
- label = "green:coin";
+ function = "coin";
+ color = "green";
};
led@2 {
reg = <2>;
- label = "blue:coin";
+ function = "coin";
+ color = "blue";
};
led@3 {
reg = <3>;
- label = "red:bill";
+ function = "bill";
+ color = "red";
};
led@4 {
reg = <4>;
- label = "green:bill";
+ function = "bill";
+ color = "green";
};
led@5 {
reg = <5>;
- label = "blue:bill";
+ function = "bill";
+ color = "blue";
};
...
};
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Dan Murphy <[email protected]>
---
Documentation/devicetree/bindings/leds/leds-lm3601x.txt | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-lm3601x.txt b/Documentation/devicetree/bindings/leds/leds-lm3601x.txt
index a88b2c4..aaffc68 100644
--- a/Documentation/devicetree/bindings/leds/leds-lm3601x.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lm3601x.txt
@@ -22,9 +22,14 @@ Required properties for flash LED child nodes:
- led-max-microamp : Range from 2.4mA - 376mA
Optional child properties:
- - label : see Documentation/devicetree/bindings/leds/common.txt
+ - function : see Documentation/devicetree/bindings/leds/common.txt
+ - color : see Documentation/devicetree/bindings/leds/common.txt
+ - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated)
Example:
+
+#include <dt-bindings/leds/functions.h>
+
led-controller@64 {
compatible = "ti,lm36010";
#address-cells = <1>;
@@ -33,7 +38,8 @@ led-controller@64 {
led@0 {
reg = <1>;
- label = "white:torch";
+ function = LED_FUNCTION_TORCH;
+ color = "white";
led-max-microamp = <376000>;
flash-max-microamp = <1500000>;
flash-max-timeout-us = <1600000>;
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Dan Murphy <[email protected]>
---
drivers/leds/leds-lm3601x.c | 45 ++++++++++++++++++++++++---------------------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/drivers/leds/leds-lm3601x.c b/drivers/leds/leds-lm3601x.c
index 081aa71..91ea652 100644
--- a/drivers/leds/leds-lm3601x.c
+++ b/drivers/leds/leds-lm3601x.c
@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <uapi/linux/uleds.h>
#define LM3601X_LED_IR 0x0
#define LM3601X_LED_TORCH 0x1
@@ -90,8 +89,6 @@ struct lm3601x_led {
struct regmap *regmap;
struct mutex lock;
- char led_name[LED_MAX_NAME_SIZE];
-
unsigned int flash_timeout;
unsigned int last_flag;
@@ -322,10 +319,24 @@ static const struct led_flash_ops flash_ops = {
.fault_get = lm3601x_flash_fault_get,
};
-static int lm3601x_register_leds(struct lm3601x_led *led)
+static int lm3601x_register_leds(struct lm3601x_led *led,
+ struct fwnode_handle *fwnode)
{
struct led_classdev *led_cdev;
struct led_flash_setting *setting;
+ struct led_init_data init_data = { fwnode };
+ char *mode_name;
+ int ret;
+
+ if (led->led_mode == LM3601X_LED_TORCH)
+ mode_name = "torch";
+ else
+ mode_name = "infrared";
+
+ ret = led_compose_name(fwnode, led->client->name, mode_name,
+ init_data.name);
+ if (ret < 0)
+ return ret;
led->fled_cdev.ops = &flash_ops;
@@ -342,20 +353,20 @@ static int lm3601x_register_leds(struct lm3601x_led *led)
setting->val = led->flash_current_max;
led_cdev = &led->fled_cdev.led_cdev;
- led_cdev->name = led->led_name;
led_cdev->brightness_set_blocking = lm3601x_brightness_set;
led_cdev->max_brightness = DIV_ROUND_UP(led->torch_current_max,
LM3601X_TORCH_REG_DIV);
led_cdev->flags |= LED_DEV_CAP_FLASH;
- return led_classdev_flash_register(&led->client->dev, &led->fled_cdev);
+ return led_classdev_flash_register_ext(&led->client->dev,
+ &led->fled_cdev, &init_data);
}
-static int lm3601x_parse_node(struct lm3601x_led *led)
+static int lm3601x_parse_node(struct lm3601x_led *led,
+ struct fwnode_handle **fwnode)
{
struct fwnode_handle *child = NULL;
int ret = -ENODEV;
- const char *name;
child = device_get_next_child_node(&led->client->dev, child);
if (!child) {
@@ -376,17 +387,6 @@ static int lm3601x_parse_node(struct lm3601x_led *led)
goto out_err;
}
- ret = fwnode_property_read_string(child, "label", &name);
- if (ret) {
- if (led->led_mode == LM3601X_LED_TORCH)
- name = "torch";
- else
- name = "infrared";
- }
-
- snprintf(led->led_name, sizeof(led->led_name),
- "%s:%s", led->client->name, name);
-
ret = fwnode_property_read_u32(child, "led-max-microamp",
&led->torch_current_max);
if (ret) {
@@ -411,6 +411,8 @@ static int lm3601x_parse_node(struct lm3601x_led *led)
goto out_err;
}
+ *fwnode = child;
+
out_err:
fwnode_handle_put(child);
return ret;
@@ -419,6 +421,7 @@ static int lm3601x_parse_node(struct lm3601x_led *led)
static int lm3601x_probe(struct i2c_client *client)
{
struct lm3601x_led *led;
+ struct fwnode_handle *fwnode;
int ret;
led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
@@ -428,7 +431,7 @@ static int lm3601x_probe(struct i2c_client *client)
led->client = client;
i2c_set_clientdata(client, led);
- ret = lm3601x_parse_node(led);
+ ret = lm3601x_parse_node(led, &fwnode);
if (ret)
return -ENODEV;
@@ -442,7 +445,7 @@ static int lm3601x_probe(struct i2c_client *client)
mutex_init(&led->lock);
- return lm3601x_register_leds(led);
+ return lm3601x_register_leds(led, fwnode);
}
static int lm3601x_remove(struct i2c_client *client)
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Dan Murphy <[email protected]>
---
Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
index 08b3528..62c8fe5 100644
--- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
@@ -26,12 +26,16 @@ Required child properties:
3 - Will enable the LED3 sync (LM36923 only)
Optional child properties:
- - label : see Documentation/devicetree/bindings/leds/common.txt
+ - function : see Documentation/devicetree/bindings/leds/common.txt
+ - color : see Documentation/devicetree/bindings/leds/common.txt
+ - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated)
- linux,default-trigger :
see Documentation/devicetree/bindings/leds/common.txt
Example:
+#include <dt-bindings/leds/functions.h>
+
led-controller@36 {
compatible = "ti,lm3692x";
reg = <0x36>;
@@ -43,7 +47,8 @@ led-controller@36 {
led@0 {
reg = <0>;
- label = "white:backlight_cluster";
+ function = LED_BACKLIGHT_CLUSTER;
+ color = "white";
linux,default-trigger = "backlight";
};
}
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Dan Murphy <[email protected]>
---
drivers/leds/leds-lm3692x.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
index 4f413a7..9dfc0f2 100644
--- a/drivers/leds/leds-lm3692x.c
+++ b/drivers/leds/leds-lm3692x.c
@@ -13,7 +13,6 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
-#include <uapi/linux/uleds.h>
#define LM36922_MODEL 0
#define LM36923_MODEL 1
@@ -95,6 +94,9 @@
#define LM3692X_FAULT_FLAG_SHRT BIT(3)
#define LM3692X_FAULT_FLAG_OPEN BIT(4)
+#define LM36922_NAME "lm36922"
+#define LM36923_NAME "lm36923"
+
/**
* struct lm3692x_led -
* @lock - Lock for reading/writing the device
@@ -103,7 +105,6 @@
* @regmap - Devices register map
* @enable_gpio - VDDIO/EN gpio to enable communication interface
* @regulator - LED supply regulator pointer
- * @label - LED label
* @led_enable - LED sync to be enabled
* @model_id - Current device model ID enumerated
*/
@@ -114,7 +115,6 @@ struct lm3692x_led {
struct regmap *regmap;
struct gpio_desc *enable_gpio;
struct regulator *regulator;
- char label[LED_MAX_NAME_SIZE];
int led_enable;
int model_id;
};
@@ -325,7 +325,8 @@ static int lm3692x_init(struct lm3692x_led *led)
static int lm3692x_probe_dt(struct lm3692x_led *led)
{
struct fwnode_handle *child = NULL;
- const char *name;
+ struct led_init_data init_data;
+ char *model_name;
int ret;
led->enable_gpio = devm_gpiod_get_optional(&led->client->dev,
@@ -346,17 +347,20 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
dev_err(&led->client->dev, "No LED Child node\n");
return -ENODEV;
}
+ init_data.fwnode = child;
- fwnode_property_read_string(child, "linux,default-trigger",
- &led->led_dev.default_trigger);
+ if (led->model_id == LM36922_MODEL)
+ model_name = LM36922_NAME;
+ else
+ model_name = LM36923_NAME;
- ret = fwnode_property_read_string(child, "label", &name);
+ ret = led_compose_name(child, model_name, ":backlight_cluster",
+ init_data.name);
if (ret)
- snprintf(led->label, sizeof(led->label),
- "%s::", led->client->name);
- else
- snprintf(led->label, sizeof(led->label),
- "%s:%s", led->client->name, name);
+ return ret;
+
+ fwnode_property_read_string(child, "linux,default-trigger",
+ &led->led_dev.default_trigger);
ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
if (ret) {
@@ -364,16 +368,13 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
return ret;
}
- led->led_dev.name = led->label;
-
- ret = devm_led_classdev_register(&led->client->dev, &led->led_dev);
+ ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev,
+ &init_data);
if (ret) {
dev_err(&led->client->dev, "led register err: %d\n", ret);
return ret;
}
- led->led_dev.dev->of_node = to_of_node(child);
-
return 0;
}
@@ -439,8 +440,8 @@ static int lm3692x_remove(struct i2c_client *client)
}
static const struct i2c_device_id lm3692x_id[] = {
- { "lm36922", LM36922_MODEL },
- { "lm36923", LM36923_MODEL },
+ { LM36922_NAME, LM36922_MODEL },
+ { LM36923_NAME, LM36923_MODEL },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm3692x_id);
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Simon Shields <[email protected]>
---
drivers/leds/leds-an30259a.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/leds/leds-an30259a.c b/drivers/leds/leds-an30259a.c
index 1c1f0c8..d714ee8 100644
--- a/drivers/leds/leds-an30259a.c
+++ b/drivers/leds/leds-an30259a.c
@@ -13,7 +13,6 @@
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/regmap.h>
-#include <uapi/linux/uleds.h>
#define AN30259A_MAX_LEDS 3
@@ -54,6 +53,8 @@
#define AN30259A_BLINK_MAX_TIME 7500 /* ms */
#define AN30259A_SLOPE_RESOLUTION 500 /* ms */
+#define AN30259A_NAME "an30259a"
+
#define STATE_OFF 0
#define STATE_KEEP 1
#define STATE_ON 2
@@ -62,11 +63,11 @@ struct an30259a;
struct an30259a_led {
struct an30259a *chip;
+ struct fwnode_handle *fwnode;
struct led_classdev cdev;
u32 num;
u32 default_state;
bool sloping;
- char label[LED_MAX_NAME_SIZE];
};
struct an30259a {
@@ -226,14 +227,7 @@ static int an30259a_dt_init(struct i2c_client *client,
led->num = source;
led->chip = chip;
-
- if (of_property_read_string(child, "label", &str))
- snprintf(led->label, sizeof(led->label), "an30259a::");
- else
- snprintf(led->label, sizeof(led->label), "an30259a:%s",
- str);
-
- led->cdev.name = led->label;
+ led->fwnode = of_fwnode_handle(child);
if (!of_property_read_string(child, "default-state", &str)) {
if (!strcmp(str, "on"))
@@ -312,13 +306,21 @@ static int an30259a_probe(struct i2c_client *client)
chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config);
for (i = 0; i < chip->num_leds; i++) {
+ struct led_init_data init_data = { chip->leds[i].fwnode };
+
+ int ret = led_compose_name(init_data.fwnode, AN30259A_NAME, ":",
+ init_data.name);
+ if (ret)
+ return ret;
+
an30259a_init_default_state(&chip->leds[i]);
chip->leds[i].cdev.brightness_set_blocking =
an30259a_brightness_set;
chip->leds[i].cdev.blink_set = an30259a_blink_set;
- err = devm_led_classdev_register(&client->dev,
- &chip->leds[i].cdev);
+ err = devm_led_classdev_register_ext(&client->dev,
+ &chip->leds[i].cdev,
+ &init_data);
if (err < 0)
goto exit;
}
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Dan Murphy <[email protected]>
---
Documentation/devicetree/bindings/leds/leds-lp8860.txt | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-lp8860.txt b/Documentation/devicetree/bindings/leds/leds-lp8860.txt
index 5f0e892..c439bdd 100644
--- a/Documentation/devicetree/bindings/leds/leds-lp8860.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lp8860.txt
@@ -20,12 +20,16 @@ Required child properties:
- reg : 0
Optional child properties:
- - label : see Documentation/devicetree/bindings/leds/common.txt
+ - function : see Documentation/devicetree/bindings/leds/common.txt
+ - color : see Documentation/devicetree/bindings/leds/common.txt
+ - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated)
- linux,default-trigger :
see Documentation/devicetree/bindings/leds/common.txt
Example:
+#include <dt-bindings/leds/functions.h>
+
led-controller@2d {
compatible = "ti,lp8860";
#address-cells = <1>;
@@ -36,7 +40,8 @@ led-controller@2d {
led@0 {
reg = <0>;
- label = "white:backlight";
+ function = LED_FUNCTION_BACKLIGHT;
+ color = "white";
linux,default-trigger = "backlight";
};
}
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Sakari Ailus <[email protected]>
---
drivers/leds/leds-as3645a.c | 65 ++++++++++++++++++++-------------------------
1 file changed, 29 insertions(+), 36 deletions(-)
diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c
index 98a69b1..d7f6037 100644
--- a/drivers/leds/leds-as3645a.c
+++ b/drivers/leds/leds-as3645a.c
@@ -132,11 +132,6 @@ struct as3645a_config {
u32 peak;
};
-struct as3645a_names {
- char flash[32];
- char indicator[32];
-};
-
struct as3645a {
struct i2c_client *client;
@@ -492,12 +487,10 @@ static int as3645a_detect(struct as3645a *flash)
}
static int as3645a_parse_node(struct as3645a *flash,
- struct as3645a_names *names,
struct device_node *node)
{
struct as3645a_config *cfg = &flash->cfg;
struct device_node *child;
- const char *name;
int rval;
for_each_child_of_node(node, child) {
@@ -524,13 +517,6 @@ static int as3645a_parse_node(struct as3645a *flash,
return -ENODEV;
}
- rval = of_property_read_string(flash->flash_node, "label", &name);
- if (!rval)
- strlcpy(names->flash, name, sizeof(names->flash));
- else
- snprintf(names->flash, sizeof(names->flash),
- "%pOFn:flash", node);
-
rval = of_property_read_u32(flash->flash_node, "flash-timeout-us",
&cfg->flash_timeout_us);
if (rval < 0) {
@@ -568,13 +554,6 @@ static int as3645a_parse_node(struct as3645a *flash,
goto out_err;
}
- rval = of_property_read_string(flash->indicator_node, "label", &name);
- if (!rval)
- strlcpy(names->indicator, name, sizeof(names->indicator));
- else
- snprintf(names->indicator, sizeof(names->indicator),
- "%pOFn:indicator", node);
-
rval = of_property_read_u32(flash->indicator_node, "led-max-microamp",
&cfg->indicator_max_ua);
if (rval < 0) {
@@ -592,21 +571,27 @@ static int as3645a_parse_node(struct as3645a *flash,
return rval;
}
-static int as3645a_led_class_setup(struct as3645a *flash,
- struct as3645a_names *names)
+static int as3645a_led_class_setup(struct as3645a *flash)
{
struct led_classdev *fled_cdev = &flash->fled.led_cdev;
struct led_classdev *iled_cdev = &flash->iled_cdev;
+ struct led_init_data init_data;
struct led_flash_setting *cfg;
int rval;
- iled_cdev->name = names->indicator;
+ init_data.fwnode = of_fwnode_handle(flash->indicator_node);
+ rval = led_compose_name(init_data.fwnode, AS_NAME, "indicator",
+ init_data.name);
+ if (rval < 0)
+ return rval;
+
iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness;
iled_cdev->max_brightness =
flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP;
iled_cdev->flags = LED_CORE_SUSPENDRESUME;
- rval = led_classdev_register(&flash->client->dev, iled_cdev);
+ rval = led_classdev_register_ext(&flash->client->dev, iled_cdev,
+ &init_data);
if (rval < 0)
return rval;
@@ -624,7 +609,12 @@ static int as3645a_led_class_setup(struct as3645a *flash,
flash->fled.ops = &as3645a_led_flash_ops;
- fled_cdev->name = names->flash;
+ init_data.fwnode = of_fwnode_handle(flash->flash_node);
+ rval = led_compose_name(init_data.fwnode, AS_NAME, "flash",
+ init_data.name);
+ if (rval < 0)
+ goto out_err;
+
fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness;
/* Value 0 is off in LED class. */
fled_cdev->max_brightness =
@@ -632,14 +622,18 @@ static int as3645a_led_class_setup(struct as3645a *flash,
flash->cfg.assist_max_ua) + 1;
fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME;
- rval = led_classdev_flash_register(&flash->client->dev, &flash->fled);
- if (rval) {
- led_classdev_unregister(iled_cdev);
- dev_err(&flash->client->dev,
- "led_classdev_flash_register() failed, error %d\n",
- rval);
- }
+ rval = led_classdev_flash_register_ext(&flash->client->dev,
+ &flash->fled, &init_data);
+ if (rval)
+ goto out_err;
+
+ return rval;
+out_err:
+ led_classdev_unregister(iled_cdev);
+ dev_err(&flash->client->dev,
+ "led_classdev_flash_register() failed, error %d\n",
+ rval);
return rval;
}
@@ -686,7 +680,6 @@ static int as3645a_v4l2_setup(struct as3645a *flash)
static int as3645a_probe(struct i2c_client *client)
{
- struct as3645a_names names;
struct as3645a *flash;
int rval;
@@ -699,7 +692,7 @@ static int as3645a_probe(struct i2c_client *client)
flash->client = client;
- rval = as3645a_parse_node(flash, &names, client->dev.of_node);
+ rval = as3645a_parse_node(flash, client->dev.of_node);
if (rval < 0)
return rval;
@@ -714,7 +707,7 @@ static int as3645a_probe(struct i2c_client *client)
if (rval)
goto out_mutex_destroy;
- rval = as3645a_led_class_setup(flash, &names);
+ rval = as3645a_led_class_setup(flash);
if (rval)
goto out_mutex_destroy;
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Xiaotong Lu <[email protected]>
Cc: Baolin Wang <[email protected]>
---
drivers/leds/leds-sc27xx-bltc.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/leds/leds-sc27xx-bltc.c b/drivers/leds/leds-sc27xx-bltc.c
index 9d9b7aa..9fe7cb1 100644
--- a/drivers/leds/leds-sc27xx-bltc.c
+++ b/drivers/leds/leds-sc27xx-bltc.c
@@ -6,7 +6,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
-#include <uapi/linux/uleds.h>
/* PMIC global control register definition */
#define SC27XX_MODULE_EN0 0xc08
@@ -36,7 +35,7 @@
#define SC27XX_LEDS_MAX 3
struct sc27xx_led {
- char name[LED_MAX_NAME_SIZE];
+ struct fwnode_handle *fwnode;
struct led_classdev ldev;
struct sc27xx_led_priv *priv;
u8 line;
@@ -132,16 +131,22 @@ static int sc27xx_led_register(struct device *dev, struct sc27xx_led_priv *priv)
for (i = 0; i < SC27XX_LEDS_MAX; i++) {
struct sc27xx_led *led = &priv->leds[i];
+ struct led_init_data init_data = { led->fwnode };
if (!led->active)
continue;
+ err = led_compose_name(led->fwnode, "sc27xx", ":",
+ init_data.name);
+ if (err)
+ return err;
+
led->line = i;
led->priv = priv;
- led->ldev.name = led->name;
led->ldev.brightness_set_blocking = sc27xx_led_set;
- err = devm_led_classdev_register(dev, &led->ldev);
+ err = devm_led_classdev_register_ext(dev, &led->ldev,
+ &init_data);
if (err)
return err;
}
@@ -154,7 +159,6 @@ static int sc27xx_led_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node, *child;
struct sc27xx_led_priv *priv;
- const char *str;
u32 base, count, reg;
int err;
@@ -196,15 +200,8 @@ static int sc27xx_led_probe(struct platform_device *pdev)
return -EINVAL;
}
+ priv->leds[reg].fwnode = of_fwnode_handle(child);
priv->leds[reg].active = true;
-
- err = of_property_read_string(child, "label", &str);
- if (err)
- snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE,
- "sc27xx::");
- else
- snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE,
- "sc27xx:%s", str);
}
err = sc27xx_led_register(dev, priv);
--
2.1.4
Add public led_compose_name() API for composing LED class device
name basing on fwnode_handle data. The function composes device name
according to either a new <color:function> pattern or the legacy
<devicename:color:function> pattern. The decision on using the
particular pattern is made basing on whether fwnode contains new
"function" and "color" properties, or the legacy "label" proeprty.
Backwards compatibility with in-driver hard-coded LED class device
names is assured thanks to the default_desc argument.
In case none of the aformentioned properties was found, then, for OF
nodes, the node name is adopted for LED class device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Baolin Wang <[email protected]>
Cc: Daniel Mack <[email protected]>
Cc: Dan Murphy <[email protected]>
Cc: Linus Walleij <[email protected]>
Cc: Oleh Kravchenko <[email protected]>
Cc: Sakari Ailus <[email protected]>
Cc: Simon Shields <[email protected]>
Cc: Xiaotong Lu <[email protected]>
---
Documentation/leds/leds-class.txt | 2 +-
drivers/leds/led-core.c | 71 +++++++++++++++++++++++++++++++++++++++
include/linux/leds.h | 32 ++++++++++++++++++
3 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
index 836cb16..e9009c4 100644
--- a/Documentation/leds/leds-class.txt
+++ b/Documentation/leds/leds-class.txt
@@ -43,7 +43,7 @@ LED Device Naming
Is currently of the form:
-"devicename:colour:function"
+"colour:function"
There have been calls for LED properties such as colour to be exported as
individual led class attributes. As a solution which doesn't incur as much
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index ede4fa0..f7371fc 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -16,6 +16,8 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/property.h>
#include <linux/rwsem.h>
#include "leds.h"
@@ -327,3 +329,72 @@ void led_sysfs_enable(struct led_classdev *led_cdev)
led_cdev->flags &= ~LED_SYSFS_DISABLE;
}
EXPORT_SYMBOL_GPL(led_sysfs_enable);
+
+static void led_parse_properties(struct fwnode_handle *fwnode,
+ struct led_properties *props)
+{
+ int ret;
+
+ if (!fwnode)
+ return;
+
+ ret = fwnode_property_read_string(fwnode, "label", &props->label);
+ if (!ret)
+ return;
+
+ ret = fwnode_property_read_string(fwnode, "function", &props->function);
+ if (ret)
+ pr_info("Failed to parse function property\n");
+
+ ret = fwnode_property_read_string(fwnode, "color", &props->color);
+ if (ret)
+ pr_info("Failed to parse color property\n");
+}
+
+int led_compose_name(struct fwnode_handle *fwnode, const char *led_hw_name,
+ const char *default_desc, char *led_classdev_name)
+{
+ struct led_properties props = {};
+
+ if (!led_classdev_name)
+ return -EINVAL;
+
+ led_parse_properties(fwnode, &props);
+
+ if (props.label) {
+ /*
+ * Presence of 'label' DT property implies legacy LED name,
+ * formatted as <devicename:color:function>, with possible
+ * section omission if doesn't apply to given device.
+ *
+ * If no led_hw_name has been passed, then it indicates that
+ * DT label should be used as-is for LED class device name.
+ * Otherwise the label is prepended with led_hw_name to compose
+ * the final LED class device name.
+ */
+ if (!led_hw_name) {
+ strncpy(led_classdev_name, props.label,
+ LED_MAX_NAME_SIZE);
+ } else {
+ snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
+ led_hw_name, props.label);
+ }
+ } else if (props.function || props.color) {
+ snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
+ props.color ?: "", props.function ?: "");
+ } else if (default_desc) {
+ if (!led_hw_name) {
+ pr_err("Legacy LED naming requires devicename segment");
+ return -EINVAL;
+ }
+ snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
+ led_hw_name, default_desc);
+ } else if (is_of_node(fwnode)) {
+ strncpy(led_classdev_name, to_of_node(fwnode)->name,
+ LED_MAX_NAME_SIZE);
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(led_compose_name);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 646c49a..ddb4001 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -238,6 +238,32 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
extern void led_sysfs_enable(struct led_classdev *led_cdev);
/**
+ * led_compose_name - compose LED class device name
+ * @child: child fwnode_handle describing a LED,
+ * or a group of synchronized LEDs.
+ * @led_hw_name: name of the LED controller, used when falling back to legacy
+ * LED naming; it should be set to NULL in new LED class drivers
+ * @default_desc: default <color:function> tuple, for backwards compatibility
+ * with in-driver hard-coded LED names used as a fallback when
+ * "label" DT property was absent; it should be set to NULL
+ * in new LED class drivers
+ * @led_classdev_name: composed LED class device name
+ *
+ * Create LED class device name basing on the configuration provided by the
+ * board firmware. The name can have a legacy form <devicename:color:function>,
+ * or a new form <color:function>. The latter is chosen if at least one of
+ * "color" or "function" properties is present in the fwnode, leaving the
+ * section blank if the related property is absent. The former is applied
+ * when legacy "label" property is present in the fwnode. In case none of the
+ * aformentioned properties was found, then, for OF nodes, the node name
+ * is adopted for LED class device name.
+ *
+ * Returns: 0 on success or negative error value on failure
+ */
+extern int led_compose_name(struct fwnode_handle *child, const char *led_hw_name,
+ const char *default_desc, char *led_classdev_name);
+
+/**
* led_sysfs_is_disabled - check if LED sysfs interface is disabled
* @led_cdev: the LED to query
*
@@ -414,6 +440,12 @@ struct led_platform_data {
struct led_info *leds;
};
+struct led_properties {
+ const char *color;
+ const char *function;
+ const char *label;
+};
+
struct gpio_desc;
typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
unsigned long *delay_on,
--
2.1.4
Replace of_led_classdev_register() with led_classdev_register_ext(), which
accepts easily extendable struct led_init_data, instead of the fixed
struct device_node argument. The latter can be now passed in a fwnode
property of the struct led_init_data.
The modification is driven by the need for passing another argument
to the LED class initialization function - a LED class device name.
Currently it is conveyed in the "name" char pointer property of
struct led_classdev, which is semantically and functionally incorrect
since it is needed only on LED class device registration, but persists
in system memory throughout the whole LED class device lifetime.
Whereas in case of the name strings coming from DT "label" property or
statically initialized ones the cost is only the pointer size, it grows
to LED_MAX_NAME_SIZE (64) with the advent of a new LED class device naming
scheme, where color and function properties come from separate board
firmware properties and the name needs to be constructed in a new buffer.
The change will not break any existing clients since the patch alters
also existing led_classdev{_flash}_register() macro wrappers, that pass
NULL in place of init_data, which leads to using legacy name
initialization path basing on the struct led_classdev's "name" property.
Two existing users of devm_of_led_classdev_registers() are modified
to use devm_led_classdev_register(), which will not impact their
operation since they in fact didn't need to pass struct device_node on
registration from the beginning.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Baolin Wang <[email protected]>
Cc: Daniel Mack <[email protected]>
Cc: Dan Murphy <[email protected]>
Cc: Linus Walleij <[email protected]>
Cc: Oleh Kravchenko <[email protected]>
Cc: Sakari Ailus <[email protected]>
Cc: Simon Shields <[email protected]>
Cc: Xiaotong Lu <[email protected]>
---
drivers/leds/led-class-flash.c | 9 +++++----
drivers/leds/led-class.c | 34 ++++++++++++++++++++++------------
drivers/leds/leds-cr0014114.c | 3 +--
drivers/leds/leds-gpio.c | 2 +-
include/linux/led-class-flash.h | 13 +++++++++----
include/linux/leds.h | 29 +++++++++++++++++++----------
6 files changed, 57 insertions(+), 33 deletions(-)
diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
index cf39827..8d1c117 100644
--- a/drivers/leds/led-class-flash.c
+++ b/drivers/leds/led-class-flash.c
@@ -285,8 +285,9 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev)
led_cdev->groups = flash_groups;
}
-int led_classdev_flash_register(struct device *parent,
- struct led_classdev_flash *fled_cdev)
+int led_classdev_flash_register_ext(struct device *parent,
+ struct led_classdev_flash *fled_cdev,
+ struct led_init_data *init_data)
{
struct led_classdev *led_cdev;
const struct led_flash_ops *ops;
@@ -312,13 +313,13 @@ int led_classdev_flash_register(struct device *parent,
}
/* Register led class device */
- ret = led_classdev_register(parent, led_cdev);
+ ret = led_classdev_register_ext(parent, led_cdev, init_data);
if (ret < 0)
return ret;
return 0;
}
-EXPORT_SYMBOL_GPL(led_classdev_flash_register);
+EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext);
void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
{
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 3c7e348..8c80763 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -17,6 +17,7 @@
#include <linux/leds.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
@@ -244,18 +245,25 @@ static int led_classdev_next_name(const char *init_name, char *name,
}
/**
- * of_led_classdev_register - register a new object of led_classdev class.
+ * led_classdev_register_ext - register a new object of led_classdev class.
*
* @parent: parent of LED device
* @led_cdev: the led_classdev structure for this device.
- * @np: DT node describing this LED
+ * @init_data: LED class device initialization data
*/
-int of_led_classdev_register(struct device *parent, struct device_node *np,
- struct led_classdev *led_cdev)
+int led_classdev_register_ext(struct device *parent,
+ struct led_classdev *led_cdev,
+ struct led_init_data *init_data)
{
char name[LED_MAX_NAME_SIZE];
int ret;
+ if (init_data && init_data->name) {
+ led_cdev->name = init_data->name;
+ } else {
+ dev_info(parent, "init_data not available");
+ }
+
ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
if (ret < 0)
return ret;
@@ -268,7 +276,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
mutex_unlock(&led_cdev->led_access);
return PTR_ERR(led_cdev->dev);
}
- led_cdev->dev->of_node = np;
+ if (init_data && init_data->fwnode)
+ led_cdev->dev->of_node = to_of_node(init_data->fwnode);
if (ret)
dev_warn(parent, "Led %s renamed to %s due to name collision",
@@ -313,7 +322,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
return 0;
}
-EXPORT_SYMBOL_GPL(of_led_classdev_register);
+EXPORT_SYMBOL_GPL(led_classdev_register_ext);
/**
* led_classdev_unregister - unregisters a object of led_properties class.
@@ -358,14 +367,15 @@ static void devm_led_classdev_release(struct device *dev, void *res)
}
/**
- * devm_of_led_classdev_register - resource managed led_classdev_register()
+ * devm_led_classdev_register_ext - resource managed led_classdev_register_ext()
*
* @parent: parent of LED device
* @led_cdev: the led_classdev structure for this device.
+ * @init_data: LED class device initialization data
*/
-int devm_of_led_classdev_register(struct device *parent,
- struct device_node *np,
- struct led_classdev *led_cdev)
+int devm_led_classdev_register_ext(struct device *parent,
+ struct led_classdev *led_cdev,
+ struct led_init_data *init_data)
{
struct led_classdev **dr;
int rc;
@@ -374,7 +384,7 @@ int devm_of_led_classdev_register(struct device *parent,
if (!dr)
return -ENOMEM;
- rc = of_led_classdev_register(parent, np, led_cdev);
+ rc = led_classdev_register_ext(parent, led_cdev, init_data);
if (rc) {
devres_free(dr);
return rc;
@@ -385,7 +395,7 @@ int devm_of_led_classdev_register(struct device *parent,
return 0;
}
-EXPORT_SYMBOL_GPL(devm_of_led_classdev_register);
+EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext);
static int devm_led_classdev_match(struct device *dev, void *res, void *data)
{
diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
index 0e42624..1c82152 100644
--- a/drivers/leds/leds-cr0014114.c
+++ b/drivers/leds/leds-cr0014114.c
@@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
led->ldev.brightness_set_blocking = cr0014114_set_sync;
- ret = devm_of_led_classdev_register(priv->dev, np,
- &led->ldev);
+ ret = devm_led_classdev_register(priv->dev, &led->ldev);
if (ret) {
dev_err(priv->dev,
"failed to register LED device %s, err %d",
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 32fa752..c87fbd3 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -112,7 +112,7 @@ static int create_gpio_led(const struct gpio_led *template,
if (ret < 0)
return ret;
- return devm_of_led_classdev_register(parent, np, &led_dat->cdev);
+ return devm_led_classdev_register(parent, &led_dat->cdev);
}
struct gpio_leds_priv {
diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h
index 700efaa..28a73d0 100644
--- a/include/linux/led-class-flash.h
+++ b/include/linux/led-class-flash.h
@@ -90,15 +90,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev(
}
/**
- * led_classdev_flash_register - register a new object of led_classdev class
- * with support for flash LEDs
+ * fwnode_led_classdev_flash_register - register a new object of led_classdev
+ * class with support for flash LEDs
* @parent: the flash LED to register
+ * @fwnode: the flash LED fwnode handle
* @fled_cdev: the led_classdev_flash structure for this device
*
* Returns: 0 on success or negative error value on failure
*/
-extern int led_classdev_flash_register(struct device *parent,
- struct led_classdev_flash *fled_cdev);
+extern 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)
/**
* led_classdev_flash_unregister - unregisters an object of led_classdev class
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 834683d..646c49a 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -20,6 +20,7 @@
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <uapi/linux/uleds.h>
struct device;
/*
@@ -33,6 +34,13 @@ enum led_brightness {
LED_FULL = 255,
};
+struct led_init_data {
+ /* Device fwnode handle */
+ struct fwnode_handle *fwnode;
+ /* Requested LED class device name */
+ char name[LED_MAX_NAME_SIZE];
+};
+
struct led_classdev {
const char *name;
enum led_brightness brightness;
@@ -73,6 +81,7 @@ struct led_classdev {
*/
int (*brightness_set_blocking)(struct led_classdev *led_cdev,
enum led_brightness brightness);
+
/* Get LED brightness level */
enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
@@ -123,16 +132,16 @@ struct led_classdev {
struct mutex led_access;
};
-extern int of_led_classdev_register(struct device *parent,
- struct device_node *np,
- struct led_classdev *led_cdev);
-#define led_classdev_register(parent, led_cdev) \
- of_led_classdev_register(parent, NULL, led_cdev)
-extern int devm_of_led_classdev_register(struct device *parent,
- struct device_node *np,
- struct led_classdev *led_cdev);
-#define devm_led_classdev_register(parent, led_cdev) \
- devm_of_led_classdev_register(parent, NULL, led_cdev)
+extern int led_classdev_register_ext(struct device *parent,
+ struct led_classdev *led_cdev,
+ struct led_init_data *init_data);
+#define led_classdev_register(parent, led_cdev) \
+ led_classdev_register_ext(parent, led_cdev, NULL)
+extern int devm_led_classdev_register_ext(struct device *parent,
+ struct led_classdev *led_cdev,
+ struct led_init_data *init_data);
+#define devm_led_classdev_register(parent, led_cdev) \
+ 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);
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Oleh Kravchenko <[email protected]>
---
drivers/leds/leds-cr0014114.c | 29 ++++++++++-------------------
1 file changed, 10 insertions(+), 19 deletions(-)
diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
index 1c82152..0aee979 100644
--- a/drivers/leds/leds-cr0014114.c
+++ b/drivers/leds/leds-cr0014114.c
@@ -8,7 +8,6 @@
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
-#include <uapi/linux/uleds.h>
/*
* CR0014114 SPI protocol descrtiption:
@@ -40,8 +39,9 @@
#define CR_FW_DELAY_MSEC 10
#define CR_RECOUNT_DELAY (HZ * 3600)
+#define CR_DEV_NAME "cr0014114"
+
struct cr0014114_led {
- char name[LED_MAX_NAME_SIZE];
struct cr0014114 *priv;
struct led_classdev ldev;
u8 brightness;
@@ -167,8 +167,7 @@ static int cr0014114_set_sync(struct led_classdev *ldev,
struct cr0014114_led,
ldev);
- dev_dbg(led->priv->dev, "Set brightness of %s to %d\n",
- led->name, brightness);
+ dev_dbg(led->priv->dev, "Set brightness to %d\n", brightness);
mutex_lock(&led->priv->lock);
led->brightness = (u8)brightness;
@@ -183,41 +182,33 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
size_t i = 0;
struct cr0014114_led *led;
struct fwnode_handle *child;
- struct device_node *np;
+ struct led_init_data init_data;
int ret;
- const char *str;
device_for_each_child_node(priv->dev, child) {
- np = to_of_node(child);
led = &priv->leds[i];
+ init_data.fwnode = child;
- ret = fwnode_property_read_string(child, "label", &str);
+ ret = led_compose_name(child, CR_DEV_NAME, ":", init_data.name);
if (ret)
- snprintf(led->name, sizeof(led->name),
- "cr0014114::");
- else
- snprintf(led->name, sizeof(led->name),
- "cr0014114:%s", str);
+ return ret;
fwnode_property_read_string(child, "linux,default-trigger",
&led->ldev.default_trigger);
led->priv = priv;
- led->ldev.name = led->name;
led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
led->ldev.brightness_set_blocking = cr0014114_set_sync;
- ret = devm_led_classdev_register(priv->dev, &led->ldev);
+ 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->name, ret);
+ "failed to register LED device , err %d", ret);
fwnode_handle_put(child);
return ret;
}
- led->ldev.dev->of_node = np;
-
i++;
}
--
2.1.4
Switch to using generic LED support for composing LED class
device name.
Signed-off-by: Jacek Anaszewski <[email protected]>
Signed-off-by: Daniel Mack <[email protected]>
---
drivers/leds/leds-lt3593.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index de3623e..d005abc 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -10,10 +10,10 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <uapi/linux/uleds.h>
+
+#define LED_LT3593_NAME "lt3593"
struct lt3593_led_data {
- char name[LED_MAX_NAME_SIZE];
struct led_classdev cdev;
struct gpio_desc *gpiod;
};
@@ -111,6 +111,7 @@ static int lt3593_led_probe(struct platform_device *pdev)
struct fwnode_handle *child;
int ret, state = LEDS_GPIO_DEFSTATE_OFF;
enum gpiod_flags flags = GPIOD_OUT_LOW;
+ struct led_init_data init_data;
const char *tmp;
if (dev_get_platdata(dev)) {
@@ -138,14 +139,11 @@ static int lt3593_led_probe(struct platform_device *pdev)
return PTR_ERR(led_data->gpiod);
child = device_get_next_child_node(dev, NULL);
+ init_data.fwnode = child;
- ret = fwnode_property_read_string(child, "label", &tmp);
- if (ret < 0)
- snprintf(led_data->name, sizeof(led_data->name),
- "lt3593::");
- else
- snprintf(led_data->name, sizeof(led_data->name),
- "lt3593:%s", tmp);
+ ret = led_compose_name(child, LED_LT3593_NAME, ":", init_data.name);
+ if (ret)
+ return ret;
fwnode_property_read_string(child, "linux,default-trigger",
&led_data->cdev.default_trigger);
@@ -160,11 +158,10 @@ static int lt3593_led_probe(struct platform_device *pdev)
}
}
- led_data->cdev.name = led_data->name;
led_data->cdev.brightness_set_blocking = lt3593_led_set;
led_data->cdev.brightness = state ? LED_FULL : LED_OFF;
- ret = devm_led_classdev_register(dev, &led_data->cdev);
+ ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data);
if (ret < 0) {
fwnode_handle_put(child);
return ret;
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Daniel Mack <[email protected]>
---
Documentation/devicetree/bindings/leds/leds-lt3593.txt | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-lt3593.txt b/Documentation/devicetree/bindings/leds/leds-lt3593.txt
index 6b2cabc..1d87c73 100644
--- a/Documentation/devicetree/bindings/leds/leds-lt3593.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lt3593.txt
@@ -9,8 +9,10 @@ The hardware supports only one LED. The properties of this LED are
configured in a sub-node in the device node.
Optional sub-node properties:
-- label: A label for the LED. If none is given, the LED will be
- named "lt3595::".
+- function: See Documentation/devicetree/bindings/leds/common.txt
+- color: See Documentation/devicetree/bindings/leds/common.txt
+- label: A label for the LED. If none is given, the LED will be
+ named "lt3595::" (deprecated)
- linux,default-trigger: The default trigger for the LED.
See Documentation/devicetree/bindings/leds/common.txt
- default-state: The initial state of the LED.
@@ -21,12 +23,15 @@ be handled by its own device node.
Example:
+#include <dt-bindings/leds/functions.h>
+
led-controller {
compatible = "lltc,lt3593";
lltc,ctrl-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
led {
- label = "white:backlight";
+ function = LED_FUNCTION_BACKLIGHT;
+ color = "white";
default-state = "on";
};
};
--
2.1.4
Refer to new "function" and "color" properties and mark "label"
as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Xiaotong Lu <[email protected]>
Cc: Baolin Wang <[email protected]>
---
Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt b/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt
index dddf84f..5177479 100644
--- a/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt
+++ b/Documentation/devicetree/bindings/leds/leds-sc27xx-bltc.txt
@@ -14,7 +14,9 @@ Required child properties:
- reg: Port this LED is connected to.
Optional child properties:
-- label: See Documentation/devicetree/bindings/leds/common.txt.
+- function: See Documentation/devicetree/bindings/leds/common.txt.
+- color: See Documentation/devicetree/bindings/leds/common.txt.
+- label: See Documentation/devicetree/bindings/leds/common.txt (deprecated).
Examples:
@@ -25,17 +27,17 @@ led-controller@200 {
reg = <0x200>;
led@0 {
- label = "red";
+ color = "red";
reg = <0x0>;
};
led@1 {
- label = "green";
+ color = "green";
reg = <0x1>;
};
led@2 {
- label = "blue";
+ color = "blue";
reg = <0x2>;
};
};
--
2.1.4
Introduce dedicated properties for conveying information about
LED function and color. Mark old "label" property as deprecated.
Signed-off-by: Jacek Anaszewski <[email protected]>
Cc: Baolin Wang <[email protected]>
Cc: Daniel Mack <[email protected]>
Cc: Dan Murphy <[email protected]>
Cc: Linus Walleij <[email protected]>
Cc: Oleh Kravchenko <[email protected]>
Cc: Sakari Ailus <[email protected]>
Cc: Simon Shields <[email protected]>
Cc: Xiaotong Lu <[email protected]>
---
Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
1 file changed, 44 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
index aa13998..3efc826 100644
--- a/Documentation/devicetree/bindings/leds/common.txt
+++ b/Documentation/devicetree/bindings/leds/common.txt
@@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
have to be tightly coupled with the LED device binding. They are represented
by child nodes of the parent LED device binding.
+
Optional properties for child nodes:
- led-sources : List of device current outputs the LED is connected to. The
outputs are identified by the numbers that must be defined
in the LED device binding documentation.
+- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
+ from the header include/dt-bindings/leds/functions.h.
+ If there is no matching LED_FUNCTION available, add a new one.
+- color : Color of the LED.
- label : The label for this LED. If omitted, the label is taken from the node
name (excluding the unit address). It has to uniquely identify
a device, i.e. no other LED class device can be assigned the same
- label.
+ label. This property is deprecated - use 'function' and 'color'
+ properties instead.
- default-state : The initial state of the LED. Valid values are "on", "off",
and "keep". If the LED is already on or off and the default-state property is
@@ -87,29 +93,59 @@ Required properties for trigger source:
* Examples
-gpio-leds {
+#include <dt-bindings/leds/functions.h>
+
+led-controller@0 {
compatible = "gpio-leds";
- system-status {
- label = "Status";
+ led0 {
+ function = LED_FUNCTION_STATUS;
linux,default-trigger = "heartbeat";
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
};
- usb {
+ led1 {
+ function = LED_FUNCTION_USB;
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>;
};
};
-max77693-led {
+led-controller@0 {
compatible = "maxim,max77693-led";
- camera-flash {
- label = "Flash";
+ led {
+ function = LED_FUNCTION_FLASH;
+ color = "white";
led-sources = <0>, <1>;
led-max-microamp = <50000>;
flash-max-microamp = <320000>;
flash-max-timeout-us = <500000>;
};
};
+
+led-controller@68 {
+ compatible = "ti,tlc59116";
+ reg = <0x68>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ function = LED_FUNCTION_WAN;
+ color = "amber";
+ reg = <0x0>;
+ };
+
+ led@2 {
+ function = LED_FUNCTION_2G;
+ color = "white";
+ reg = <0x2>;
+ };
+
+ led@9 {
+ function = LED_FUNCTION_ALIVE;
+ color = "green";
+ reg = <0x9>;
+ linux,default_trigger = "heartbeat";
+ };
+};
--
2.1.4
Hi Jacek,
On 7 November 2018 at 06:07, Jacek Anaszewski
<[email protected]> wrote:
> Replace of_led_classdev_register() with led_classdev_register_ext(), which
> accepts easily extendable struct led_init_data, instead of the fixed
> struct device_node argument. The latter can be now passed in a fwnode
> property of the struct led_init_data.
>
> The modification is driven by the need for passing another argument
> to the LED class initialization function - a LED class device name.
> Currently it is conveyed in the "name" char pointer property of
> struct led_classdev, which is semantically and functionally incorrect
> since it is needed only on LED class device registration, but persists
> in system memory throughout the whole LED class device lifetime.
>
> Whereas in case of the name strings coming from DT "label" property or
> statically initialized ones the cost is only the pointer size, it grows
> to LED_MAX_NAME_SIZE (64) with the advent of a new LED class device naming
> scheme, where color and function properties come from separate board
> firmware properties and the name needs to be constructed in a new buffer.
>
> The change will not break any existing clients since the patch alters
> also existing led_classdev{_flash}_register() macro wrappers, that pass
> NULL in place of init_data, which leads to using legacy name
> initialization path basing on the struct led_classdev's "name" property.
>
> Two existing users of devm_of_led_classdev_registers() are modified
> to use devm_led_classdev_register(), which will not impact their
> operation since they in fact didn't need to pass struct device_node on
> registration from the beginning.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> drivers/leds/led-class-flash.c | 9 +++++----
> drivers/leds/led-class.c | 34 ++++++++++++++++++++++------------
> drivers/leds/leds-cr0014114.c | 3 +--
> drivers/leds/leds-gpio.c | 2 +-
> include/linux/led-class-flash.h | 13 +++++++++----
> include/linux/leds.h | 29 +++++++++++++++++++----------
> 6 files changed, 57 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
> index cf39827..8d1c117 100644
> --- a/drivers/leds/led-class-flash.c
> +++ b/drivers/leds/led-class-flash.c
> @@ -285,8 +285,9 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev)
> led_cdev->groups = flash_groups;
> }
>
> -int led_classdev_flash_register(struct device *parent,
> - struct led_classdev_flash *fled_cdev)
> +int led_classdev_flash_register_ext(struct device *parent,
> + struct led_classdev_flash *fled_cdev,
> + struct led_init_data *init_data)
> {
> struct led_classdev *led_cdev;
> const struct led_flash_ops *ops;
> @@ -312,13 +313,13 @@ int led_classdev_flash_register(struct device *parent,
> }
>
> /* Register led class device */
> - ret = led_classdev_register(parent, led_cdev);
> + ret = led_classdev_register_ext(parent, led_cdev, init_data);
> if (ret < 0)
> return ret;
>
> return 0;
> }
> -EXPORT_SYMBOL_GPL(led_classdev_flash_register);
> +EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext);
>
> void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
> {
> diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
> index 3c7e348..8c80763 100644
> --- a/drivers/leds/led-class.c
> +++ b/drivers/leds/led-class.c
> @@ -17,6 +17,7 @@
> #include <linux/leds.h>
> #include <linux/list.h>
> #include <linux/module.h>
> +#include <linux/of.h>
> #include <linux/slab.h>
> #include <linux/spinlock.h>
> #include <linux/timer.h>
> @@ -244,18 +245,25 @@ static int led_classdev_next_name(const char *init_name, char *name,
> }
>
> /**
> - * of_led_classdev_register - register a new object of led_classdev class.
> + * led_classdev_register_ext - register a new object of led_classdev class.
> *
> * @parent: parent of LED device
> * @led_cdev: the led_classdev structure for this device.
> - * @np: DT node describing this LED
> + * @init_data: LED class device initialization data
> */
> -int of_led_classdev_register(struct device *parent, struct device_node *np,
> - struct led_classdev *led_cdev)
> +int led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data)
> {
> char name[LED_MAX_NAME_SIZE];
> int ret;
>
> + if (init_data && init_data->name) {
> + led_cdev->name = init_data->name;
> + } else {
> + dev_info(parent, "init_data not available");
> + }
> +
> ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
> if (ret < 0)
> return ret;
> @@ -268,7 +276,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
> mutex_unlock(&led_cdev->led_access);
> return PTR_ERR(led_cdev->dev);
> }
> - led_cdev->dev->of_node = np;
> + if (init_data && init_data->fwnode)
> + led_cdev->dev->of_node = to_of_node(init_data->fwnode);
>
> if (ret)
> dev_warn(parent, "Led %s renamed to %s due to name collision",
> @@ -313,7 +322,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
>
> return 0;
> }
> -EXPORT_SYMBOL_GPL(of_led_classdev_register);
> +EXPORT_SYMBOL_GPL(led_classdev_register_ext);
>
> /**
> * led_classdev_unregister - unregisters a object of led_properties class.
> @@ -358,14 +367,15 @@ static void devm_led_classdev_release(struct device *dev, void *res)
> }
>
> /**
> - * devm_of_led_classdev_register - resource managed led_classdev_register()
> + * devm_led_classdev_register_ext - resource managed led_classdev_register_ext()
> *
> * @parent: parent of LED device
> * @led_cdev: the led_classdev structure for this device.
> + * @init_data: LED class device initialization data
> */
> -int devm_of_led_classdev_register(struct device *parent,
> - struct device_node *np,
> - struct led_classdev *led_cdev)
> +int devm_led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data)
> {
> struct led_classdev **dr;
> int rc;
> @@ -374,7 +384,7 @@ int devm_of_led_classdev_register(struct device *parent,
> if (!dr)
> return -ENOMEM;
>
> - rc = of_led_classdev_register(parent, np, led_cdev);
> + rc = led_classdev_register_ext(parent, led_cdev, init_data);
> if (rc) {
> devres_free(dr);
> return rc;
> @@ -385,7 +395,7 @@ int devm_of_led_classdev_register(struct device *parent,
>
> return 0;
> }
> -EXPORT_SYMBOL_GPL(devm_of_led_classdev_register);
> +EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext);
>
> static int devm_led_classdev_match(struct device *dev, void *res, void *data)
> {
> diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
> index 0e42624..1c82152 100644
> --- a/drivers/leds/leds-cr0014114.c
> +++ b/drivers/leds/leds-cr0014114.c
> @@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
> led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
> led->ldev.brightness_set_blocking = cr0014114_set_sync;
>
> - ret = devm_of_led_classdev_register(priv->dev, np,
> - &led->ldev);
> + ret = devm_led_classdev_register(priv->dev, &led->ldev);
> if (ret) {
> dev_err(priv->dev,
> "failed to register LED device %s, err %d",
> diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
> index 32fa752..c87fbd3 100644
> --- a/drivers/leds/leds-gpio.c
> +++ b/drivers/leds/leds-gpio.c
> @@ -112,7 +112,7 @@ static int create_gpio_led(const struct gpio_led *template,
> if (ret < 0)
> return ret;
>
> - return devm_of_led_classdev_register(parent, np, &led_dat->cdev);
> + return devm_led_classdev_register(parent, &led_dat->cdev);
> }
>
> struct gpio_leds_priv {
> diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h
> index 700efaa..28a73d0 100644
> --- a/include/linux/led-class-flash.h
> +++ b/include/linux/led-class-flash.h
> @@ -90,15 +90,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev(
> }
>
> /**
> - * led_classdev_flash_register - register a new object of led_classdev class
> - * with support for flash LEDs
> + * fwnode_led_classdev_flash_register - register a new object of led_classdev
s/fwnode_led_classdev_flash_register/led_classdev_flash_register_ext
> + * class with support for flash LEDs
> * @parent: the flash LED to register
> + * @fwnode: the flash LED fwnode handle
s/fwnode/init_data
> * @fled_cdev: the led_classdev_flash structure for this device
> *
> * Returns: 0 on success or negative error value on failure
> */
> -extern int led_classdev_flash_register(struct device *parent,
> - struct led_classdev_flash *fled_cdev);
> +extern 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)
>
> /**
> * led_classdev_flash_unregister - unregisters an object of led_classdev class
> diff --git a/include/linux/leds.h b/include/linux/leds.h
> index 834683d..646c49a 100644
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -20,6 +20,7 @@
> #include <linux/spinlock.h>
> #include <linux/timer.h>
> #include <linux/workqueue.h>
> +#include <uapi/linux/uleds.h>
>
> struct device;
> /*
> @@ -33,6 +34,13 @@ enum led_brightness {
> LED_FULL = 255,
> };
>
> +struct led_init_data {
> + /* Device fwnode handle */
> + struct fwnode_handle *fwnode;
> + /* Requested LED class device name */
> + char name[LED_MAX_NAME_SIZE];
> +};
> +
> struct led_classdev {
> const char *name;
> enum led_brightness brightness;
> @@ -73,6 +81,7 @@ struct led_classdev {
> */
> int (*brightness_set_blocking)(struct led_classdev *led_cdev,
> enum led_brightness brightness);
> +
Unrelated change.
> /* Get LED brightness level */
> enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
>
> @@ -123,16 +132,16 @@ struct led_classdev {
> struct mutex led_access;
> };
>
> -extern int of_led_classdev_register(struct device *parent,
> - struct device_node *np,
> - struct led_classdev *led_cdev);
> -#define led_classdev_register(parent, led_cdev) \
> - of_led_classdev_register(parent, NULL, led_cdev)
> -extern int devm_of_led_classdev_register(struct device *parent,
> - struct device_node *np,
> - struct led_classdev *led_cdev);
> -#define devm_led_classdev_register(parent, led_cdev) \
> - devm_of_led_classdev_register(parent, NULL, led_cdev)
> +extern int led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data);
> +#define led_classdev_register(parent, led_cdev) \
> + led_classdev_register_ext(parent, led_cdev, NULL)
> +extern int devm_led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data);
> +#define devm_led_classdev_register(parent, led_cdev) \
> + 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);
> --
> 2.1.4
>
It can work well for SC27XX LED, FWIW you can add my tested tag.
Tested-by: Baolin Wang <[email protected]>
--
Baolin Wang
Best Regards
Hi Jacek,
On 7 November 2018 at 06:07, Jacek Anaszewski
<[email protected]> wrote:
> Add public led_compose_name() API for composing LED class device
> name basing on fwnode_handle data. The function composes device name
> according to either a new <color:function> pattern or the legacy
> <devicename:color:function> pattern. The decision on using the
> particular pattern is made basing on whether fwnode contains new
> "function" and "color" properties, or the legacy "label" proeprty.
>
> Backwards compatibility with in-driver hard-coded LED class device
> names is assured thanks to the default_desc argument.
>
> In case none of the aformentioned properties was found, then, for OF
> nodes, the node name is adopted for LED class device name.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> Documentation/leds/leds-class.txt | 2 +-
> drivers/leds/led-core.c | 71 +++++++++++++++++++++++++++++++++++++++
> include/linux/leds.h | 32 ++++++++++++++++++
> 3 files changed, 104 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
> index 836cb16..e9009c4 100644
> --- a/Documentation/leds/leds-class.txt
> +++ b/Documentation/leds/leds-class.txt
> @@ -43,7 +43,7 @@ LED Device Naming
>
> Is currently of the form:
>
> -"devicename:colour:function"
> +"colour:function"
>
> There have been calls for LED properties such as colour to be exported as
> individual led class attributes. As a solution which doesn't incur as much
> diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
> index ede4fa0..f7371fc 100644
> --- a/drivers/leds/led-core.c
> +++ b/drivers/leds/led-core.c
> @@ -16,6 +16,8 @@
> #include <linux/list.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/property.h>
> #include <linux/rwsem.h>
> #include "leds.h"
>
> @@ -327,3 +329,72 @@ void led_sysfs_enable(struct led_classdev *led_cdev)
> led_cdev->flags &= ~LED_SYSFS_DISABLE;
> }
> EXPORT_SYMBOL_GPL(led_sysfs_enable);
> +
> +static void led_parse_properties(struct fwnode_handle *fwnode,
> + struct led_properties *props)
> +{
> + int ret;
> +
> + if (!fwnode)
> + return;
> +
> + ret = fwnode_property_read_string(fwnode, "label", &props->label);
> + if (!ret)
> + return;
> +
> + ret = fwnode_property_read_string(fwnode, "function", &props->function);
> + if (ret)
> + pr_info("Failed to parse function property\n");
> +
> + ret = fwnode_property_read_string(fwnode, "color", &props->color);
> + if (ret)
> + pr_info("Failed to parse color property\n");
Now the color and function properties can be optional, so we should
deal with different return errors.
-EINVAL means we have not set color or function property, which means
we should not give failure message for users (maybe "not supply color
property\n") and return 0 as success.
For other errors, we should not ignore them, instead we should give
failure messages and return errors.
Tested-by: Baolin Wang <[email protected]>
> +}
> +
> +int led_compose_name(struct fwnode_handle *fwnode, const char *led_hw_name,
> + const char *default_desc, char *led_classdev_name)
> +{
> + struct led_properties props = {};
> +
> + if (!led_classdev_name)
> + return -EINVAL;
> +
> + led_parse_properties(fwnode, &props);
> +
> + if (props.label) {
> + /*
> + * Presence of 'label' DT property implies legacy LED name,
> + * formatted as <devicename:color:function>, with possible
> + * section omission if doesn't apply to given device.
> + *
> + * If no led_hw_name has been passed, then it indicates that
> + * DT label should be used as-is for LED class device name.
> + * Otherwise the label is prepended with led_hw_name to compose
> + * the final LED class device name.
> + */
> + if (!led_hw_name) {
> + strncpy(led_classdev_name, props.label,
> + LED_MAX_NAME_SIZE);
> + } else {
> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
> + led_hw_name, props.label);
> + }
> + } else if (props.function || props.color) {
> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
> + props.color ?: "", props.function ?: "");
> + } else if (default_desc) {
> + if (!led_hw_name) {
> + pr_err("Legacy LED naming requires devicename segment");
> + return -EINVAL;
> + }
> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
> + led_hw_name, default_desc);
> + } else if (is_of_node(fwnode)) {
> + strncpy(led_classdev_name, to_of_node(fwnode)->name,
> + LED_MAX_NAME_SIZE);
> + } else
> + return -EINVAL;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(led_compose_name);
> diff --git a/include/linux/leds.h b/include/linux/leds.h
> index 646c49a..ddb4001 100644
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -238,6 +238,32 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
> extern void led_sysfs_enable(struct led_classdev *led_cdev);
>
> /**
> + * led_compose_name - compose LED class device name
> + * @child: child fwnode_handle describing a LED,
> + * or a group of synchronized LEDs.
> + * @led_hw_name: name of the LED controller, used when falling back to legacy
> + * LED naming; it should be set to NULL in new LED class drivers
> + * @default_desc: default <color:function> tuple, for backwards compatibility
> + * with in-driver hard-coded LED names used as a fallback when
> + * "label" DT property was absent; it should be set to NULL
> + * in new LED class drivers
> + * @led_classdev_name: composed LED class device name
> + *
> + * Create LED class device name basing on the configuration provided by the
> + * board firmware. The name can have a legacy form <devicename:color:function>,
> + * or a new form <color:function>. The latter is chosen if at least one of
> + * "color" or "function" properties is present in the fwnode, leaving the
> + * section blank if the related property is absent. The former is applied
> + * when legacy "label" property is present in the fwnode. In case none of the
> + * aformentioned properties was found, then, for OF nodes, the node name
> + * is adopted for LED class device name.
> + *
> + * Returns: 0 on success or negative error value on failure
> + */
> +extern int led_compose_name(struct fwnode_handle *child, const char *led_hw_name,
> + const char *default_desc, char *led_classdev_name);
> +
> +/**
> * led_sysfs_is_disabled - check if LED sysfs interface is disabled
> * @led_cdev: the LED to query
> *
> @@ -414,6 +440,12 @@ struct led_platform_data {
> struct led_info *leds;
> };
>
> +struct led_properties {
> + const char *color;
> + const char *function;
> + const char *label;
> +};
> +
> struct gpio_desc;
> typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
> unsigned long *delay_on,
> --
> 2.1.4
>
--
Baolin Wang
Best Regards
Hi Jacek,
On 7 November 2018 at 06:07, Jacek Anaszewski
<[email protected]> wrote:
> Switch to using generic LED support for composing LED class
> device name.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> Cc: Baolin Wang <[email protected]>
Thanks for simplifying the code, it can work well for SC27XX LED.
Tested-by: Baolin Wang <[email protected]>
> ---
> drivers/leds/leds-sc27xx-bltc.c | 23 ++++++++++-------------
> 1 file changed, 10 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/leds/leds-sc27xx-bltc.c b/drivers/leds/leds-sc27xx-bltc.c
> index 9d9b7aa..9fe7cb1 100644
> --- a/drivers/leds/leds-sc27xx-bltc.c
> +++ b/drivers/leds/leds-sc27xx-bltc.c
> @@ -6,7 +6,6 @@
> #include <linux/of.h>
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> -#include <uapi/linux/uleds.h>
>
> /* PMIC global control register definition */
> #define SC27XX_MODULE_EN0 0xc08
> @@ -36,7 +35,7 @@
> #define SC27XX_LEDS_MAX 3
>
> struct sc27xx_led {
> - char name[LED_MAX_NAME_SIZE];
> + struct fwnode_handle *fwnode;
> struct led_classdev ldev;
> struct sc27xx_led_priv *priv;
> u8 line;
> @@ -132,16 +131,22 @@ static int sc27xx_led_register(struct device *dev, struct sc27xx_led_priv *priv)
>
> for (i = 0; i < SC27XX_LEDS_MAX; i++) {
> struct sc27xx_led *led = &priv->leds[i];
> + struct led_init_data init_data = { led->fwnode };
>
> if (!led->active)
> continue;
>
> + err = led_compose_name(led->fwnode, "sc27xx", ":",
> + init_data.name);
> + if (err)
> + return err;
> +
> led->line = i;
> led->priv = priv;
> - led->ldev.name = led->name;
> led->ldev.brightness_set_blocking = sc27xx_led_set;
>
> - err = devm_led_classdev_register(dev, &led->ldev);
> + err = devm_led_classdev_register_ext(dev, &led->ldev,
> + &init_data);
> if (err)
> return err;
> }
> @@ -154,7 +159,6 @@ static int sc27xx_led_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct device_node *np = dev->of_node, *child;
> struct sc27xx_led_priv *priv;
> - const char *str;
> u32 base, count, reg;
> int err;
>
> @@ -196,15 +200,8 @@ static int sc27xx_led_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> + priv->leds[reg].fwnode = of_fwnode_handle(child);
> priv->leds[reg].active = true;
> -
> - err = of_property_read_string(child, "label", &str);
> - if (err)
> - snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE,
> - "sc27xx::");
> - else
> - snprintf(priv->leds[reg].name, LED_MAX_NAME_SIZE,
> - "sc27xx:%s", str);
> }
>
> err = sc27xx_led_register(dev, priv);
> --
> 2.1.4
>
--
Baolin Wang
Best Regards
On 6.11.2018 23:07, Jacek Anaszewski wrote:
> Add common LED function definitions for use in Device Tree.
> The function names were extracted from existing dts files
> after eliminating oddities.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> include/dt-bindings/leds/functions.h | 101 +++++++++++++++++++++++++++++++++++
> 1 file changed, 101 insertions(+)
> create mode 100644 include/dt-bindings/leds/functions.h
Hi Jacek,
Just nit picking. I think the subject should be:
"dt-bindings: leds: ..." to be consistent.
Best regards,
Michal
Hi Michal
On 11/07/2018 09:36 AM, Vokáč Michal wrote:
> On 6.11.2018 23:07, Jacek Anaszewski wrote:
>> Add common LED function definitions for use in Device Tree.
>> The function names were extracted from existing dts files
>> after eliminating oddities.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> include/dt-bindings/leds/functions.h | 101 +++++++++++++++++++++++++++++++++++
>> 1 file changed, 101 insertions(+)
>> create mode 100644 include/dt-bindings/leds/functions.h
>
> Hi Jacek,
> Just nit picking. I think the subject should be:
>
> "dt-bindings: leds: ..." to be consistent.
Thanks for the heads-up. I'll change it in the v2.
--
Best regards,
Jacek Anaszewski
On 6/11/2018 11:07 PM, Jacek Anaszewski wrote:
> Switch to using generic LED support for composing LED class
> device name.
Thanks for the rework!
> Signed-off-by: Jacek Anaszewski <[email protected]>
> ---
> drivers/leds/leds-lt3593.c | 19 ++++++++-----------
> 1 file changed, 8 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
> index de3623e..d005abc 100644
> --- a/drivers/leds/leds-lt3593.c
> +++ b/drivers/leds/leds-lt3593.c
> @@ -10,10 +10,10 @@
> #include <linux/slab.h>
> #include <linux/module.h>
> #include <linux/of.h>
> -#include <uapi/linux/uleds.h>
> +
> +#define LED_LT3593_NAME "lt3593"
>
> struct lt3593_led_data {
> - char name[LED_MAX_NAME_SIZE];
> struct led_classdev cdev;
> struct gpio_desc *gpiod;
> };
> @@ -111,6 +111,7 @@ static int lt3593_led_probe(struct platform_device *pdev)
> struct fwnode_handle *child;
> int ret, state = LEDS_GPIO_DEFSTATE_OFF;
> enum gpiod_flags flags = GPIOD_OUT_LOW;
> + struct led_init_data init_data;
> const char *tmp;
>
> if (dev_get_platdata(dev)) {
> @@ -138,14 +139,11 @@ static int lt3593_led_probe(struct platform_device *pdev)
> return PTR_ERR(led_data->gpiod);
>
> child = device_get_next_child_node(dev, NULL);
> + init_data.fwnode = child;
Not quite following. `fwnode' is the only member of that struct that is
initialized?
>
> - ret = fwnode_property_read_string(child, "label", &tmp);
> - if (ret < 0)
> - snprintf(led_data->name, sizeof(led_data->name),
> - "lt3593::");
> - else
> - snprintf(led_data->name, sizeof(led_data->name),
> - "lt3593:%s", tmp);
> + ret = led_compose_name(child, LED_LT3593_NAME, ":", init_data.name);
... and here, a member that wasn't written before is used? What am I
missing?
Thanks,
Daniel
On 11/07/2018 08:37 PM, Daniel Mack wrote:
> On 6/11/2018 11:07 PM, Jacek Anaszewski wrote:
>> Switch to using generic LED support for composing LED class
>> device name.
>
> Thanks for the rework!
>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> ---
>> drivers/leds/leds-lt3593.c | 19 ++++++++-----------
>> 1 file changed, 8 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
>> index de3623e..d005abc 100644
>> --- a/drivers/leds/leds-lt3593.c
>> +++ b/drivers/leds/leds-lt3593.c
>> @@ -10,10 +10,10 @@
>> #include <linux/slab.h>
>> #include <linux/module.h>
>> #include <linux/of.h>
>> -#include <uapi/linux/uleds.h>
>> +
>> +#define LED_LT3593_NAME "lt3593"
>> struct lt3593_led_data {
>> - char name[LED_MAX_NAME_SIZE];
>> struct led_classdev cdev;
>> struct gpio_desc *gpiod;
>> };
>> @@ -111,6 +111,7 @@ static int lt3593_led_probe(struct platform_device
>> *pdev)
>> struct fwnode_handle *child;
>> int ret, state = LEDS_GPIO_DEFSTATE_OFF;
>> enum gpiod_flags flags = GPIOD_OUT_LOW;
>> + struct led_init_data init_data;
>> const char *tmp;
>> if (dev_get_platdata(dev)) {
>> @@ -138,14 +139,11 @@ static int lt3593_led_probe(struct
>> platform_device *pdev)
>> return PTR_ERR(led_data->gpiod);
>> child = device_get_next_child_node(dev, NULL);
>> + init_data.fwnode = child;
>
> Not quite following. `fwnode' is the only member of that struct that is
> initialized?
>
>> - ret = fwnode_property_read_string(child, "label", &tmp);
>> - if (ret < 0)
>> - snprintf(led_data->name, sizeof(led_data->name),
>> - "lt3593::");
>> - else
>> - snprintf(led_data->name, sizeof(led_data->name),
>> - "lt3593:%s", tmp);
>> + ret = led_compose_name(child, LED_LT3593_NAME, ":", init_data.name);
>
> ... and here, a member that wasn't written before is used? What am I
> missing?
init_data.name pointer is passed to led_compose_name(), which fills
this array with the composed name.
--
Best regards,
Jacek Anaszewski
Hi Baolin,
Thanks for the review. Will address the remarks in a v2.
On 11/07/2018 07:55 AM, Baolin Wang wrote:
> Hi Jacek,
>
> On 7 November 2018 at 06:07, Jacek Anaszewski
[...]
>
> It can work well for SC27XX LED, FWIW you can add my tested tag.
> Tested-by: Baolin Wang <[email protected]>
>
--
Best regards,
Jacek Anaszewski
On 7/11/2018 8:49 PM, Jacek Anaszewski wrote:
> On 11/07/2018 08:37 PM, Daniel Mack wrote:
>> On 6/11/2018 11:07 PM, Jacek Anaszewski wrote:
>>> Switch to using generic LED support for composing LED class
>>> device name.
>>
>> Thanks for the rework!
>>
>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>> ---
>>> drivers/leds/leds-lt3593.c | 19 ++++++++-----------
>>> 1 file changed, 8 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
>>> index de3623e..d005abc 100644
>>> --- a/drivers/leds/leds-lt3593.c
>>> +++ b/drivers/leds/leds-lt3593.c
>>> @@ -10,10 +10,10 @@
>>> #include <linux/slab.h>
>>> #include <linux/module.h>
>>> #include <linux/of.h>
>>> -#include <uapi/linux/uleds.h>
>>> +
>>> +#define LED_LT3593_NAME "lt3593"
>>> struct lt3593_led_data {
>>> - char name[LED_MAX_NAME_SIZE];
>>> struct led_classdev cdev;
>>> struct gpio_desc *gpiod;
>>> };
>>> @@ -111,6 +111,7 @@ static int lt3593_led_probe(struct platform_device
>>> *pdev)
>>> struct fwnode_handle *child;
>>> int ret, state = LEDS_GPIO_DEFSTATE_OFF;
>>> enum gpiod_flags flags = GPIOD_OUT_LOW;
>>> + struct led_init_data init_data;
>>> const char *tmp;
>>> if (dev_get_platdata(dev)) {
>>> @@ -138,14 +139,11 @@ static int lt3593_led_probe(struct
>>> platform_device *pdev)
>>> return PTR_ERR(led_data->gpiod);
>>> child = device_get_next_child_node(dev, NULL);
>>> + init_data.fwnode = child;
>>
>> Not quite following. `fwnode' is the only member of that struct that is
>> initialized?
>>
>>> - ret = fwnode_property_read_string(child, "label", &tmp);
>>> - if (ret < 0)
>>> - snprintf(led_data->name, sizeof(led_data->name),
>>> - "lt3593::");
>>> - else
>>> - snprintf(led_data->name, sizeof(led_data->name),
>>> - "lt3593:%s", tmp);
>>> + ret = led_compose_name(child, LED_LT3593_NAME, ":", init_data.name);
>>
>> ... and here, a member that wasn't written before is used? What am I
>> missing?
>
> init_data.name pointer is passed to led_compose_name(), which fills
> this array with the composed name.
Ah, that's the target. Stupid me!
With this:
Acked-by: Daniel Mack <[email protected]>
Thanks,
Daniel
On Tue, Nov 6, 2018 at 4:07 PM Jacek Anaszewski
<[email protected]> wrote:
>
> Add common LED function definitions for use in Device Tree.
> The function names were extracted from existing dts files
> after eliminating oddities.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> include/dt-bindings/leds/functions.h | 101 +++++++++++++++++++++++++++++++++++
> 1 file changed, 101 insertions(+)
> create mode 100644 include/dt-bindings/leds/functions.h
>
> diff --git a/include/dt-bindings/leds/functions.h b/include/dt-bindings/leds/functions.h
> new file mode 100644
> index 0000000..3f94e09
> --- /dev/null
> +++ b/include/dt-bindings/leds/functions.h
> @@ -0,0 +1,101 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#define LED_FUNCTION_2G "2g"
> +#define LED_FUNCTION_ACTIVITY "activity"
> +#define LED_FUNCTION_ADSL "adsl"
> +#define LED_FUNCTION_ALARM "alarm"
> +#define LED_FUNCTION_ALIVE "alive"
> +#define LED_FUNCTION_ALL "all"
> +#define LED_FUNCTION_APP "app"
> +#define LED_FUNCTION_AUX "aux"
> +#define LED_FUNCTION_BACKUP "backup"
> +#define LED_FUNCTION_BACKLIGHT "backlight"
> +#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
I'd prefer we go further and only define 1 endorsed function name.
Backlight, disk, network, fault/error all seem to have a few
duplicates. I'm also thinking the functions make linux,default-trigger
redundant in some cases.
I'm not a huge fan of making these defines, but it does make it
perfectly clear if folks use standard names or not.
> +#define LED_FUNCTION_BEEP "beep"
> +#define LED_FUNCTION_BLUETOOTH "bluetooth"
> +#define LED_FUNCTION_BOOT "boot"
> +#define LED_FUNCTION_BOTTOM "bottom"
> +#define LED_FUNCTION_BRICK_STATUS "brick-status"
> +#define LED_FUNCTION_CEL "cel"
> +#define LED_FUNCTION_CEL_PWR "cel-pwr"
> +#define LED_FUNCTION_CEL_RESET "cel-reset"
> +#define LED_FUNCTION_CHRG "chrg"
> +#define LED_FUNCTION_COM "com"
> +#define LED_FUNCTION_COPY "copy"
> +#define LED_FUNCTION_CPU "cpu"
> +#define LED_FUNCTION_DEBUG "debug"
> +#define LED_FUNCTION_DIA "dia"
> +#define LED_FUNCTION_DISK "disk"
> +#define LED_FUNCTION_DISPLAY_CLUSTER "display_cluster"
> +#define LED_FUNCTION_DOWN "down"
> +#define LED_FUNCTION_DSL "dsl"
> +#define LED_FUNCTION_ENOCEAN "enocean"
> +#define LED_FUNCTION_ENTER "enter"
> +#define LED_FUNCTION_ERROR "error"
> +#define LED_FUNCTION_ESATA "esata"
> +#define LED_FUNCTION_ETHERNET_STATUS "ethernet-status"
> +#define LED_FUNCTION_FAIL "fail"
> +#define LED_FUNCTION_FAULT "fault"
> +#define LED_FUNCTION_FLASH "flash"
> +#define LED_FUNCTION_FRONT "front"
> +#define LED_FUNCTION_FUNC "func"
> +#define LED_FUNCTION_GPIO "gpio"
> +#define LED_FUNCTION_GSM "gsm"
> +#define LED_FUNCTION_HD "hd"
> +#define LED_FUNCTION_HDD "hdd"
> +#define LED_FUNCTION_HDDERR "hdderr"
> +#define LED_FUNCTION_HEALTH "health"
> +#define LED_FUNCTION_HEARTBEAT "heartbeat"
> +#define LED_FUNCTION_HOME "home"
> +#define LED_FUNCTION_INDICATOR "indicator"
> +#define LED_FUNCTION_INET "inet"
> +#define LED_FUNCTION_INFO "info"
> +#define LED_FUNCTION_INTERNET "internet"
> +#define LED_FUNCTION_KEYPAD "keypad"
> +#define LED_FUNCTION_LAN "lan"
> +#define LED_FUNCTION_LEFT "left"
> +#define LED_FUNCTION_LIVE "live"
> +#define LED_FUNCTION_MICROSD "microsd"
> +#define LED_FUNCTION_MISC "misc"
> +#define LED_FUNCTION_MMC "mmc"
> +#define LED_FUNCTION_NAND "nand"
> +#define LED_FUNCTION_NETWORK "network"
> +#define LED_FUNCTION_ON "on"
> +#define LED_FUNCTION_OS "os"
> +#define LED_FUNCTION_PANEL "panel"
> +#define LED_FUNCTION_PMU_STAT "pmu_stat"
> +#define LED_FUNCTION_PROG "prog"
> +#define LED_FUNCTION_PROGRAMMING "programming"
> +#define LED_FUNCTION_PULSE "pulse"
> +#define LED_FUNCTION_PWR "pwr"
> +#define LED_FUNCTION_QSS "qss"
> +#define LED_FUNCTION_REAR "rear"
> +#define LED_FUNCTION_REBUILD "rebuild"
> +#define LED_FUNCTION_RIGHT "right"
> +#define LED_FUNCTION_ROUTER "router"
> +#define LED_FUNCTION_RS "rs"
> +#define LED_FUNCTION_RX "rx"
> +#define LED_FUNCTION_SATA "sata"
> +#define LED_FUNCTION_SD "sd"
> +#define LED_FUNCTION_SLEEP "sleep"
> +#define LED_FUNCTION_STANDBY "standby"
> +#define LED_FUNCTION_STATUS "status"
> +#define LED_FUNCTION_SW "sw"
> +#define LED_FUNCTION_SWRDY "swrdy"
> +#define LED_FUNCTION_SYSTEM "system"
> +#define LED_FUNCTION_TEL "tel"
> +#define LED_FUNCTION_TOP "top"
> +#define LED_FUNCTION_TORCH "torch"
> +#define LED_FUNCTION_TV "tv"
> +#define LED_FUNCTION_TX "tx"
> +#define LED_FUNCTION_UP "up"
> +#define LED_FUNCTION_USB "usb"
> +#define LED_FUNCTION_USB_COPY "usb_copy"
> +#define LED_FUNCTION_USER "user"
> +#define LED_FUNCTION_USR "usr"
> +#define LED_FUNCTION_WAN "wan"
> +#define LED_FUNCTION_WIFI "wifi"
> +#define LED_FUNCTION_WIRELESS "wireless"
> +#define LED_FUNCTION_WLAN "wlan"
> +#define LED_FUNCTION_WMODE "wmode"
> +#define LED_FUNCTION_WPS "wps"
> --
> 2.1.4
>
Jacek
On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
> Replace of_led_classdev_register() with led_classdev_register_ext(), which
> accepts easily extendable struct led_init_data, instead of the fixed
> struct device_node argument. The latter can be now passed in a fwnode
> property of the struct led_init_data.
>
> The modification is driven by the need for passing another argument
> to the LED class initialization function - a LED class device name.
> Currently it is conveyed in the "name" char pointer property of
> struct led_classdev, which is semantically and functionally incorrect
> since it is needed only on LED class device registration, but persists
> in system memory throughout the whole LED class device lifetime.
>
> Whereas in case of the name strings coming from DT "label" property or
> statically initialized ones the cost is only the pointer size, it grows
> to LED_MAX_NAME_SIZE (64) with the advent of a new LED class device naming
> scheme, where color and function properties come from separate board
> firmware properties and the name needs to be constructed in a new buffer.
>
> The change will not break any existing clients since the patch alters
> also existing led_classdev{_flash}_register() macro wrappers, that pass
> NULL in place of init_data, which leads to using legacy name
> initialization path basing on the struct led_classdev's "name" property.
>
> Two existing users of devm_of_led_classdev_registers() are modified
> to use devm_led_classdev_register(), which will not impact their
> operation since they in fact didn't need to pass struct device_node on
> registration from the beginning.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> drivers/leds/led-class-flash.c | 9 +++++----
> drivers/leds/led-class.c | 34 ++++++++++++++++++++++------------
> drivers/leds/leds-cr0014114.c | 3 +--
> drivers/leds/leds-gpio.c | 2 +-
> include/linux/led-class-flash.h | 13 +++++++++----
> include/linux/leds.h | 29 +++++++++++++++++++----------
> 6 files changed, 57 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
> index cf39827..8d1c117 100644
> --- a/drivers/leds/led-class-flash.c
> +++ b/drivers/leds/led-class-flash.c
> @@ -285,8 +285,9 @@ static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev)
> led_cdev->groups = flash_groups;
> }
>
> -int led_classdev_flash_register(struct device *parent,
> - struct led_classdev_flash *fled_cdev)
> +int led_classdev_flash_register_ext(struct device *parent,
> + struct led_classdev_flash *fled_cdev,
> + struct led_init_data *init_data)
> {
> struct led_classdev *led_cdev;
> const struct led_flash_ops *ops;
> @@ -312,13 +313,13 @@ int led_classdev_flash_register(struct device *parent,
> }
>
> /* Register led class device */
> - ret = led_classdev_register(parent, led_cdev);
> + ret = led_classdev_register_ext(parent, led_cdev, init_data);
> if (ret < 0)
> return ret;
>
> return 0;
> }
> -EXPORT_SYMBOL_GPL(led_classdev_flash_register);
> +EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext);
>
> void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
> {
> diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
> index 3c7e348..8c80763 100644
> --- a/drivers/leds/led-class.c
> +++ b/drivers/leds/led-class.c
> @@ -17,6 +17,7 @@
> #include <linux/leds.h>
> #include <linux/list.h>
> #include <linux/module.h>
> +#include <linux/of.h>
> #include <linux/slab.h>
> #include <linux/spinlock.h>
> #include <linux/timer.h>
> @@ -244,18 +245,25 @@ static int led_classdev_next_name(const char *init_name, char *name,
> }
>
> /**
> - * of_led_classdev_register - register a new object of led_classdev class.
> + * led_classdev_register_ext - register a new object of led_classdev class.
For this should the comment indicate a different between the extended and non-extended calls?
Like the _ext might say register a new object of led_classdev with init_data?
Same comments for each addition below.
Otherwise with Baolin's comments for 1/24
Acked-by: Dan Murphy <[email protected]>
Dan
> *
> * @parent: parent of LED device
> * @led_cdev: the led_classdev structure for this device.
> - * @np: DT node describing this LED
> + * @init_data: LED class device initialization data
> */
> -int of_led_classdev_register(struct device *parent, struct device_node *np,
> - struct led_classdev *led_cdev)
> +int led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data)
> {
> char name[LED_MAX_NAME_SIZE];
> int ret;
>
> + if (init_data && init_data->name) {
> + led_cdev->name = init_data->name;
> + } else {
> + dev_info(parent, "init_data not available");
> + }
> +
> ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
> if (ret < 0)
> return ret;
> @@ -268,7 +276,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
> mutex_unlock(&led_cdev->led_access);
> return PTR_ERR(led_cdev->dev);
> }
> - led_cdev->dev->of_node = np;
> + if (init_data && init_data->fwnode)
> + led_cdev->dev->of_node = to_of_node(init_data->fwnode);
>
> if (ret)
> dev_warn(parent, "Led %s renamed to %s due to name collision",
> @@ -313,7 +322,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
>
> return 0;
> }
> -EXPORT_SYMBOL_GPL(of_led_classdev_register);
> +EXPORT_SYMBOL_GPL(led_classdev_register_ext);
>
> /**
> * led_classdev_unregister - unregisters a object of led_properties class.
> @@ -358,14 +367,15 @@ static void devm_led_classdev_release(struct device *dev, void *res)
> }
>
> /**
> - * devm_of_led_classdev_register - resource managed led_classdev_register()
> + * devm_led_classdev_register_ext - resource managed led_classdev_register_ext()
> *
> * @parent: parent of LED device
> * @led_cdev: the led_classdev structure for this device.
> + * @init_data: LED class device initialization data
> */
> -int devm_of_led_classdev_register(struct device *parent,
> - struct device_node *np,
> - struct led_classdev *led_cdev)
> +int devm_led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data)
> {
> struct led_classdev **dr;
> int rc;
> @@ -374,7 +384,7 @@ int devm_of_led_classdev_register(struct device *parent,
> if (!dr)
> return -ENOMEM;
>
> - rc = of_led_classdev_register(parent, np, led_cdev);
> + rc = led_classdev_register_ext(parent, led_cdev, init_data);
> if (rc) {
> devres_free(dr);
> return rc;
> @@ -385,7 +395,7 @@ int devm_of_led_classdev_register(struct device *parent,
>
> return 0;
> }
> -EXPORT_SYMBOL_GPL(devm_of_led_classdev_register);
> +EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext);
>
> static int devm_led_classdev_match(struct device *dev, void *res, void *data)
> {
> diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
> index 0e42624..1c82152 100644
> --- a/drivers/leds/leds-cr0014114.c
> +++ b/drivers/leds/leds-cr0014114.c
> @@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
> led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
> led->ldev.brightness_set_blocking = cr0014114_set_sync;
>
> - ret = devm_of_led_classdev_register(priv->dev, np,
> - &led->ldev);
> + ret = devm_led_classdev_register(priv->dev, &led->ldev);
> if (ret) {
> dev_err(priv->dev,
> "failed to register LED device %s, err %d",
> diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
> index 32fa752..c87fbd3 100644
> --- a/drivers/leds/leds-gpio.c
> +++ b/drivers/leds/leds-gpio.c
> @@ -112,7 +112,7 @@ static int create_gpio_led(const struct gpio_led *template,
> if (ret < 0)
> return ret;
>
> - return devm_of_led_classdev_register(parent, np, &led_dat->cdev);
> + return devm_led_classdev_register(parent, &led_dat->cdev);
> }
>
> struct gpio_leds_priv {
> diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h
> index 700efaa..28a73d0 100644
> --- a/include/linux/led-class-flash.h
> +++ b/include/linux/led-class-flash.h
> @@ -90,15 +90,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev(
> }
>
> /**
> - * led_classdev_flash_register - register a new object of led_classdev class
> - * with support for flash LEDs
> + * fwnode_led_classdev_flash_register - register a new object of led_classdev
> + * class with support for flash LEDs
> * @parent: the flash LED to register
> + * @fwnode: the flash LED fwnode handle
> * @fled_cdev: the led_classdev_flash structure for this device
> *
> * Returns: 0 on success or negative error value on failure
> */
> -extern int led_classdev_flash_register(struct device *parent,
> - struct led_classdev_flash *fled_cdev);
> +extern 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)
>
> /**
> * led_classdev_flash_unregister - unregisters an object of led_classdev class
> diff --git a/include/linux/leds.h b/include/linux/leds.h
> index 834683d..646c49a 100644
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -20,6 +20,7 @@
> #include <linux/spinlock.h>
> #include <linux/timer.h>
> #include <linux/workqueue.h>
> +#include <uapi/linux/uleds.h>
>
> struct device;
> /*
> @@ -33,6 +34,13 @@ enum led_brightness {
> LED_FULL = 255,
> };
>
> +struct led_init_data {
> + /* Device fwnode handle */
> + struct fwnode_handle *fwnode;
> + /* Requested LED class device name */
> + char name[LED_MAX_NAME_SIZE];
> +};
> +
> struct led_classdev {
> const char *name;
> enum led_brightness brightness;
> @@ -73,6 +81,7 @@ struct led_classdev {
> */
> int (*brightness_set_blocking)(struct led_classdev *led_cdev,
> enum led_brightness brightness);
> +
> /* Get LED brightness level */
> enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
>
> @@ -123,16 +132,16 @@ struct led_classdev {
> struct mutex led_access;
> };
>
> -extern int of_led_classdev_register(struct device *parent,
> - struct device_node *np,
> - struct led_classdev *led_cdev);
> -#define led_classdev_register(parent, led_cdev) \
> - of_led_classdev_register(parent, NULL, led_cdev)
> -extern int devm_of_led_classdev_register(struct device *parent,
> - struct device_node *np,
> - struct led_classdev *led_cdev);
> -#define devm_led_classdev_register(parent, led_cdev) \
> - devm_of_led_classdev_register(parent, NULL, led_cdev)
> +extern int led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data);
> +#define led_classdev_register(parent, led_cdev) \
> + led_classdev_register_ext(parent, led_cdev, NULL)
> +extern int devm_led_classdev_register_ext(struct device *parent,
> + struct led_classdev *led_cdev,
> + struct led_init_data *init_data);
> +#define devm_led_classdev_register(parent, led_cdev) \
> + 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);
>
--
------------------
Dan Murphy
Jacek
On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
> Introduce dedicated properties for conveying information about
> LED function and color. Mark old "label" property as deprecated.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
> 1 file changed, 44 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
> index aa13998..3efc826 100644
> --- a/Documentation/devicetree/bindings/leds/common.txt
> +++ b/Documentation/devicetree/bindings/leds/common.txt
> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
> have to be tightly coupled with the LED device binding. They are represented
> by child nodes of the parent LED device binding.
>
> +
> Optional properties for child nodes:
> - led-sources : List of device current outputs the LED is connected to. The
> outputs are identified by the numbers that must be defined
> in the LED device binding documentation.
> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
> + from the header include/dt-bindings/leds/functions.h.
> + If there is no matching LED_FUNCTION available, add a new one.
> +- color : Color of the LED.
Should we define the colors too? There are only really 4. Red, green, blue and white.
Generally varying colors are created base on the primary colors. Even the amber color
Dan
> - label : The label for this LED. If omitted, the label is taken from the node
> name (excluding the unit address). It has to uniquely identify
> a device, i.e. no other LED class device can be assigned the same
> - label.
> + label. This property is deprecated - use 'function' and 'color'
> + properties instead.
>
> - default-state : The initial state of the LED. Valid values are "on", "off",
> and "keep". If the LED is already on or off and the default-state property is
> @@ -87,29 +93,59 @@ Required properties for trigger source:
>
> * Examples
>
> -gpio-leds {
> +#include <dt-bindings/leds/functions.h>
> +
> +led-controller@0 {
> compatible = "gpio-leds";
>
> - system-status {
> - label = "Status";
> + led0 {
> + function = LED_FUNCTION_STATUS;
> linux,default-trigger = "heartbeat";
> gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
> };
>
> - usb {
> + led1 {
> + function = LED_FUNCTION_USB;
> gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
> trigger-sources = <&ohci_port1>, <&ehci_port1>;
> };
> };
>
> -max77693-led {
> +led-controller@0 {
> compatible = "maxim,max77693-led";
>
> - camera-flash {
> - label = "Flash";
> + led {
> + function = LED_FUNCTION_FLASH;
> + color = "white";
> led-sources = <0>, <1>;
> led-max-microamp = <50000>;
> flash-max-microamp = <320000>;
> flash-max-timeout-us = <500000>;
> };
> };
> +
> +led-controller@68 {
> + compatible = "ti,tlc59116";
> + reg = <0x68>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + led@0 {
> + function = LED_FUNCTION_WAN;
> + color = "amber";
> + reg = <0x0>;
> + };
> +
> + led@2 {
> + function = LED_FUNCTION_2G;
> + color = "white";
> + reg = <0x2>;
> + };
> +
> + led@9 {
> + function = LED_FUNCTION_ALIVE;
> + color = "green";
> + reg = <0x9>;
> + linux,default_trigger = "heartbeat";
> + };
> +};
>
--
------------------
Dan Murphy
On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
> Refer to new "function" and "color" properties and mark "label"
> as deprecated.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Dan Murphy <[email protected]>
> ---
Acked-by: Dan Murphy <[email protected]>
> Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
> index 08b3528..62c8fe5 100644
> --- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
> +++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt
> @@ -26,12 +26,16 @@ Required child properties:
> 3 - Will enable the LED3 sync (LM36923 only)
>
> Optional child properties:
> - - label : see Documentation/devicetree/bindings/leds/common.txt
> + - function : see Documentation/devicetree/bindings/leds/common.txt
> + - color : see Documentation/devicetree/bindings/leds/common.txt
> + - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated)
> - linux,default-trigger :
> see Documentation/devicetree/bindings/leds/common.txt
>
> Example:
>
> +#include <dt-bindings/leds/functions.h>
> +
> led-controller@36 {
> compatible = "ti,lm3692x";
> reg = <0x36>;
> @@ -43,7 +47,8 @@ led-controller@36 {
>
> led@0 {
> reg = <0>;
> - label = "white:backlight_cluster";
> + function = LED_BACKLIGHT_CLUSTER;
> + color = "white";
> linux,default-trigger = "backlight";
> };
> }
>
--
------------------
Dan Murphy
Hi Baolin,
Thanks for the review.
On 11/07/2018 08:20 AM, Baolin Wang wrote:
> Hi Jacek,
>
> On 7 November 2018 at 06:07, Jacek Anaszewski
> <[email protected]> wrote:
>> Add public led_compose_name() API for composing LED class device
>> name basing on fwnode_handle data. The function composes device name
>> according to either a new <color:function> pattern or the legacy
>> <devicename:color:function> pattern. The decision on using the
>> particular pattern is made basing on whether fwnode contains new
>> "function" and "color" properties, or the legacy "label" proeprty.
>>
>> Backwards compatibility with in-driver hard-coded LED class device
>> names is assured thanks to the default_desc argument.
>>
>> In case none of the aformentioned properties was found, then, for OF
>> nodes, the node name is adopted for LED class device name.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> Documentation/leds/leds-class.txt | 2 +-
>> drivers/leds/led-core.c | 71 +++++++++++++++++++++++++++++++++++++++
>> include/linux/leds.h | 32 ++++++++++++++++++
>> 3 files changed, 104 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
>> index 836cb16..e9009c4 100644
>> --- a/Documentation/leds/leds-class.txt
>> +++ b/Documentation/leds/leds-class.txt
>> @@ -43,7 +43,7 @@ LED Device Naming
>>
>> Is currently of the form:
>>
>> -"devicename:colour:function"
>> +"colour:function"
>>
>> There have been calls for LED properties such as colour to be exported as
>> individual led class attributes. As a solution which doesn't incur as much
>> diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
>> index ede4fa0..f7371fc 100644
>> --- a/drivers/leds/led-core.c
>> +++ b/drivers/leds/led-core.c
>> @@ -16,6 +16,8 @@
>> #include <linux/list.h>
>> #include <linux/module.h>
>> #include <linux/mutex.h>
>> +#include <linux/of.h>
>> +#include <linux/property.h>
>> #include <linux/rwsem.h>
>> #include "leds.h"
>>
>> @@ -327,3 +329,72 @@ void led_sysfs_enable(struct led_classdev *led_cdev)
>> led_cdev->flags &= ~LED_SYSFS_DISABLE;
>> }
>> EXPORT_SYMBOL_GPL(led_sysfs_enable);
>> +
>> +static void led_parse_properties(struct fwnode_handle *fwnode,
>> + struct led_properties *props)
>> +{
>> + int ret;
>> +
>> + if (!fwnode)
>> + return;
>> +
>> + ret = fwnode_property_read_string(fwnode, "label", &props->label);
>> + if (!ret)
>> + return;
>> +
>> + ret = fwnode_property_read_string(fwnode, "function", &props->function);
>> + if (ret)
>> + pr_info("Failed to parse function property\n");
>> +
>> + ret = fwnode_property_read_string(fwnode, "color", &props->color);
>> + if (ret)
>> + pr_info("Failed to parse color property\n");
>
> Now the color and function properties can be optional, so we should
> deal with different return errors.
> -EINVAL means we have not set color or function property, which means
> we should not give failure message for users (maybe "not supply color
> property\n") and return 0 as success.
The lack of any of these properties is not critical, therefore this
function does not return the error code, but only prints the status.
Please note that I'm not using pr_error(), but pr_info().
Related to the message text - I agree, I will change it to e.g.
"color property not found"
> For other errors, we should not ignore them, instead we should give
> failure messages and return errors.
I've skimmed through other kernel drivers and vast majority of
them don't check exact failure code in case of non-zero return,
but assume that property is missing, and eventually report
error code. I'd do the same here.
> Tested-by: Baolin Wang <[email protected]>
>
>> +}
>> +
>> +int led_compose_name(struct fwnode_handle *fwnode, const char *led_hw_name,
>> + const char *default_desc, char *led_classdev_name)
>> +{
>> + struct led_properties props = {};
>> +
>> + if (!led_classdev_name)
>> + return -EINVAL;
>> +
>> + led_parse_properties(fwnode, &props);
>> +
>> + if (props.label) {
>> + /*
>> + * Presence of 'label' DT property implies legacy LED name,
>> + * formatted as <devicename:color:function>, with possible
>> + * section omission if doesn't apply to given device.
>> + *
>> + * If no led_hw_name has been passed, then it indicates that
>> + * DT label should be used as-is for LED class device name.
>> + * Otherwise the label is prepended with led_hw_name to compose
>> + * the final LED class device name.
>> + */
>> + if (!led_hw_name) {
>> + strncpy(led_classdev_name, props.label,
>> + LED_MAX_NAME_SIZE);
>> + } else {
>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>> + led_hw_name, props.label);
>> + }
>> + } else if (props.function || props.color) {
>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>> + props.color ?: "", props.function ?: "");
>> + } else if (default_desc) {
>> + if (!led_hw_name) {
>> + pr_err("Legacy LED naming requires devicename segment");
>> + return -EINVAL;
>> + }
>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>> + led_hw_name, default_desc);
>> + } else if (is_of_node(fwnode)) {
>> + strncpy(led_classdev_name, to_of_node(fwnode)->name,
>> + LED_MAX_NAME_SIZE);
>> + } else
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(led_compose_name);
>> diff --git a/include/linux/leds.h b/include/linux/leds.h
>> index 646c49a..ddb4001 100644
>> --- a/include/linux/leds.h
>> +++ b/include/linux/leds.h
>> @@ -238,6 +238,32 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
>> extern void led_sysfs_enable(struct led_classdev *led_cdev);
>>
>> /**
>> + * led_compose_name - compose LED class device name
>> + * @child: child fwnode_handle describing a LED,
>> + * or a group of synchronized LEDs.
>> + * @led_hw_name: name of the LED controller, used when falling back to legacy
>> + * LED naming; it should be set to NULL in new LED class drivers
>> + * @default_desc: default <color:function> tuple, for backwards compatibility
>> + * with in-driver hard-coded LED names used as a fallback when
>> + * "label" DT property was absent; it should be set to NULL
>> + * in new LED class drivers
>> + * @led_classdev_name: composed LED class device name
>> + *
>> + * Create LED class device name basing on the configuration provided by the
>> + * board firmware. The name can have a legacy form <devicename:color:function>,
>> + * or a new form <color:function>. The latter is chosen if at least one of
>> + * "color" or "function" properties is present in the fwnode, leaving the
>> + * section blank if the related property is absent. The former is applied
>> + * when legacy "label" property is present in the fwnode. In case none of the
>> + * aformentioned properties was found, then, for OF nodes, the node name
>> + * is adopted for LED class device name.
>> + *
>> + * Returns: 0 on success or negative error value on failure
>> + */
>> +extern int led_compose_name(struct fwnode_handle *child, const char *led_hw_name,
>> + const char *default_desc, char *led_classdev_name);
>> +
>> +/**
>> * led_sysfs_is_disabled - check if LED sysfs interface is disabled
>> * @led_cdev: the LED to query
>> *
>> @@ -414,6 +440,12 @@ struct led_platform_data {
>> struct led_info *leds;
>> };
>>
>> +struct led_properties {
>> + const char *color;
>> + const char *function;
>> + const char *label;
>> +};
>> +
>> struct gpio_desc;
>> typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
>> unsigned long *delay_on,
>> --
>> 2.1.4
>>
>
>
>
--
Best regards,
Jacek Anaszewski
Hi Dan,
Thanks for the review.
On 11/08/2018 06:50 PM, Dan Murphy wrote:
> Jacek
>
> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
[...]
>>
>> /**
>> - * of_led_classdev_register - register a new object of led_classdev class.
>> + * led_classdev_register_ext - register a new object of led_classdev class.
>
> For this should the comment indicate a different between the extended and non-extended calls?
> Like the _ext might say register a new object of led_classdev with init_data?
>
> Same comments for each addition below.
Agreed, I will amend it as you propose.
> Otherwise with Baolin's comments for 1/24
>
> Acked-by: Dan Murphy <[email protected]>
>
> Dan
>
>> *
>> * @parent: parent of LED device
>> * @led_cdev: the led_classdev structure for this device.
>> - * @np: DT node describing this LED
>> + * @init_data: LED class device initialization data
>> */
>> -int of_led_classdev_register(struct device *parent, struct device_node *np,
>> - struct led_classdev *led_cdev)
>> +int led_classdev_register_ext(struct device *parent,
>> + struct led_classdev *led_cdev,
>> + struct led_init_data *init_data)
>> {
>> char name[LED_MAX_NAME_SIZE];
>> int ret;
>>
>> + if (init_data && init_data->name) {
>> + led_cdev->name = init_data->name;
>> + } else {
>> + dev_info(parent, "init_data not available");
>> + }
>> +
>> ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
>> if (ret < 0)
>> return ret;
>> @@ -268,7 +276,8 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
>> mutex_unlock(&led_cdev->led_access);
>> return PTR_ERR(led_cdev->dev);
>> }
>> - led_cdev->dev->of_node = np;
>> + if (init_data && init_data->fwnode)
>> + led_cdev->dev->of_node = to_of_node(init_data->fwnode);
>>
>> if (ret)
>> dev_warn(parent, "Led %s renamed to %s due to name collision",
>> @@ -313,7 +322,7 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
>>
>> return 0;
>> }
>> -EXPORT_SYMBOL_GPL(of_led_classdev_register);
>> +EXPORT_SYMBOL_GPL(led_classdev_register_ext);
>>
>> /**
>> * led_classdev_unregister - unregisters a object of led_properties class.
>> @@ -358,14 +367,15 @@ static void devm_led_classdev_release(struct device *dev, void *res)
>> }
>>
>> /**
>> - * devm_of_led_classdev_register - resource managed led_classdev_register()
>> + * devm_led_classdev_register_ext - resource managed led_classdev_register_ext()
>> *
>> * @parent: parent of LED device
>> * @led_cdev: the led_classdev structure for this device.
>> + * @init_data: LED class device initialization data
>> */
>> -int devm_of_led_classdev_register(struct device *parent,
>> - struct device_node *np,
>> - struct led_classdev *led_cdev)
>> +int devm_led_classdev_register_ext(struct device *parent,
>> + struct led_classdev *led_cdev,
>> + struct led_init_data *init_data)
>> {
>> struct led_classdev **dr;
>> int rc;
>> @@ -374,7 +384,7 @@ int devm_of_led_classdev_register(struct device *parent,
>> if (!dr)
>> return -ENOMEM;
>>
>> - rc = of_led_classdev_register(parent, np, led_cdev);
>> + rc = led_classdev_register_ext(parent, led_cdev, init_data);
>> if (rc) {
>> devres_free(dr);
>> return rc;
>> @@ -385,7 +395,7 @@ int devm_of_led_classdev_register(struct device *parent,
>>
>> return 0;
>> }
>> -EXPORT_SYMBOL_GPL(devm_of_led_classdev_register);
>> +EXPORT_SYMBOL_GPL(devm_led_classdev_register_ext);
>>
>> static int devm_led_classdev_match(struct device *dev, void *res, void *data)
>> {
>> diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
>> index 0e42624..1c82152 100644
>> --- a/drivers/leds/leds-cr0014114.c
>> +++ b/drivers/leds/leds-cr0014114.c
>> @@ -207,8 +207,7 @@ static int cr0014114_probe_dt(struct cr0014114 *priv)
>> led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
>> led->ldev.brightness_set_blocking = cr0014114_set_sync;
>>
>> - ret = devm_of_led_classdev_register(priv->dev, np,
>> - &led->ldev);
>> + ret = devm_led_classdev_register(priv->dev, &led->ldev);
>> if (ret) {
>> dev_err(priv->dev,
>> "failed to register LED device %s, err %d",
>> diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
>> index 32fa752..c87fbd3 100644
>> --- a/drivers/leds/leds-gpio.c
>> +++ b/drivers/leds/leds-gpio.c
>> @@ -112,7 +112,7 @@ static int create_gpio_led(const struct gpio_led *template,
>> if (ret < 0)
>> return ret;
>>
>> - return devm_of_led_classdev_register(parent, np, &led_dat->cdev);
>> + return devm_led_classdev_register(parent, &led_dat->cdev);
>> }
>>
>> struct gpio_leds_priv {
>> diff --git a/include/linux/led-class-flash.h b/include/linux/led-class-flash.h
>> index 700efaa..28a73d0 100644
>> --- a/include/linux/led-class-flash.h
>> +++ b/include/linux/led-class-flash.h
>> @@ -90,15 +90,20 @@ static inline struct led_classdev_flash *lcdev_to_flcdev(
>> }
>>
>> /**
>> - * led_classdev_flash_register - register a new object of led_classdev class
>> - * with support for flash LEDs
>> + * fwnode_led_classdev_flash_register - register a new object of led_classdev
>> + * class with support for flash LEDs
>> * @parent: the flash LED to register
>> + * @fwnode: the flash LED fwnode handle
>> * @fled_cdev: the led_classdev_flash structure for this device
>> *
>> * Returns: 0 on success or negative error value on failure
>> */
>> -extern int led_classdev_flash_register(struct device *parent,
>> - struct led_classdev_flash *fled_cdev);
>> +extern 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)
>>
>> /**
>> * led_classdev_flash_unregister - unregisters an object of led_classdev class
>> diff --git a/include/linux/leds.h b/include/linux/leds.h
>> index 834683d..646c49a 100644
>> --- a/include/linux/leds.h
>> +++ b/include/linux/leds.h
>> @@ -20,6 +20,7 @@
>> #include <linux/spinlock.h>
>> #include <linux/timer.h>
>> #include <linux/workqueue.h>
>> +#include <uapi/linux/uleds.h>
>>
>> struct device;
>> /*
>> @@ -33,6 +34,13 @@ enum led_brightness {
>> LED_FULL = 255,
>> };
>>
>> +struct led_init_data {
>> + /* Device fwnode handle */
>> + struct fwnode_handle *fwnode;
>> + /* Requested LED class device name */
>> + char name[LED_MAX_NAME_SIZE];
>> +};
>> +
>> struct led_classdev {
>> const char *name;
>> enum led_brightness brightness;
>> @@ -73,6 +81,7 @@ struct led_classdev {
>> */
>> int (*brightness_set_blocking)(struct led_classdev *led_cdev,
>> enum led_brightness brightness);
>> +
>> /* Get LED brightness level */
>> enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
>>
>> @@ -123,16 +132,16 @@ struct led_classdev {
>> struct mutex led_access;
>> };
>>
>> -extern int of_led_classdev_register(struct device *parent,
>> - struct device_node *np,
>> - struct led_classdev *led_cdev);
>> -#define led_classdev_register(parent, led_cdev) \
>> - of_led_classdev_register(parent, NULL, led_cdev)
>> -extern int devm_of_led_classdev_register(struct device *parent,
>> - struct device_node *np,
>> - struct led_classdev *led_cdev);
>> -#define devm_led_classdev_register(parent, led_cdev) \
>> - devm_of_led_classdev_register(parent, NULL, led_cdev)
>> +extern int led_classdev_register_ext(struct device *parent,
>> + struct led_classdev *led_cdev,
>> + struct led_init_data *init_data);
>> +#define led_classdev_register(parent, led_cdev) \
>> + led_classdev_register_ext(parent, led_cdev, NULL)
>> +extern int devm_led_classdev_register_ext(struct device *parent,
>> + struct led_classdev *led_cdev,
>> + struct led_init_data *init_data);
>> +#define devm_led_classdev_register(parent, led_cdev) \
>> + 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);
>>
>
>
--
Best regards,
Jacek Anaszewski
Dan,
On 11/08/2018 07:00 PM, Dan Murphy wrote:
> Jacek
>
> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>> Introduce dedicated properties for conveying information about
>> LED function and color. Mark old "label" property as deprecated.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
>> index aa13998..3efc826 100644
>> --- a/Documentation/devicetree/bindings/leds/common.txt
>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
>> have to be tightly coupled with the LED device binding. They are represented
>> by child nodes of the parent LED device binding.
>>
>> +
>> Optional properties for child nodes:
>> - led-sources : List of device current outputs the LED is connected to. The
>> outputs are identified by the numbers that must be defined
>> in the LED device binding documentation.
>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
>> + from the header include/dt-bindings/leds/functions.h.
>> + If there is no matching LED_FUNCTION available, add a new one.
>> +- color : Color of the LED.
>
> Should we define the colors too? There are only really 4. Red, green, blue and white.
>
> Generally varying colors are created base on the primary colors. Even the amber color
No problem, I can add LED colors. However, I don't quite follow how
the mix of base color strings would give "amber" ? :-)
--
Best regards,
Jacek Anaszewski
Dan,
On 11/08/2018 07:06 PM, Dan Murphy wrote:
> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>> Add public led_compose_name() API for composing LED class device
>> name basing on fwnode_handle data. The function composes device name
>> according to either a new <color:function> pattern or the legacy
>> <devicename:color:function> pattern. The decision on using the
>> particular pattern is made basing on whether fwnode contains new
>> "function" and "color" properties, or the legacy "label" proeprty.
>>
>> Backwards compatibility with in-driver hard-coded LED class device
>> names is assured thanks to the default_desc argument.
>>
>> In case none of the aformentioned properties was found, then, for OF
>> nodes, the node name is adopted for LED class device name.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> Documentation/leds/leds-class.txt | 2 +-
>> drivers/leds/led-core.c | 71 +++++++++++++++++++++++++++++++++++++++
>> include/linux/leds.h | 32 ++++++++++++++++++
>> 3 files changed, 104 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
>> index 836cb16..e9009c4 100644
>> --- a/Documentation/leds/leds-class.txt
>> +++ b/Documentation/leds/leds-class.txt
>> @@ -43,7 +43,7 @@ LED Device Naming
>>
>> Is currently of the form:
>>
>> -"devicename:colour:function"
>> +"colour:function"
>>
>> There have been calls for LED properties such as colour to be exported as
>> individual led class attributes. As a solution which doesn't incur as much
>> diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
>> index ede4fa0..f7371fc 100644
>> --- a/drivers/leds/led-core.c
>> +++ b/drivers/leds/led-core.c
>> @@ -16,6 +16,8 @@
>> #include <linux/list.h>
>> #include <linux/module.h>
>> #include <linux/mutex.h>
>> +#include <linux/of.h>
>> +#include <linux/property.h>
>> #include <linux/rwsem.h>
>> #include "leds.h"
>>
>> @@ -327,3 +329,72 @@ void led_sysfs_enable(struct led_classdev *led_cdev)
>> led_cdev->flags &= ~LED_SYSFS_DISABLE;
>> }
>> EXPORT_SYMBOL_GPL(led_sysfs_enable);
>> +
>> +static void led_parse_properties(struct fwnode_handle *fwnode,
>> + struct led_properties *props)
>> +{
>> + int ret;
>> +
>> + if (!fwnode)
>> + return;
>> +
>> + ret = fwnode_property_read_string(fwnode, "label", &props->label);
>
> If we have the label do we need to continue to look for the function and color nodes?
>
> It can be checked and diverted using fwnode_property_present for the "label" property
Good catch. I will respin it as proposed.
>> + if (!ret)
>> + return;
>> +
>> + ret = fwnode_property_read_string(fwnode, "function", &props->function);
>> + if (ret)
>> + pr_info("Failed to parse function property\n");
>> +
>> + ret = fwnode_property_read_string(fwnode, "color", &props->color);
>> + if (ret)
>> + pr_info("Failed to parse color property\n");
>> +}
>> +
>> +int led_compose_name(struct fwnode_handle *fwnode, const char *led_hw_name,
>> + const char *default_desc, char *led_classdev_name)
>> +{
>> + struct led_properties props = {};
>> +
>> + if (!led_classdev_name)
>> + return -EINVAL;
>> +
>> + led_parse_properties(fwnode, &props);
>> +
>> + if (props.label) {
>> + /*
>> + * Presence of 'label' DT property implies legacy LED name,
>> + * formatted as <devicename:color:function>, with possible
>> + * section omission if doesn't apply to given device.
>> + *
>> + * If no led_hw_name has been passed, then it indicates that
>> + * DT label should be used as-is for LED class device name.
>> + * Otherwise the label is prepended with led_hw_name to compose
>> + * the final LED class device name.
>> + */
>> + if (!led_hw_name) {
>> + strncpy(led_classdev_name, props.label,
>> + LED_MAX_NAME_SIZE);
>> + } else {
>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>> + led_hw_name, props.label);
>> + }
>> + } else if (props.function || props.color) {
>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>> + props.color ?: "", props.function ?: "");
>> + } else if (default_desc) {
>> + if (!led_hw_name) {
>> + pr_err("Legacy LED naming requires devicename segment");
>> + return -EINVAL;
>> + }
>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>> + led_hw_name, default_desc);
>> + } else if (is_of_node(fwnode)) {
>> + strncpy(led_classdev_name, to_of_node(fwnode)->name,
>> + LED_MAX_NAME_SIZE);
>> + } else
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(led_compose_name);
>> diff --git a/include/linux/leds.h b/include/linux/leds.h
>> index 646c49a..ddb4001 100644
>> --- a/include/linux/leds.h
>> +++ b/include/linux/leds.h
>> @@ -238,6 +238,32 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
>> extern void led_sysfs_enable(struct led_classdev *led_cdev);
>>
>> /**
>> + * led_compose_name - compose LED class device name
>> + * @child: child fwnode_handle describing a LED,
>> + * or a group of synchronized LEDs.
>> + * @led_hw_name: name of the LED controller, used when falling back to legacy
>> + * LED naming; it should be set to NULL in new LED class drivers
>> + * @default_desc: default <color:function> tuple, for backwards compatibility
>> + * with in-driver hard-coded LED names used as a fallback when
>> + * "label" DT property was absent; it should be set to NULL
>> + * in new LED class drivers
>> + * @led_classdev_name: composed LED class device name
>> + *
>> + * Create LED class device name basing on the configuration provided by the
>> + * board firmware. The name can have a legacy form <devicename:color:function>,
>> + * or a new form <color:function>. The latter is chosen if at least one of
>> + * "color" or "function" properties is present in the fwnode, leaving the
>> + * section blank if the related property is absent. The former is applied
>> + * when legacy "label" property is present in the fwnode. In case none of the
>> + * aformentioned properties was found, then, for OF nodes, the node name
>
> s/aforementioned
>
>> + * is adopted for LED class device name.
>> + *
>> + * Returns: 0 on success or negative error value on failure
>> + */
>> +extern int led_compose_name(struct fwnode_handle *child, const char *led_hw_name,
>> + const char *default_desc, char *led_classdev_name);
>> +
>> +/**
>> * led_sysfs_is_disabled - check if LED sysfs interface is disabled
>> * @led_cdev: the LED to query
>> *
>> @@ -414,6 +440,12 @@ struct led_platform_data {
>> struct led_info *leds;
>> };
>>
>> +struct led_properties {
>> + const char *color;
>> + const char *function;
>> + const char *label;
>> +};
>> +
>> struct gpio_desc;
>> typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
>> unsigned long *delay_on,
>>
>
>
--
Best regards,
Jacek Anaszewski
Dan,
On 11/08/2018 07:14 PM, Dan Murphy wrote:
> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>> Switch to using generic LED support for composing LED class
>> device name.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> ---
>> drivers/leds/leds-lm3692x.c | 39 ++++++++++++++++++++-------------------
>> 1 file changed, 20 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
>> index 4f413a7..9dfc0f2 100644
>> --- a/drivers/leds/leds-lm3692x.c
>> +++ b/drivers/leds/leds-lm3692x.c
>> @@ -13,7 +13,6 @@
>> #include <linux/regmap.h>
>> #include <linux/regulator/consumer.h>
>> #include <linux/slab.h>
>> -#include <uapi/linux/uleds.h>
>>
>> #define LM36922_MODEL 0
>> #define LM36923_MODEL 1
>> @@ -95,6 +94,9 @@
>> #define LM3692X_FAULT_FLAG_SHRT BIT(3)
>> #define LM3692X_FAULT_FLAG_OPEN BIT(4)
>>
>> +#define LM36922_NAME "lm36922"
>> +#define LM36923_NAME "lm36923"
>> +
>> /**
>> * struct lm3692x_led -
>> * @lock - Lock for reading/writing the device
>> @@ -103,7 +105,6 @@
>> * @regmap - Devices register map
>> * @enable_gpio - VDDIO/EN gpio to enable communication interface
>> * @regulator - LED supply regulator pointer
>> - * @label - LED label
>> * @led_enable - LED sync to be enabled
>> * @model_id - Current device model ID enumerated
>> */
>> @@ -114,7 +115,6 @@ struct lm3692x_led {
>> struct regmap *regmap;
>> struct gpio_desc *enable_gpio;
>> struct regulator *regulator;
>> - char label[LED_MAX_NAME_SIZE];
>> int led_enable;
>> int model_id;
>> };
>> @@ -325,7 +325,8 @@ static int lm3692x_init(struct lm3692x_led *led)
>> static int lm3692x_probe_dt(struct lm3692x_led *led)
>> {
>> struct fwnode_handle *child = NULL;
>> - const char *name;
>> + struct led_init_data init_data;
>> + char *model_name;
>> int ret;
>>
>> led->enable_gpio = devm_gpiod_get_optional(&led->client->dev,
>> @@ -346,17 +347,20 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
>> dev_err(&led->client->dev, "No LED Child node\n");
>> return -ENODEV;
>> }
>> + init_data.fwnode = child;
>>
>> - fwnode_property_read_string(child, "linux,default-trigger",
>> - &led->led_dev.default_trigger);
>> + if (led->model_id == LM36922_MODEL)
>> + model_name = LM36922_NAME;
>> + else
>> + model_name = LM36923_NAME;
>>
>> - ret = fwnode_property_read_string(child, "label", &name);
>> + ret = led_compose_name(child, model_name, ":backlight_cluster",
>> + init_data.name);
>> if (ret)
>> - snprintf(led->label, sizeof(led->label),
>> - "%s::", led->client->name);
>> - else
>> - snprintf(led->label, sizeof(led->label),
>> - "%s:%s", led->client->name, name);
>> + return ret;
>> +
>> + fwnode_property_read_string(child, "linux,default-trigger",
>> + &led->led_dev.default_trigger);
>>
>> ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
>> if (ret) {
>> @@ -364,16 +368,13 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
>> return ret;
>> }
>>
>> - led->led_dev.name = led->label;
>> -
>> - ret = devm_led_classdev_register(&led->client->dev, &led->led_dev);
>> + ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev,
>> + &init_data);
>> if (ret) {
>> dev_err(&led->client->dev, "led register err: %d\n", ret);
>> return ret;
>> }
>>
>> - led->led_dev.dev->of_node = to_of_node(child);
>> -
>> return 0;
>> }
>>
>> @@ -439,8 +440,8 @@ static int lm3692x_remove(struct i2c_client *client)
>> }
>>
>> static const struct i2c_device_id lm3692x_id[] = {
>> - { "lm36922", LM36922_MODEL },
>> - { "lm36923", LM36923_MODEL },
>> + { LM36922_NAME, LM36922_MODEL },
>> + { LM36923_NAME, LM36923_MODEL },
>
> How is this change relevant?
> No mention in the comments about this change.
Unrelated. It is a remnant from the stage of development, where I had
an impression that i2c_client name is taken from this array
somehow. Only later I learned that it is taken from OF compatible
property after removing vendor prefix with comma.
Afterwards I decide to abide by this change since it seems to be
just an improvement - if I'm adding the string definition anyway,
then why not replace other matching literals?
I will add the explanation if the commit message if there are no
other objections.
>> { }
>> };
>> MODULE_DEVICE_TABLE(i2c, lm3692x_id);
>>
>
>
--
Best regards,
Jacek Anaszewski
Dan,
On 11/08/2018 07:16 PM, Dan Murphy wrote:
> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>> Switch to using generic LED support for composing LED class
>> device name.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Signed-off-by: Dan Murphy <[email protected]>
>> ---
>> drivers/leds/leds-lp8860.c | 38 +++++++++++++++++++-------------------
>> 1 file changed, 19 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c
>> index 39c72a9..7c12ccd 100644
>> --- a/drivers/leds/leds-lp8860.c
>> +++ b/drivers/leds/leds-lp8860.c
>> @@ -22,7 +22,6 @@
>> #include <linux/of_gpio.h>
>> #include <linux/gpio/consumer.h>
>> #include <linux/slab.h>
>> -#include <uapi/linux/uleds.h>
>>
>> #define LP8860_DISP_CL1_BRT_MSB 0x00
>> #define LP8860_DISP_CL1_BRT_LSB 0x01
>> @@ -87,6 +86,8 @@
>>
>> #define LP8860_CLEAR_FAULTS 0x01
>>
>> +#define LP8860_NAME "lp8860"
>> +
>> /**
>> * struct lp8860_led -
>> * @lock - Lock for reading/writing the device
>> @@ -96,7 +97,6 @@
>> * @eeprom_regmap - EEPROM register map
>> * @enable_gpio - VDDIO/EN gpio to enable communication interface
>> * @regulator - LED supply regulator pointer
>> - * @label - LED label
>> */
>> struct lp8860_led {
>> struct mutex lock;
>> @@ -106,7 +106,6 @@ struct lp8860_led {
>> struct regmap *eeprom_regmap;
>> struct gpio_desc *enable_gpio;
>> struct regulator *regulator;
>> - char label[LED_MAX_NAME_SIZE];
>> };
>>
>> struct lp8860_eeprom_reg {
>> @@ -387,25 +386,26 @@ static int lp8860_probe(struct i2c_client *client,
>> struct lp8860_led *led;
>> struct device_node *np = client->dev.of_node;
>> struct device_node *child_node;
>> - const char *name;
>> + struct led_init_data init_data;
>>
>> led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
>> if (!led)
>> return -ENOMEM;
>>
>> - for_each_available_child_of_node(np, child_node) {
>> - led->led_dev.default_trigger = of_get_property(child_node,
>> - "linux,default-trigger",
>> - NULL);
>> -
>> - ret = of_property_read_string(child_node, "label", &name);
>> - if (!ret)
>> - snprintf(led->label, sizeof(led->label), "%s:%s",
>> - id->name, name);
>> - else
>> - snprintf(led->label, sizeof(led->label),
>> - "%s::display_cluster", id->name);
>> - }
>
> We need to keep a loop here looking for additional nodes as this device has string support and just
> not cluster support.
>
> Just need to get the other LED patches done.
In the current shape only the properties from the last parsed child node
will be used for initializing the LED class device. So, this should be
meant also a fix removing this obscurity. Worth mentioning in the commit
message. Or I'm not getting it right?
>> + child_node = of_get_next_available_child(np, NULL);
>> + if (!child_node)
>> + return -EINVAL;
>> +
>> + init_data.fwnode = of_fwnode_handle(child_node),
>> +
>> + led->led_dev.default_trigger = of_get_property(child_node,
>> + "linux,default-trigger",
>> + NULL);
>> +
>> + ret = led_compose_name(init_data.fwnode, LP8860_NAME,
>> + ":display_cluster", init_data.name);
>
> Should we use the #defines here for display_cluster?
Right, will fix in the next version.
>> + if (ret)
>> + return ret;
>>
>> led->enable_gpio = devm_gpiod_get_optional(&client->dev,
>> "enable", GPIOD_OUT_LOW);
>> @@ -420,7 +420,6 @@ static int lp8860_probe(struct i2c_client *client,
>> led->regulator = NULL;
>>
>> led->client = client;
>> - led->led_dev.name = led->label;
>> led->led_dev.brightness_set_blocking = lp8860_brightness_set;
>>
>> mutex_init(&led->lock);
>> @@ -447,7 +446,8 @@ static int lp8860_probe(struct i2c_client *client,
>> if (ret)
>> return ret;
>>
>> - ret = devm_led_classdev_register(&client->dev, &led->led_dev);
>> + ret = devm_led_classdev_register_ext(&client->dev, &led->led_dev,
>> + &init_data);
>> if (ret) {
>> dev_err(&client->dev, "led register err: %d\n", ret);
>> return ret;
>>
>
>
--
Best regards,
Jacek Anaszewski
Hi Rob,
Thanks for the review.
On 11/08/2018 04:13 PM, Rob Herring wrote:
> On Tue, Nov 6, 2018 at 4:07 PM Jacek Anaszewski
> <[email protected]> wrote:
>>
>> Add common LED function definitions for use in Device Tree.
>> The function names were extracted from existing dts files
>> after eliminating oddities.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> include/dt-bindings/leds/functions.h | 101 +++++++++++++++++++++++++++++++++++
>> 1 file changed, 101 insertions(+)
>> create mode 100644 include/dt-bindings/leds/functions.h
>>
>> diff --git a/include/dt-bindings/leds/functions.h b/include/dt-bindings/leds/functions.h
>> new file mode 100644
>> index 0000000..3f94e09
>> --- /dev/null
>> +++ b/include/dt-bindings/leds/functions.h
>> @@ -0,0 +1,101 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +#define LED_FUNCTION_2G "2g"
>> +#define LED_FUNCTION_ACTIVITY "activity"
>> +#define LED_FUNCTION_ADSL "adsl"
>> +#define LED_FUNCTION_ALARM "alarm"
>> +#define LED_FUNCTION_ALIVE "alive"
>> +#define LED_FUNCTION_ALL "all"
>> +#define LED_FUNCTION_APP "app"
>> +#define LED_FUNCTION_AUX "aux"
>> +#define LED_FUNCTION_BACKUP "backup"
>> +#define LED_FUNCTION_BACKLIGHT "backlight"
>> +#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
>
> I'd prefer we go further and only define 1 endorsed function name.
> Backlight, disk, network, fault/error all seem to have a few
OK, I'll try to remove semantically akin duplicates.
> duplicates. I'm also thinking the functions make linux,default-trigger
> redundant in some cases.
Yes, this is tempting. Needs more thorough analysis, though.
> I'm not a huge fan of making these defines, but it does make it
> perfectly clear if folks use standard names or not.
>
>> +#define LED_FUNCTION_BEEP "beep"
>> +#define LED_FUNCTION_BLUETOOTH "bluetooth"
>> +#define LED_FUNCTION_BOOT "boot"
>> +#define LED_FUNCTION_BOTTOM "bottom"
>> +#define LED_FUNCTION_BRICK_STATUS "brick-status"
>> +#define LED_FUNCTION_CEL "cel"
>> +#define LED_FUNCTION_CEL_PWR "cel-pwr"
>> +#define LED_FUNCTION_CEL_RESET "cel-reset"
>> +#define LED_FUNCTION_CHRG "chrg"
>> +#define LED_FUNCTION_COM "com"
>> +#define LED_FUNCTION_COPY "copy"
>> +#define LED_FUNCTION_CPU "cpu"
>> +#define LED_FUNCTION_DEBUG "debug"
>> +#define LED_FUNCTION_DIA "dia"
>> +#define LED_FUNCTION_DISK "disk"
>> +#define LED_FUNCTION_DISPLAY_CLUSTER "display_cluster"
>> +#define LED_FUNCTION_DOWN "down"
>> +#define LED_FUNCTION_DSL "dsl"
>> +#define LED_FUNCTION_ENOCEAN "enocean"
>> +#define LED_FUNCTION_ENTER "enter"
>> +#define LED_FUNCTION_ERROR "error"
>> +#define LED_FUNCTION_ESATA "esata"
>> +#define LED_FUNCTION_ETHERNET_STATUS "ethernet-status"
>> +#define LED_FUNCTION_FAIL "fail"
>> +#define LED_FUNCTION_FAULT "fault"
>> +#define LED_FUNCTION_FLASH "flash"
>> +#define LED_FUNCTION_FRONT "front"
>> +#define LED_FUNCTION_FUNC "func"
>> +#define LED_FUNCTION_GPIO "gpio"
>> +#define LED_FUNCTION_GSM "gsm"
>> +#define LED_FUNCTION_HD "hd"
>> +#define LED_FUNCTION_HDD "hdd"
>> +#define LED_FUNCTION_HDDERR "hdderr"
>> +#define LED_FUNCTION_HEALTH "health"
>> +#define LED_FUNCTION_HEARTBEAT "heartbeat"
>> +#define LED_FUNCTION_HOME "home"
>> +#define LED_FUNCTION_INDICATOR "indicator"
>> +#define LED_FUNCTION_INET "inet"
>> +#define LED_FUNCTION_INFO "info"
>> +#define LED_FUNCTION_INTERNET "internet"
>> +#define LED_FUNCTION_KEYPAD "keypad"
>> +#define LED_FUNCTION_LAN "lan"
>> +#define LED_FUNCTION_LEFT "left"
>> +#define LED_FUNCTION_LIVE "live"
>> +#define LED_FUNCTION_MICROSD "microsd"
>> +#define LED_FUNCTION_MISC "misc"
>> +#define LED_FUNCTION_MMC "mmc"
>> +#define LED_FUNCTION_NAND "nand"
>> +#define LED_FUNCTION_NETWORK "network"
>> +#define LED_FUNCTION_ON "on"
>> +#define LED_FUNCTION_OS "os"
>> +#define LED_FUNCTION_PANEL "panel"
>> +#define LED_FUNCTION_PMU_STAT "pmu_stat"
>> +#define LED_FUNCTION_PROG "prog"
>> +#define LED_FUNCTION_PROGRAMMING "programming"
>> +#define LED_FUNCTION_PULSE "pulse"
>> +#define LED_FUNCTION_PWR "pwr"
>> +#define LED_FUNCTION_QSS "qss"
>> +#define LED_FUNCTION_REAR "rear"
>> +#define LED_FUNCTION_REBUILD "rebuild"
>> +#define LED_FUNCTION_RIGHT "right"
>> +#define LED_FUNCTION_ROUTER "router"
>> +#define LED_FUNCTION_RS "rs"
>> +#define LED_FUNCTION_RX "rx"
>> +#define LED_FUNCTION_SATA "sata"
>> +#define LED_FUNCTION_SD "sd"
>> +#define LED_FUNCTION_SLEEP "sleep"
>> +#define LED_FUNCTION_STANDBY "standby"
>> +#define LED_FUNCTION_STATUS "status"
>> +#define LED_FUNCTION_SW "sw"
>> +#define LED_FUNCTION_SWRDY "swrdy"
>> +#define LED_FUNCTION_SYSTEM "system"
>> +#define LED_FUNCTION_TEL "tel"
>> +#define LED_FUNCTION_TOP "top"
>> +#define LED_FUNCTION_TORCH "torch"
>> +#define LED_FUNCTION_TV "tv"
>> +#define LED_FUNCTION_TX "tx"
>> +#define LED_FUNCTION_UP "up"
>> +#define LED_FUNCTION_USB "usb"
>> +#define LED_FUNCTION_USB_COPY "usb_copy"
>> +#define LED_FUNCTION_USER "user"
>> +#define LED_FUNCTION_USR "usr"
>> +#define LED_FUNCTION_WAN "wan"
>> +#define LED_FUNCTION_WIFI "wifi"
>> +#define LED_FUNCTION_WIRELESS "wireless"
>> +#define LED_FUNCTION_WLAN "wlan"
>> +#define LED_FUNCTION_WMODE "wmode"
>> +#define LED_FUNCTION_WPS "wps"
>> --
>> 2.1.4
>>
>
--
Best regards,
Jacek Anaszewski
Jacek
On 11/08/2018 02:47 PM, Jacek Anaszewski wrote:
> Dan,
>
> On 11/08/2018 07:00 PM, Dan Murphy wrote:
>> Jacek
>>
>> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>>> Introduce dedicated properties for conveying information about
>>> LED function and color. Mark old "label" property as deprecated.
>>>
>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>> Cc: Baolin Wang <[email protected]>
>>> Cc: Daniel Mack <[email protected]>
>>> Cc: Dan Murphy <[email protected]>
>>> Cc: Linus Walleij <[email protected]>
>>> Cc: Oleh Kravchenko <[email protected]>
>>> Cc: Sakari Ailus <[email protected]>
>>> Cc: Simon Shields <[email protected]>
>>> Cc: Xiaotong Lu <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
>>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
>>> index aa13998..3efc826 100644
>>> --- a/Documentation/devicetree/bindings/leds/common.txt
>>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>>> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
>>> have to be tightly coupled with the LED device binding. They are represented
>>> by child nodes of the parent LED device binding.
>>>
>>> +
>>> Optional properties for child nodes:
>>> - led-sources : List of device current outputs the LED is connected to. The
>>> outputs are identified by the numbers that must be defined
>>> in the LED device binding documentation.
>>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
>>> + from the header include/dt-bindings/leds/functions.h.
>>> + If there is no matching LED_FUNCTION available, add a new one.
>>> +- color : Color of the LED.
>>
>> Should we define the colors too? There are only really 4. Red, green, blue and white.
>>
>> Generally varying colors are created base on the primary colors. Even the amber color
>
> No problem, I can add LED colors. However, I don't quite follow how
> the mix of base color strings would give "amber" ? :-)
>
Amber or yellow. Red and green with a hint of blue or no blue depending on how dark you want it.
You don't always have to turn the LED on full to mix. Sometimes lowering the level of the stronger colors like red
and upping weaker colors like green you can different color
Dan
--
------------------
Dan Murphy
Jacek
On 11/08/2018 02:48 PM, Jacek Anaszewski wrote:
> Dan,
>
> On 11/08/2018 07:14 PM, Dan Murphy wrote:
>> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>>> Switch to using generic LED support for composing LED class
>>> device name.
>>>
>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>> Cc: Dan Murphy <[email protected]>
>>> ---
>>> drivers/leds/leds-lm3692x.c | 39 ++++++++++++++++++++-------------------
>>> 1 file changed, 20 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
>>> index 4f413a7..9dfc0f2 100644
>>> --- a/drivers/leds/leds-lm3692x.c
>>> +++ b/drivers/leds/leds-lm3692x.c
>>> @@ -13,7 +13,6 @@
>>> #include <linux/regmap.h>
>>> #include <linux/regulator/consumer.h>
>>> #include <linux/slab.h>
>>> -#include <uapi/linux/uleds.h>
>>>
>>> #define LM36922_MODEL 0
>>> #define LM36923_MODEL 1
>>> @@ -95,6 +94,9 @@
>>> #define LM3692X_FAULT_FLAG_SHRT BIT(3)
>>> #define LM3692X_FAULT_FLAG_OPEN BIT(4)
>>>
>>> +#define LM36922_NAME "lm36922"
>>> +#define LM36923_NAME "lm36923"
>>> +
>>> /**
>>> * struct lm3692x_led -
>>> * @lock - Lock for reading/writing the device
>>> @@ -103,7 +105,6 @@
>>> * @regmap - Devices register map
>>> * @enable_gpio - VDDIO/EN gpio to enable communication interface
>>> * @regulator - LED supply regulator pointer
>>> - * @label - LED label
>>> * @led_enable - LED sync to be enabled
>>> * @model_id - Current device model ID enumerated
>>> */
>>> @@ -114,7 +115,6 @@ struct lm3692x_led {
>>> struct regmap *regmap;
>>> struct gpio_desc *enable_gpio;
>>> struct regulator *regulator;
>>> - char label[LED_MAX_NAME_SIZE];
>>> int led_enable;
>>> int model_id;
>>> };
>>> @@ -325,7 +325,8 @@ static int lm3692x_init(struct lm3692x_led *led)
>>> static int lm3692x_probe_dt(struct lm3692x_led *led)
>>> {
>>> struct fwnode_handle *child = NULL;
>>> - const char *name;
>>> + struct led_init_data init_data;
>>> + char *model_name;
>>> int ret;
>>>
>>> led->enable_gpio = devm_gpiod_get_optional(&led->client->dev,
>>> @@ -346,17 +347,20 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
>>> dev_err(&led->client->dev, "No LED Child node\n");
>>> return -ENODEV;
>>> }
>>> + init_data.fwnode = child;
>>>
>>> - fwnode_property_read_string(child, "linux,default-trigger",
>>> - &led->led_dev.default_trigger);
>>> + if (led->model_id == LM36922_MODEL)
>>> + model_name = LM36922_NAME;
>>> + else
>>> + model_name = LM36923_NAME;
>>>
>>> - ret = fwnode_property_read_string(child, "label", &name);
>>> + ret = led_compose_name(child, model_name, ":backlight_cluster",
>>> + init_data.name);
>>> if (ret)
>>> - snprintf(led->label, sizeof(led->label),
>>> - "%s::", led->client->name);
>>> - else
>>> - snprintf(led->label, sizeof(led->label),
>>> - "%s:%s", led->client->name, name);
>>> + return ret;
>>> +
>>> + fwnode_property_read_string(child, "linux,default-trigger",
>>> + &led->led_dev.default_trigger);
>>>
>>> ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
>>> if (ret) {
>>> @@ -364,16 +368,13 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
>>> return ret;
>>> }
>>>
>>> - led->led_dev.name = led->label;
>>> -
>>> - ret = devm_led_classdev_register(&led->client->dev, &led->led_dev);
>>> + ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev,
>>> + &init_data);
>>> if (ret) {
>>> dev_err(&led->client->dev, "led register err: %d\n", ret);
>>> return ret;
>>> }
>>>
>>> - led->led_dev.dev->of_node = to_of_node(child);
>>> -
>>> return 0;
>>> }
>>>
>>> @@ -439,8 +440,8 @@ static int lm3692x_remove(struct i2c_client *client)
>>> }
>>>
>>> static const struct i2c_device_id lm3692x_id[] = {
>>> - { "lm36922", LM36922_MODEL },
>>> - { "lm36923", LM36923_MODEL },
>>> + { LM36922_NAME, LM36922_MODEL },
>>> + { LM36923_NAME, LM36923_MODEL },
>>
>> How is this change relevant?
>> No mention in the comments about this change.
>
> Unrelated. It is a remnant from the stage of development, where I had
> an impression that i2c_client name is taken from this array
> somehow. Only later I learned that it is taken from OF compatible
> property after removing vendor prefix with comma.
>
> Afterwards I decide to abide by this change since it seems to be
> just an improvement - if I'm adding the string definition anyway,
> then why not replace other matching literals?
>
> I will add the explanation if the commit message if there are no
> other objections.
That works for me. Just did not want the change to be "hidden" even without
the intent of hiding it.
Dan
>
>>> { }
>>> };
>>> MODULE_DEVICE_TABLE(i2c, lm3692x_id);
>>>
>>
>>
>
--
------------------
Dan Murphy
Hi Jacek,
On 9 November 2018 at 04:47, Jacek Anaszewski
<[email protected]> wrote:
> Hi Baolin,
>
> Thanks for the review.
>
> On 11/07/2018 08:20 AM, Baolin Wang wrote:
>> Hi Jacek,
>>
>> On 7 November 2018 at 06:07, Jacek Anaszewski
>> <[email protected]> wrote:
>>> Add public led_compose_name() API for composing LED class device
>>> name basing on fwnode_handle data. The function composes device name
>>> according to either a new <color:function> pattern or the legacy
>>> <devicename:color:function> pattern. The decision on using the
>>> particular pattern is made basing on whether fwnode contains new
>>> "function" and "color" properties, or the legacy "label" proeprty.
>>>
>>> Backwards compatibility with in-driver hard-coded LED class device
>>> names is assured thanks to the default_desc argument.
>>>
>>> In case none of the aformentioned properties was found, then, for OF
>>> nodes, the node name is adopted for LED class device name.
>>>
>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>> Cc: Baolin Wang <[email protected]>
>>> Cc: Daniel Mack <[email protected]>
>>> Cc: Dan Murphy <[email protected]>
>>> Cc: Linus Walleij <[email protected]>
>>> Cc: Oleh Kravchenko <[email protected]>
>>> Cc: Sakari Ailus <[email protected]>
>>> Cc: Simon Shields <[email protected]>
>>> Cc: Xiaotong Lu <[email protected]>
>>> ---
>>> Documentation/leds/leds-class.txt | 2 +-
>>> drivers/leds/led-core.c | 71 +++++++++++++++++++++++++++++++++++++++
>>> include/linux/leds.h | 32 ++++++++++++++++++
>>> 3 files changed, 104 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
>>> index 836cb16..e9009c4 100644
>>> --- a/Documentation/leds/leds-class.txt
>>> +++ b/Documentation/leds/leds-class.txt
>>> @@ -43,7 +43,7 @@ LED Device Naming
>>>
>>> Is currently of the form:
>>>
>>> -"devicename:colour:function"
>>> +"colour:function"
>>>
>>> There have been calls for LED properties such as colour to be exported as
>>> individual led class attributes. As a solution which doesn't incur as much
>>> diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
>>> index ede4fa0..f7371fc 100644
>>> --- a/drivers/leds/led-core.c
>>> +++ b/drivers/leds/led-core.c
>>> @@ -16,6 +16,8 @@
>>> #include <linux/list.h>
>>> #include <linux/module.h>
>>> #include <linux/mutex.h>
>>> +#include <linux/of.h>
>>> +#include <linux/property.h>
>>> #include <linux/rwsem.h>
>>> #include "leds.h"
>>>
>>> @@ -327,3 +329,72 @@ void led_sysfs_enable(struct led_classdev *led_cdev)
>>> led_cdev->flags &= ~LED_SYSFS_DISABLE;
>>> }
>>> EXPORT_SYMBOL_GPL(led_sysfs_enable);
>>> +
>>> +static void led_parse_properties(struct fwnode_handle *fwnode,
>>> + struct led_properties *props)
>>> +{
>>> + int ret;
>>> +
>>> + if (!fwnode)
>>> + return;
>>> +
>>> + ret = fwnode_property_read_string(fwnode, "label", &props->label);
>>> + if (!ret)
>>> + return;
>>> +
>>> + ret = fwnode_property_read_string(fwnode, "function", &props->function);
>>> + if (ret)
>>> + pr_info("Failed to parse function property\n");
>>> +
>>> + ret = fwnode_property_read_string(fwnode, "color", &props->color);
>>> + if (ret)
>>> + pr_info("Failed to parse color property\n");
>>
>> Now the color and function properties can be optional, so we should
>> deal with different return errors.
>> -EINVAL means we have not set color or function property, which means
>> we should not give failure message for users (maybe "not supply color
>> property\n") and return 0 as success.
>
> The lack of any of these properties is not critical, therefore this
> function does not return the error code, but only prints the status.
> Please note that I'm not using pr_error(), but pr_info().
> Related to the message text - I agree, I will change it to e.g.
> "color property not found"
Yes, that's reasonable.
>
>> For other errors, we should not ignore them, instead we should give
>> failure messages and return errors.
>
> I've skimmed through other kernel drivers and vast majority of
> them don't check exact failure code in case of non-zero return,
> but assume that property is missing, and eventually report
> error code. I'd do the same here.
Fair enough. You can still add my tested tag. Thanks.
>> Tested-by: Baolin Wang <[email protected]>
>>
>>> +}
>>> +
>>> +int led_compose_name(struct fwnode_handle *fwnode, const char *led_hw_name,
>>> + const char *default_desc, char *led_classdev_name)
>>> +{
>>> + struct led_properties props = {};
>>> +
>>> + if (!led_classdev_name)
>>> + return -EINVAL;
>>> +
>>> + led_parse_properties(fwnode, &props);
>>> +
>>> + if (props.label) {
>>> + /*
>>> + * Presence of 'label' DT property implies legacy LED name,
>>> + * formatted as <devicename:color:function>, with possible
>>> + * section omission if doesn't apply to given device.
>>> + *
>>> + * If no led_hw_name has been passed, then it indicates that
>>> + * DT label should be used as-is for LED class device name.
>>> + * Otherwise the label is prepended with led_hw_name to compose
>>> + * the final LED class device name.
>>> + */
>>> + if (!led_hw_name) {
>>> + strncpy(led_classdev_name, props.label,
>>> + LED_MAX_NAME_SIZE);
>>> + } else {
>>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>>> + led_hw_name, props.label);
>>> + }
>>> + } else if (props.function || props.color) {
>>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>>> + props.color ?: "", props.function ?: "");
>>> + } else if (default_desc) {
>>> + if (!led_hw_name) {
>>> + pr_err("Legacy LED naming requires devicename segment");
>>> + return -EINVAL;
>>> + }
>>> + snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s",
>>> + led_hw_name, default_desc);
>>> + } else if (is_of_node(fwnode)) {
>>> + strncpy(led_classdev_name, to_of_node(fwnode)->name,
>>> + LED_MAX_NAME_SIZE);
>>> + } else
>>> + return -EINVAL;
>>> +
>>> + return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(led_compose_name);
>>> diff --git a/include/linux/leds.h b/include/linux/leds.h
>>> index 646c49a..ddb4001 100644
>>> --- a/include/linux/leds.h
>>> +++ b/include/linux/leds.h
>>> @@ -238,6 +238,32 @@ extern void led_sysfs_disable(struct led_classdev *led_cdev);
>>> extern void led_sysfs_enable(struct led_classdev *led_cdev);
>>>
>>> /**
>>> + * led_compose_name - compose LED class device name
>>> + * @child: child fwnode_handle describing a LED,
>>> + * or a group of synchronized LEDs.
>>> + * @led_hw_name: name of the LED controller, used when falling back to legacy
>>> + * LED naming; it should be set to NULL in new LED class drivers
>>> + * @default_desc: default <color:function> tuple, for backwards compatibility
>>> + * with in-driver hard-coded LED names used as a fallback when
>>> + * "label" DT property was absent; it should be set to NULL
>>> + * in new LED class drivers
>>> + * @led_classdev_name: composed LED class device name
>>> + *
>>> + * Create LED class device name basing on the configuration provided by the
>>> + * board firmware. The name can have a legacy form <devicename:color:function>,
>>> + * or a new form <color:function>. The latter is chosen if at least one of
>>> + * "color" or "function" properties is present in the fwnode, leaving the
>>> + * section blank if the related property is absent. The former is applied
>>> + * when legacy "label" property is present in the fwnode. In case none of the
>>> + * aformentioned properties was found, then, for OF nodes, the node name
>>> + * is adopted for LED class device name.
>>> + *
>>> + * Returns: 0 on success or negative error value on failure
>>> + */
>>> +extern int led_compose_name(struct fwnode_handle *child, const char *led_hw_name,
>>> + const char *default_desc, char *led_classdev_name);
>>> +
>>> +/**
>>> * led_sysfs_is_disabled - check if LED sysfs interface is disabled
>>> * @led_cdev: the LED to query
>>> *
>>> @@ -414,6 +440,12 @@ struct led_platform_data {
>>> struct led_info *leds;
>>> };
>>>
>>> +struct led_properties {
>>> + const char *color;
>>> + const char *function;
>>> + const char *label;
>>> +};
>>> +
>>> struct gpio_desc;
>>> typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
>>> unsigned long *delay_on,
>>> --
>>> 2.1.4
>>>
>>
>>
>>
>
> --
> Best regards,
> Jacek Anaszewski
--
Baolin Wang
Best Regards
On 07/11/2018 0.07, Jacek Anaszewski wrote:
> Introduce dedicated properties for conveying information about
> LED function and color. Mark old "label" property as deprecated.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> ---
> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
> 1 file changed, 44 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
> index aa13998..3efc826 100644
> --- a/Documentation/devicetree/bindings/leds/common.txt
> +++ b/Documentation/devicetree/bindings/leds/common.txt
> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
> have to be tightly coupled with the LED device binding. They are represented
> by child nodes of the parent LED device binding.
>
> +
> Optional properties for child nodes:
> - led-sources : List of device current outputs the LED is connected to. The
> outputs are identified by the numbers that must be defined
> in the LED device binding documentation.
> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
> + from the header include/dt-bindings/leds/functions.h.
> + If there is no matching LED_FUNCTION available, add a new one.
> +- color : Color of the LED.
We have had for years out-of-tree patch for multi color gpio led driver
which extends this concept with multiple colors. Then in sysfs there has
been possibility to control the color and otherwise use blinking or
other features.
Our need is multi color status led of the device which includes
different kind of blinkings and colors on different situations.
Current in-tree gpio led driver just wasn't atomic enough and a bit
clumsy interface for handling this.
Now that this is being looked at could we come up with solution that we
could define multiple colors for one led in device tree and then we
could work on getting the driver upstreamed?
What we did was generally:
leds-multi {
compatible = "gpio-multi-leds";
status {
gpios = <...>;
linux,default-trigger = "none";
deafult-state = "keep";
color-red {
pin-mask = <0x01>;
};
color-green {
pin-mask = <0x02>;
};
color-orange {
pin-mask = <0x03>;
};
};
};
Thanks,
Vesa Jääskeläinen
Dan,
On 11/08/2018 10:08 PM, Dan Murphy wrote:
> Jacek
>
> On 11/08/2018 02:47 PM, Jacek Anaszewski wrote:
>> Dan,
>>
>> On 11/08/2018 07:00 PM, Dan Murphy wrote:
>>> Jacek
>>>
>>> On 11/06/2018 04:07 PM, Jacek Anaszewski wrote:
>>>> Introduce dedicated properties for conveying information about
>>>> LED function and color. Mark old "label" property as deprecated.
>>>>
>>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>>> Cc: Baolin Wang <[email protected]>
>>>> Cc: Daniel Mack <[email protected]>
>>>> Cc: Dan Murphy <[email protected]>
>>>> Cc: Linus Walleij <[email protected]>
>>>> Cc: Oleh Kravchenko <[email protected]>
>>>> Cc: Sakari Ailus <[email protected]>
>>>> Cc: Simon Shields <[email protected]>
>>>> Cc: Xiaotong Lu <[email protected]>
>>>> ---
>>>> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
>>>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
>>>> index aa13998..3efc826 100644
>>>> --- a/Documentation/devicetree/bindings/leds/common.txt
>>>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>>>> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
>>>> have to be tightly coupled with the LED device binding. They are represented
>>>> by child nodes of the parent LED device binding.
>>>>
>>>> +
>>>> Optional properties for child nodes:
>>>> - led-sources : List of device current outputs the LED is connected to. The
>>>> outputs are identified by the numbers that must be defined
>>>> in the LED device binding documentation.
>>>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
>>>> + from the header include/dt-bindings/leds/functions.h.
>>>> + If there is no matching LED_FUNCTION available, add a new one.
>>>> +- color : Color of the LED.
>>>
>>> Should we define the colors too? There are only really 4. Red, green, blue and white.
>>>
>>> Generally varying colors are created base on the primary colors. Even the amber color
>>
>> No problem, I can add LED colors. However, I don't quite follow how
>> the mix of base color strings would give "amber" ? :-)
>>
>
> Amber or yellow. Red and green with a hint of blue or no blue depending on how dark you want it.
>
> You don't always have to turn the LED on full to mix. Sometimes lowering the level of the stronger colors like red
> and upping weaker colors like green you can different color
That's obvious. I was rather curious what you had on mind by mentioning
four colors (red, green, blue and white) in the context of "amber".
Just to remind: we're still talking about LED names, not the values.
--
Best regards,
Jacek Anaszewski
Hi Vesa,
On 11/09/2018 09:32 AM, Vesa Jääskeläinen wrote:
> On 07/11/2018 0.07, Jacek Anaszewski wrote:
>> Introduce dedicated properties for conveying information about
>> LED function and color. Mark old "label" property as deprecated.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> Documentation/devicetree/bindings/leds/common.txt | 52
>> +++++++++++++++++++----
>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/leds/common.txt
>> b/Documentation/devicetree/bindings/leds/common.txt
>> index aa13998..3efc826 100644
>> --- a/Documentation/devicetree/bindings/leds/common.txt
>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>> @@ -10,14 +10,20 @@ can influence the way of the LED device
>> initialization, the LED components
>> have to be tightly coupled with the LED device binding. They are
>> represented
>> by child nodes of the parent LED device binding.
>> +
>> Optional properties for child nodes:
>> - led-sources : List of device current outputs the LED is connected
>> to. The
>> outputs are identified by the numbers that must be defined
>> in the LED device binding documentation.
>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed
>> definitions
>> + from the header include/dt-bindings/leds/functions.h.
>> + If there is no matching LED_FUNCTION available, add a new one.
>> +- color : Color of the LED.
>
> We have had for years out-of-tree patch for multi color gpio led driver
> which extends this concept with multiple colors. Then in sysfs there has
> been possibility to control the color and otherwise use blinking or
> other features.
>
> Our need is multi color status led of the device which includes
> different kind of blinkings and colors on different situations.
>
> Current in-tree gpio led driver just wasn't atomic enough and a bit
> clumsy interface for handling this.
>
> Now that this is being looked at could we come up with solution that we
> could define multiple colors for one led in device tree and then we
> could work on getting the driver upstreamed?
>
> What we did was generally:
>
> leds-multi {
> compatible = "gpio-multi-leds";
>
> status {
> gpios = <...>;
> linux,default-trigger = "none";
> deafult-state = "keep";
>
> color-red {
> pin-mask = <0x01>;
> };
>
> color-green {
> pin-mask = <0x02>;
> };
>
> color-orange {
> pin-mask = <0x03>;
> };
> };
> };
>
Device Tree node implementation doesn't actually say too much
about the sysfs interface you came up with, which is most vital
in this case.
Support for RGB LEDs, or other variations of LED synchronization
have been approached several times, but without satisfying result
so far.
Generally the problem boils down to the issue of how triggers
should handle multiple synchronized LED class devices in a backwards
compatible way with monochrome LEDs.
At some point the HSV [0] approach was proposed, but there was a problem
with getting uniform colors across devices. Especially white.
Certainly a calibration mechanism would be required.
[0] https://lkml.org/lkml/2017/8/30/423
--
Best regards,
Jacek Anaszewski
Hi Jacek,
On 09/11/2018 22.42, Jacek Anaszewski wrote:
> Hi Vesa,
>
> On 11/09/2018 09:32 AM, Vesa Jääskeläinen wrote:
>> On 07/11/2018 0.07, Jacek Anaszewski wrote:
>>> Introduce dedicated properties for conveying information about
>>> LED function and color. Mark old "label" property as deprecated.
>>>
>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>> Cc: Baolin Wang <[email protected]>
>>> Cc: Daniel Mack <[email protected]>
>>> Cc: Dan Murphy <[email protected]>
>>> Cc: Linus Walleij <[email protected]>
>>> Cc: Oleh Kravchenko <[email protected]>
>>> Cc: Sakari Ailus <[email protected]>
>>> Cc: Simon Shields <[email protected]>
>>> Cc: Xiaotong Lu <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/leds/common.txt | 52
>>> +++++++++++++++++++----
>>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/leds/common.txt
>>> b/Documentation/devicetree/bindings/leds/common.txt
>>> index aa13998..3efc826 100644
>>> --- a/Documentation/devicetree/bindings/leds/common.txt
>>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>>> @@ -10,14 +10,20 @@ can influence the way of the LED device
>>> initialization, the LED components
>>> have to be tightly coupled with the LED device binding. They are
>>> represented
>>> by child nodes of the parent LED device binding.
>>> +
>>> Optional properties for child nodes:
>>> - led-sources : List of device current outputs the LED is connected
>>> to. The
>>> outputs are identified by the numbers that must be defined
>>> in the LED device binding documentation.
>>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed
>>> definitions
>>> + from the header include/dt-bindings/leds/functions.h.
>>> + If there is no matching LED_FUNCTION available, add a new one.
>>> +- color : Color of the LED.
>>
>> We have had for years out-of-tree patch for multi color gpio led driver
>> which extends this concept with multiple colors. Then in sysfs there has
>> been possibility to control the color and otherwise use blinking or
>> other features.
>>
>> Our need is multi color status led of the device which includes
>> different kind of blinkings and colors on different situations.
>>
>> Current in-tree gpio led driver just wasn't atomic enough and a bit
>> clumsy interface for handling this.
>>
>> Now that this is being looked at could we come up with solution that we
>> could define multiple colors for one led in device tree and then we
>> could work on getting the driver upstreamed?
>>
>> What we did was generally:
>>
>> leds-multi {
>> compatible = "gpio-multi-leds";
>>
>> status {
>> gpios = <...>;
>> linux,default-trigger = "none";
>> deafult-state = "keep";
>>
>> color-red {
>> pin-mask = <0x01>;
>> };
>>
>> color-green {
>> pin-mask = <0x02>;
>> };
>>
>> color-orange {
>> pin-mask = <0x03>;
>> };
>> };
>> };
>>
>
> Device Tree node implementation doesn't actually say too much
> about the sysfs interface you came up with, which is most vital
> in this case.
In our case it is very simple. There is "color" named sysfs node under
gpio instance.
It creates own led instance for each children in this case it is named
as "status" and then uses properties under it to define operation.
Currently we do have fixed list of color names in driver to require
"standardized" names but that could be easily changed to be dynamic.
Driver registers all GPIOs defined in "gpios" under the instance.
So one can say:
echo "orange" > color
This setting goes to the driver, it figures out logical name "orange"
and the configure all listed GPIO's to its "pin-mask" state. Polarity of
the GPIO's is configured in GPIO definition so this is more or less turn
this particular pin to activate state.
So in this case it changes led's color to orange and still lets one to
use standard led triggers. Eg. set periodic blinking or so.
If one cat's "color" it lists all available colors for user and shows
which one is active.
When brightness is configured as zero the all registered go to off state
and when non-zero then it goes to state what ever is configured with
"color" sysfs entry.
> Support for RGB LEDs, or other variations of LED synchronization
> have been approached several times, but without satisfying result
> so far.
>
> Generally the problem boils down to the issue of how triggers
> should handle multiple synchronized LED class devices in a backwards
> compatible way with monochrome LEDs.
>
> At some point the HSV [0] approach was proposed, but there was a problem
> with getting uniform colors across devices. Especially white.
> Certainly a calibration mechanism would be required.
>
> [0] https://lkml.org/lkml/2017/8/30/423
We do not usually use PWM controlled leds so our calibration has been HW
engineer tuning the resistors for the leds to get acceptable color for
different colors variations.
If one wants to have fixed colors for such device then one could use
this similar method to define them or/and free form interface to enter
RGB values there. Thou with PWM RGB leds you probably want to have more
animation there which probably would require some additional support code.
One way to do atomic PWM RGB color change with sysfs could be:
echo "21 223 242" > color
or
echo "21 223 242" > rgb
or:
echo "r:21 g:232 b:242" > color (or something similar)
and if there is know registered name then just write it to "color" which
would pick registered color rgb values to led instances rgb value.
Now for PWM RGB led one could use "brightness" and "rgb" value to
calculate actual color with some color space formula (like hsv in [0]).
Doing white with RGB LED is a bit hard so usually you want to get RGBW
LED (or RGBAW LED) if "real" white is something that is needed. This
could then be "rgbw" entry and "color" to pick from fixed set.
These presets in device tree for "color" could be considered one way of
doing calibration for particular hardware.
So in device tree for RGB PWM led it could be like:
color-orange {
rgb = <249 197 9>
}
color-warm-white {
rgb = <255 253 249>
}
How would that sound like?
Thanks,
Vesa Jääskeläinen
Hi!
> Add common LED function definitions for use in Device Tree.
> The function names were extracted from existing dts files
> after eliminating oddities.
Thanks for doing this.
> diff --git a/include/dt-bindings/leds/functions.h b/include/dt-bindings/leds/functions.h
> new file mode 100644
> index 0000000..3f94e09
> --- /dev/null
> +++ b/include/dt-bindings/leds/functions.h
> @@ -0,0 +1,101 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#define LED_FUNCTION_2G "2g"
> +#define LED_FUNCTION_ACTIVITY "activity"
> +#define LED_FUNCTION_ADSL "adsl"
> +#define LED_FUNCTION_ALARM "alarm"
> +#define LED_FUNCTION_ALIVE "alive"
> +#define LED_FUNCTION_ALL "all"
> +#define LED_FUNCTION_APP "app"
> +#define LED_FUNCTION_AUX "aux"
> +#define LED_FUNCTION_BACKUP "backup"
> +#define LED_FUNCTION_BACKLIGHT "backlight"
> +#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
Sounds like one of backlight and backlight_cluster should be deprecated?
> +#define LED_FUNCTION_BEEP "beep"
> +#define LED_FUNCTION_BLUETOOTH "bluetooth"
> +#define LED_FUNCTION_BOOT "boot"
> +#define LED_FUNCTION_BOTTOM "bottom"
I believe some of these should get comments. For example what does
"all" and "bottom" LEDs do?
> +#define LED_FUNCTION_BRICK_STATUS "brick-status"
> +#define LED_FUNCTION_CEL "cel"
> +#define LED_FUNCTION_CEL_PWR "cel-pwr"
> +#define LED_FUNCTION_CEL_RESET "cel-reset"
> +#define LED_FUNCTION_CHRG "chrg"
> +#define LED_FUNCTION_COM "com"
> +#define LED_FUNCTION_COPY "copy"
> +#define LED_FUNCTION_CPU "cpu"
> +#define LED_FUNCTION_DEBUG "debug"
> +#define LED_FUNCTION_DIA "dia"
What does this one do?
> +#define LED_FUNCTION_DISK "disk"
We have disk, hd, hdd and sata. Deprecate some?
> +#define LED_FUNCTION_DISPLAY_CLUSTER "display_cluster"
> +#define LED_FUNCTION_DOWN "down"
> +#define LED_FUNCTION_DSL "dsl"
> +#define LED_FUNCTION_ENOCEAN "enocean"
> +#define LED_FUNCTION_ENTER "enter"
> +#define LED_FUNCTION_ERROR "error"
> +#define LED_FUNCTION_ESATA "esata"
> +#define LED_FUNCTION_ETHERNET_STATUS "ethernet-status"
> +#define LED_FUNCTION_FAIL "fail"
> +#define LED_FUNCTION_FAULT "fault"
> +#define LED_FUNCTION_FLASH "flash"
> +#define LED_FUNCTION_FRONT "front"
> +#define LED_FUNCTION_FUNC "func"
> +#define LED_FUNCTION_GPIO "gpio"
> +#define LED_FUNCTION_GSM "gsm"
> +#define LED_FUNCTION_HD "hd"
> +#define LED_FUNCTION_HDD "hdd"
> +#define LED_FUNCTION_HDDERR "hdderr"
Ok, I'll
> +#define LED_FUNCTION_HEALTH "health"
> +#define LED_FUNCTION_HEARTBEAT "heartbeat"
Sounds same as alive, deprecate alive?
> +#define LED_FUNCTION_WIFI "wifi"
> +#define LED_FUNCTION_WIRELESS "wireless"
> +#define LED_FUNCTION_WLAN "wlan"
Same as wifi and wireless, I guess, deprecate some?
I'll touch same subject in another email.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue 2018-11-06 23:07:09, Jacek Anaszewski wrote:
> Replace of_led_classdev_register() with led_classdev_register_ext(), which
> accepts easily extendable struct led_init_data, instead of the fixed
> struct device_node argument. The latter can be now passed in a fwnode
> property of the struct led_init_data.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Baolin Wang <[email protected]>
> Cc: Daniel Mack <[email protected]>
> Cc: Dan Murphy <[email protected]>
> Cc: Linus Walleij <[email protected]>
> Cc: Oleh Kravchenko <[email protected]>
> Cc: Sakari Ailus <[email protected]>
> Cc: Simon Shields <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
With Baolin's comments addressed:
Acked-by: Pavel Machek <[email protected]>
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
> Add public led_compose_name() API for composing LED class device
> name basing on fwnode_handle data. The function composes device name
> according to either a new <color:function> pattern or the legacy
> <devicename:color:function> pattern. The decision on using the
> particular pattern is made basing on whether fwnode contains new
> "function" and "color" properties, or the legacy "label" proeprty.
>
> Backwards compatibility with in-driver hard-coded LED class device
> names is assured thanks to the default_desc argument.
>
> In case none of the aformentioned properties was found, then, for OF
> nodes, the node name is adopted for LED class device name.
>
> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
> index 836cb16..e9009c4 100644
> --- a/Documentation/leds/leds-class.txt
> +++ b/Documentation/leds/leds-class.txt
> @@ -43,7 +43,7 @@ LED Device Naming
>
> Is currently of the form:
>
> -"devicename:colour:function"
> +"colour:function"
>
I don't think we want to do it in all cases.
So, on my cellphone seeing lp5523:green:led is indeed not useful.
But on notebook with usb keyboard attached, you need to keep the
devicename to be able to distinguish capslock on internal keyboard and
capslock on first USB keyboard and capslock on second USB keyboard.
Taking look at the list of functions, here's stuff like "hdd" and
"hdderr". I assume the first means hdd activity... If we can do it, it
would be nicest to have "sda:green:activity" and maybe
"sda:red:error". For a raid array with 8 drives...
For example I have a router running linux. It has 4 lan ports, with
correspondings LED, and an wan led.
Having "green:lan1" to "green:lan4" and "green:wan" plus
"red:wanerror" would work, but I'd really preffer
"eth0:green:link"... "adsl0:green:link", "adsl0:red:error".
There are now phones with flashes on both main and selfie
cameras. Again, knowing which device is which is important. As is
knowing which display is controlled by particular backlight.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue 2018-11-06 23:07:13, Jacek Anaszewski wrote:
> Refer to new "function" and "color" properties and mark "label"
> as deprecated.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> Cc: Baolin Wang <[email protected]>
Don't you want to keep both color and label? New dts on old kernel
should still work...?
Ok, I see these are only examples....
Pavel
> @@ -25,17 +27,17 @@ led-controller@200 {
> reg = <0x200>;
>
> led@0 {
> - label = "red";
> + color = "red";
> reg = <0x0>;
> };
>
> led@1 {
> - label = "green";
> + color = "green";
> reg = <0x1>;
> };
>
> led@2 {
> - label = "blue";
> + color = "blue";
> reg = <0x2>;
> };
> };
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue 2018-11-06 23:07:14, Jacek Anaszewski wrote:
> Switch to using generic LED support for composing LED class
> device name.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Xiaotong Lu <[email protected]>
> Cc: Baolin Wang <[email protected]>
Acked-by: Pavel Machek <[email protected]>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue 2018-11-06 23:07:20, Jacek Anaszewski wrote:
> Switch to using generic LED support for composing LED class
> device name.
>
> Signed-off-by: Jacek Anaszewski <[email protected]>
> Cc: Dan Murphy <[email protected]>
Acked-by: Pavel Machek <[email protected]>
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi Pavel,
Thanks for the review.
On 11/11/2018 12:31 PM, Pavel Machek wrote:
> Hi!
>
>> Add common LED function definitions for use in Device Tree.
>> The function names were extracted from existing dts files
>> after eliminating oddities.
>
> Thanks for doing this.
>
>> diff --git a/include/dt-bindings/leds/functions.h b/include/dt-bindings/leds/functions.h
>> new file mode 100644
>> index 0000000..3f94e09
>> --- /dev/null
>> +++ b/include/dt-bindings/leds/functions.h
>> @@ -0,0 +1,101 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>
>> +#define LED_FUNCTION_2G "2g"
>> +#define LED_FUNCTION_ACTIVITY "activity"
>> +#define LED_FUNCTION_ADSL "adsl"
>> +#define LED_FUNCTION_ALARM "alarm"
>> +#define LED_FUNCTION_ALIVE "alive"
>> +#define LED_FUNCTION_ALL "all"
>> +#define LED_FUNCTION_APP "app"
>> +#define LED_FUNCTION_AUX "aux"
>> +#define LED_FUNCTION_BACKUP "backup"
>> +#define LED_FUNCTION_BACKLIGHT "backlight"
>> +#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
>
> Sounds like one of backlight and backlight_cluster should be deprecated?
I think so.
>> +#define LED_FUNCTION_BEEP "beep"
>> +#define LED_FUNCTION_BLUETOOTH "bluetooth"
>> +#define LED_FUNCTION_BOOT "boot"
>> +#define LED_FUNCTION_BOTTOM "bottom"
>
> I believe some of these should get comments. For example what does
> "all" and "bottom" LEDs do?
It would be best to ask the author, but for now,
I'd just remove all of "bottom", "up", "left", "right"
etc.
>> +#define LED_FUNCTION_BRICK_STATUS "brick-status"
>> +#define LED_FUNCTION_CEL "cel"
>> +#define LED_FUNCTION_CEL_PWR "cel-pwr"
>> +#define LED_FUNCTION_CEL_RESET "cel-reset"
>> +#define LED_FUNCTION_CHRG "chrg"
>> +#define LED_FUNCTION_COM "com"
>> +#define LED_FUNCTION_COPY "copy"
>> +#define LED_FUNCTION_CPU "cpu"
>> +#define LED_FUNCTION_DEBUG "debug"
>> +#define LED_FUNCTION_DIA "dia"
>
> What does this one do?
I'd opt for something like "diagnostics", but this is a blind shot.
Let's remove it then and, and let people add more meaningful
definition in case it is needed.
>> +#define LED_FUNCTION_DISK "disk"
>
> We have disk, hd, hdd and sata. Deprecate some?
Disk should be the best choice, especially given that we have
identically named trigger.
>> +#define LED_FUNCTION_DISPLAY_CLUSTER "display_cluster"
>> +#define LED_FUNCTION_DOWN "down"
>> +#define LED_FUNCTION_DSL "dsl"
>> +#define LED_FUNCTION_ENOCEAN "enocean"
>> +#define LED_FUNCTION_ENTER "enter"
>> +#define LED_FUNCTION_ERROR "error"
>> +#define LED_FUNCTION_ESATA "esata"
>> +#define LED_FUNCTION_ETHERNET_STATUS "ethernet-status"
>> +#define LED_FUNCTION_FAIL "fail"
>> +#define LED_FUNCTION_FAULT "fault"
>> +#define LED_FUNCTION_FLASH "flash"
>> +#define LED_FUNCTION_FRONT "front"
>> +#define LED_FUNCTION_FUNC "func"
>> +#define LED_FUNCTION_GPIO "gpio"
>> +#define LED_FUNCTION_GSM "gsm"
>
>> +#define LED_FUNCTION_HD "hd"
>> +#define LED_FUNCTION_HDD "hdd"
>> +#define LED_FUNCTION_HDDERR "hdderr"
>
> Ok, I'll
Hmm?
>
>> +#define LED_FUNCTION_HEALTH "health"
>> +#define LED_FUNCTION_HEARTBEAT "heartbeat"
>
> Sounds same as alive, deprecate alive?
Heartbeat may be designated specifically for registration
for events from the trigger with the same name.
>> +#define LED_FUNCTION_WIFI "wifi"
>> +#define LED_FUNCTION_WIRELESS "wireless"
>> +#define LED_FUNCTION_WLAN "wlan"
>
> Same as wifi and wireless, I guess, deprecate some?
I'd remove "wireless" and "wlan".
> I'll touch same subject in another email.
> Pavel
>
--
Best regards,
Jacek Anaszewski
Hi Pavel,
On 11/11/2018 01:02 PM, Pavel Machek wrote:
> Hi!
>
>> Add public led_compose_name() API for composing LED class device
>> name basing on fwnode_handle data. The function composes device name
>> according to either a new <color:function> pattern or the legacy
>> <devicename:color:function> pattern. The decision on using the
>> particular pattern is made basing on whether fwnode contains new
>> "function" and "color" properties, or the legacy "label" proeprty.
>>
>> Backwards compatibility with in-driver hard-coded LED class device
>> names is assured thanks to the default_desc argument.
>>
>> In case none of the aformentioned properties was found, then, for OF
>> nodes, the node name is adopted for LED class device name.
>>
>
>> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
>> index 836cb16..e9009c4 100644
>> --- a/Documentation/leds/leds-class.txt
>> +++ b/Documentation/leds/leds-class.txt
>> @@ -43,7 +43,7 @@ LED Device Naming
>>
>> Is currently of the form:
>>
>> -"devicename:colour:function"
>> +"colour:function"
>>
>
> I don't think we want to do it in all cases.
>
> So, on my cellphone seeing lp5523:green:led is indeed not useful.
>
> But on notebook with usb keyboard attached, you need to keep the
> devicename to be able to distinguish capslock on internal keyboard and
> capslock on first USB keyboard and capslock on second USB keyboard.
>
> Taking look at the list of functions, here's stuff like "hdd" and
> "hdderr". I assume the first means hdd activity... If we can do it, it
> would be nicest to have "sda:green:activity" and maybe
> "sda:red:error". For a raid array with 8 drives...
>
> For example I have a router running linux. It has 4 lan ports, with
> correspondings LED, and an wan led.
>
> Having "green:lan1" to "green:lan4" and "green:wan" plus
> "red:wanerror" would work, but I'd really preffer
> "eth0:green:link"... "adsl0:green:link", "adsl0:red:error".
>
> There are now phones with flashes on both main and selfie
> cameras. Again, knowing which device is which is important. As is
> knowing which display is controlled by particular backlight.
It's overcomplicating the naming again. In every case you can tweak
the function name to eth0_link, eth1_link etc.
--
Best regards,
Jacek Anaszewski
Hi Pavel.
On 11/11/2018 03:29 PM, Pavel Machek wrote:
> On Tue 2018-11-06 23:07:13, Jacek Anaszewski wrote:
>> Refer to new "function" and "color" properties and mark "label"
>> as deprecated.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>
> Don't you want to keep both color and label? New dts on old kernel
> should still work...?
>
> Ok, I see these are only examples....
Right, this is only an example, and we'd rather want to encourage
people to switch to using new LED naming.
>> @@ -25,17 +27,17 @@ led-controller@200 {
>> reg = <0x200>;
>>
>> led@0 {
>> - label = "red";
>> + color = "red";
>> reg = <0x0>;
>> };
>>
>> led@1 {
>> - label = "green";
>> + color = "green";
>> reg = <0x1>;
>> };
>>
>> led@2 {
>> - label = "blue";
>> + color = "blue";
>> reg = <0x2>;
>> };
>> };
>
--
Best regards,
Jacek Anaszewski
Hi!
> >> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
> >> index 836cb16..e9009c4 100644
> >> --- a/Documentation/leds/leds-class.txt
> >> +++ b/Documentation/leds/leds-class.txt
> >> @@ -43,7 +43,7 @@ LED Device Naming
> >>
> >> Is currently of the form:
> >>
> >> -"devicename:colour:function"
> >> +"colour:function"
> >>
> >
> > I don't think we want to do it in all cases.
> >
> > So, on my cellphone seeing lp5523:green:led is indeed not useful.
> >
> > But on notebook with usb keyboard attached, you need to keep the
> > devicename to be able to distinguish capslock on internal keyboard and
> > capslock on first USB keyboard and capslock on second USB keyboard.
> >
> > Taking look at the list of functions, here's stuff like "hdd" and
> > "hdderr". I assume the first means hdd activity... If we can do it, it
> > would be nicest to have "sda:green:activity" and maybe
> > "sda:red:error". For a raid array with 8 drives...
> >
> > For example I have a router running linux. It has 4 lan ports, with
> > correspondings LED, and an wan led.
> >
> > Having "green:lan1" to "green:lan4" and "green:wan" plus
> > "red:wanerror" would work, but I'd really preffer
> > "eth0:green:link"... "adsl0:green:link", "adsl0:red:error".
> >
> > There are now phones with flashes on both main and selfie
> > cameras. Again, knowing which device is which is important. As is
> > knowing which display is controlled by particular backlight.
>
> It's overcomplicating the naming again. In every case you can tweak
> the function name to eth0_link, eth1_link etc.
Well, but in such case it would be good to keep existing scheme.
My system looks like this:
input16::capslock tpacpi::bay_active tpacpi::standby
input16::numlock tpacpi::dock_active tpacpi::thinklight
input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
I agree that we should get rid of "tpacpi:" part in some cases. But
it does not make sense to get rid of "input16:" part -- it tells you
if the LED is on USB or on built-in keyboard.
Ideally, tpacpi::thinklight would be input5::frontlight (as it is
frontlight for the keyboard).
Yes we should simplify, but it still needs to work in all cases.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
> >> +#define LED_FUNCTION_BACKLIGHT "backlight"
> >> +#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
> >
> > Sounds like one of backlight and backlight_cluster should be deprecated?
>
> I think so.
Agreed.
> >> +#define LED_FUNCTION_DEBUG "debug"
> >> +#define LED_FUNCTION_DIA "dia"
> >
> > What does this one do?
>
> I'd opt for something like "diagnostics", but this is a blind shot.
> Let's remove it then and, and let people add more meaningful
> definition in case it is needed.
>
> >> +#define LED_FUNCTION_DISK "disk"
> >
> > We have disk, hd, hdd and sata. Deprecate some?
>
> Disk should be the best choice, especially given that we have
> identically named trigger.
Ok.
> >> +#define LED_FUNCTION_HD "hd"
> >> +#define LED_FUNCTION_HDD "hdd"
> >> +#define LED_FUNCTION_HDDERR "hdderr"
> >
> > Ok, I'll
>
> Hmm?
I was going to say that I'll bring it up in different email.
I believe we should have disk:green:activity and disk:red:error, not
"green:hdd" and "red:hdderr".
> >> +#define LED_FUNCTION_HEALTH "health"
> >> +#define LED_FUNCTION_HEARTBEAT "heartbeat"
> >
> > Sounds same as alive, deprecate alive?
>
> Heartbeat may be designated specifically for registration
> for events from the trigger with the same name.
Ok. What is "alive" then?
> >> +#define LED_FUNCTION_WIFI "wifi"
> >> +#define LED_FUNCTION_WIRELESS "wireless"
> >> +#define LED_FUNCTION_WLAN "wlan"
> >
> > Same as wifi and wireless, I guess, deprecate some?
>
> I'd remove "wireless" and "wlan".
Actually I'd keep wlan, but... :-).
We may want to do add some comments there, and sort it "most
common/recommended first" or something.
Best regards (and thanks for doing the work),
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On 11/11/2018 09:16 PM, Pavel Machek wrote:
> Hi!
>
>>>> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
>>>> index 836cb16..e9009c4 100644
>>>> --- a/Documentation/leds/leds-class.txt
>>>> +++ b/Documentation/leds/leds-class.txt
>>>> @@ -43,7 +43,7 @@ LED Device Naming
>>>>
>>>> Is currently of the form:
>>>>
>>>> -"devicename:colour:function"
>>>> +"colour:function"
>>>>
>>>
>>> I don't think we want to do it in all cases.
>>>
>>> So, on my cellphone seeing lp5523:green:led is indeed not useful.
>>>
>>> But on notebook with usb keyboard attached, you need to keep the
>>> devicename to be able to distinguish capslock on internal keyboard and
>>> capslock on first USB keyboard and capslock on second USB keyboard.
>>>
>>> Taking look at the list of functions, here's stuff like "hdd" and
>>> "hdderr". I assume the first means hdd activity... If we can do it, it
>>> would be nicest to have "sda:green:activity" and maybe
>>> "sda:red:error". For a raid array with 8 drives...
>>>
>>> For example I have a router running linux. It has 4 lan ports, with
>>> correspondings LED, and an wan led.
>>>
>>> Having "green:lan1" to "green:lan4" and "green:wan" plus
>>> "red:wanerror" would work, but I'd really preffer
>>> "eth0:green:link"... "adsl0:green:link", "adsl0:red:error".
>>>
>>> There are now phones with flashes on both main and selfie
>>> cameras. Again, knowing which device is which is important. As is
>>> knowing which display is controlled by particular backlight.
>>
>> It's overcomplicating the naming again. In every case you can tweak
>> the function name to eth0_link, eth1_link etc.
>
> Well, but in such case it would be good to keep existing scheme.
>
> My system looks like this:
>
> input16::capslock tpacpi::bay_active tpacpi::standby
> input16::numlock tpacpi::dock_active tpacpi::thinklight
> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
>
> I agree that we should get rid of "tpacpi:" part in some cases. But
> it does not make sense to get rid of "input16:" part -- it tells you
> if the LED is on USB or on built-in keyboard.
>
> Ideally, tpacpi::thinklight would be input5::frontlight (as it is
> frontlight for the keyboard).
>
> Yes we should simplify, but it still needs to work in all cases.
Well, label is not being removed. You still can use it an the old
fashion, even when using new led_compose_name().
Maybe removing the description of the old LED naming from
Documentation/leds/leds-class.txt was too drastic move.
I'll keep it next to the new one, and only add a note that
it is kept only for backwards compatibility.
--
Best regards,
Jacek Anaszewski
On 11/11/2018 09:20 PM, Pavel Machek wrote:
> Hi!
>
>>>> +#define LED_FUNCTION_BACKLIGHT "backlight"
>>>> +#define LED_FUNCTION_BACKLIGHT_CLUSTER "backlight_cluster"
>>>
>>> Sounds like one of backlight and backlight_cluster should be deprecated?
>>
>> I think so.
>
> Agreed.
>
>>>> +#define LED_FUNCTION_DEBUG "debug"
>>>> +#define LED_FUNCTION_DIA "dia"
>>>
>>> What does this one do?
>>
>> I'd opt for something like "diagnostics", but this is a blind shot.
>> Let's remove it then and, and let people add more meaningful
>> definition in case it is needed.
>>
>>>> +#define LED_FUNCTION_DISK "disk"
>>>
>>> We have disk, hd, hdd and sata. Deprecate some?
>>
>> Disk should be the best choice, especially given that we have
>> identically named trigger.
>
> Ok.
>
>>>> +#define LED_FUNCTION_HD "hd"
>>>> +#define LED_FUNCTION_HDD "hdd"
>>>> +#define LED_FUNCTION_HDDERR "hdderr"
>>>
>>> Ok, I'll
>>
>> Hmm?
>
> I was going to say that I'll bring it up in different email.
>
> I believe we should have disk:green:activity and disk:red:error, not
> "green:hdd" and "red:hdderr".
How would you propose to name the section corresponding to "disk",
if "function" is occupied by "activity"? Should it deserve a separate
DT property?
>>>> +#define LED_FUNCTION_HEALTH "health"
>>>> +#define LED_FUNCTION_HEARTBEAT "heartbeat"
>>>
>>> Sounds same as alive, deprecate alive?
>>
>> Heartbeat may be designated specifically for registration
>> for events from the trigger with the same name.
>
> Ok. What is "alive" then?
Tells whether something is active or not?
In this case it seems to overlap with "pwr" probably.
>>>> +#define LED_FUNCTION_WIFI "wifi"
>>>> +#define LED_FUNCTION_WIRELESS "wireless"
>>>> +#define LED_FUNCTION_WLAN "wlan"
>>>
>>> Same as wifi and wireless, I guess, deprecate some?
>>
>> I'd remove "wireless" and "wlan".
>
> Actually I'd keep wlan, but... :-).
It may depend of the regional preferences.
> We may want to do add some comments there, and sort it "most
> common/recommended first" or something.
>
> Best regards (and thanks for doing the work),
I'm doing it also for myself to avoid extra lines for
explaining the LED naming quirks every time a new driver
is submitted :-)
--
Best regards,
Jacek Anaszewski
Hi,
On 11/11/2018 23.14, Jacek Anaszewski wrote:
> On 11/11/2018 09:16 PM, Pavel Machek wrote:
>> Hi!
>>
>>>>> diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt
>>>>> index 836cb16..e9009c4 100644
>>>>> --- a/Documentation/leds/leds-class.txt
>>>>> +++ b/Documentation/leds/leds-class.txt
>>>>> @@ -43,7 +43,7 @@ LED Device Naming
>>>>>
>>>>> Is currently of the form:
>>>>>
>>>>> -"devicename:colour:function"
>>>>> +"colour:function"
Couldn't we have here multiple variants that would then be chosen based
on device tree definition?
"devicename:colour:function"
"devicename:function"
"devicename:label"
"colour:function"
"function"
"label"
If "label" would be specified then just use that as a led name, giving name:
- label
If "function" would be defined then go to special formatting with
optional "color", giving names:
- color:function
- function
I suppose 'devicename' would then be automatically filled based on
driver instance unless one defines 'no-devicename' or something like
that for led definition.
Personally I do not see the need for "color" in any led name. In my
opinion the only thing needed here would be location prefix (where
needed -- and it should be possible to disable that) and then logical
name for the led.
>>>> I don't think we want to do it in all cases.
>>>>
>>>> So, on my cellphone seeing lp5523:green:led is indeed not useful.
>>>>
>>>> But on notebook with usb keyboard attached, you need to keep the
>>>> devicename to be able to distinguish capslock on internal keyboard and
>>>> capslock on first USB keyboard and capslock on second USB keyboard.
>>>>
>>>> Taking look at the list of functions, here's stuff like "hdd" and
>>>> "hdderr". I assume the first means hdd activity... If we can do it, it
>>>> would be nicest to have "sda:green:activity" and maybe
>>>> "sda:red:error". For a raid array with 8 drives...
>>>>
>>>> For example I have a router running linux. It has 4 lan ports, with
>>>> correspondings LED, and an wan led.
>>>>
>>>> Having "green:lan1" to "green:lan4" and "green:wan" plus
>>>> "red:wanerror" would work, but I'd really preffer
>>>> "eth0:green:link"... "adsl0:green:link", "adsl0:red:error".
>>>>
>>>> There are now phones with flashes on both main and selfie
>>>> cameras. Again, knowing which device is which is important. As is
>>>> knowing which display is controlled by particular backlight.
>>>
>>> It's overcomplicating the naming again. In every case you can tweak
>>> the function name to eth0_link, eth1_link etc.
>>
>> Well, but in such case it would be good to keep existing scheme.
>>
>> My system looks like this:
>>
>> input16::capslock tpacpi::bay_active tpacpi::standby
>> input16::numlock tpacpi::dock_active tpacpi::thinklight
>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
>>
>> I agree that we should get rid of "tpacpi:" part in some cases. But
>> it does not make sense to get rid of "input16:" part -- it tells you
>> if the LED is on USB or on built-in keyboard.
>>
>> Ideally, tpacpi::thinklight would be input5::frontlight (as it is
>> frontlight for the keyboard).
>>
>> Yes we should simplify, but it still needs to work in all cases.
>
> Well, label is not being removed. You still can use it an the old
> fashion, even when using new led_compose_name().
>
> Maybe removing the description of the old LED naming from
> Documentation/leds/leds-class.txt was too drastic move.
> I'll keep it next to the new one, and only add a note that
> it is kept only for backwards compatibility.
With above proposal for naming it should match more or less everyone's
needs?
Simple naming for embedded device makers and more advanced for server
system makers.
No need to say that something is legacy or backwards compatibility feature.
Thanks,
Vesa Jääskeläinen
Hi Jacek,
On 07/11/2018 0.07, Jacek Anaszewski wrote:
> Add common LED function definitions for use in Device Tree.
> The function names were extracted from existing dts files
> after eliminating oddities.
Is your intent here is to standardize the function definitions and to
aid in that is to specify list of string defines?
Without a meaning what all of those mean it does complete the original goal.
In your list there are many things that could easily have multiple
meanings for different audiences.
Some examples:
#define LED_FUNCTION_2G "2g"
- Does this mean that 2 metric grams has been detected in scale or
cellular 2G connectivity?
#define LED_FUNCTION_ALL "all"
- This doesn't ring a bell to me what it could be in reality. All leds
on doesn't sound right.
#define LED_FUNCTION_AUX "aux"
- There can be many things aux and multiple aux things in one device.
#define LED_FUNCTION_HD "hd"
- Is there a high definition video playing? Or audio? Or harddisk
failure led?
You have already come up with long list of items. I am just wondering
what is the logic in order to get to "common" list?
Can you just add custom items in device tree without being in the list?
Would it be better to start with a short simple list with meanings
defined properly?
When do you then remove entries from the list? Let's say 3G networks are
currently getting turned off world wide which kinda deprecates the term
from definitions and probably should be then removed from the list (if
it would be there).
Is there planned to be some auto connection from function to some other
automated functionality? Or why wouldn't the label keyword be enough as
it seems to be exactly the same thing? (without the common list -- which
could be implemented for label too if seen as a good thing)
Thanks,
Vesa Jääskeläinen
Hi!
> >> It's overcomplicating the naming again. In every case you can tweak
> >> the function name to eth0_link, eth1_link etc.
> >
> > Well, but in such case it would be good to keep existing scheme.
> >
> > My system looks like this:
> >
> > input16::capslock tpacpi::bay_active tpacpi::standby
> > input16::numlock tpacpi::dock_active tpacpi::thinklight
> > input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
> > input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
> > input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
> > input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
> >
> > I agree that we should get rid of "tpacpi:" part in some cases. But
> > it does not make sense to get rid of "input16:" part -- it tells you
> > if the LED is on USB or on built-in keyboard.
> >
> > Ideally, tpacpi::thinklight would be input5::frontlight (as it is
> > frontlight for the keyboard).
> >
> > Yes we should simplify, but it still needs to work in all cases.
>
> Well, label is not being removed. You still can use it an the old
> fashion, even when using new led_compose_name().
>
> Maybe removing the description of the old LED naming from
> Documentation/leds/leds-class.txt was too drastic move.
> I'll keep it next to the new one, and only add a note that
> it is kept only for backwards compatibility.
I agree that removing it is "just too drastic".
But it is not just for backwards compatibility. See my examples above,
it is needed to tell which device the LED is asociated with, and it is
absolutely required for USB devices (for example).
And even for "embedded" stuff like routers, we want eth0:green:link,
eth0:yellow:activity and not some kind of hack.
Ideally, colors would come from fixed list, functions would come from
fixed list, and device part would come from name used elsewhere in the
kernel.
(And yes, it probably means we should have something in device tree to
link LED to its device. device = "name" would be good start...)
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On 11/12/2018 01:01 AM, Vesa Jääskeläinen wrote:
> Hi,
>
> On 11/11/2018 23.14, Jacek Anaszewski wrote:
>> On 11/11/2018 09:16 PM, Pavel Machek wrote:
>>> Hi!
>>>
>>>>>> diff --git a/Documentation/leds/leds-class.txt
>>>>>> b/Documentation/leds/leds-class.txt
>>>>>> index 836cb16..e9009c4 100644
>>>>>> --- a/Documentation/leds/leds-class.txt
>>>>>> +++ b/Documentation/leds/leds-class.txt
>>>>>> @@ -43,7 +43,7 @@ LED Device Naming
>>>>>> Is currently of the form:
>>>>>> -"devicename:colour:function"
>>>>>> +"colour:function"
>
> Couldn't we have here multiple variants that would then be chosen based
> on device tree definition?
>
> "devicename:colour:function"
> "devicename:function"
> "devicename:label"
> "colour:function"
> "function"
> "label"
Documentation/leds/leds-class.txt in a description of
"devicename:colour:function" naming scheme states the following:
"If sections of the name don't apply, just leave that section blank"
Currently not many Device Tree nodes follow that recommendation but with
the led_compose_name() I'm going to enforce it (only for the
devicename-less naming scheme), which is needed for reliable parsing of
LED color and function, which with naming schemes you proposed it
wouldn't be possible.
But, even with led_compose_name(), it will be possible to get the
names listed by you:
If you provide the 'label' property in the DT, then with the new
led_compose_name() you will get the LED class device name in one of the
two below forms, depending on the parameters passed to the function:
- If led_hw_name argument is not NULL:
led_hw_name:label
- If led_hw_name argument is NULL then the label is taken as-is for
for LED class device name (it may be appended a numerical suffix if
the name is already taken)
This flexibility is for backwards compatibility with existing drivers,
where some of them add devicename section to the parsed DT label,
and others adopts the DT label as-is for LED class device name,
relying on DT to provide the devicename.
> If "label" would be specified then just use that as a led name, giving
> name:
> - label
Please get acquainted with the entire patch set, the commit messages,
and the documentation of led_compose_name(). You'll find out that
this is exactly how led_compose_name() is designed.
> If "function" would be defined then go to special formatting with
> optional "color", giving names:
> - color:function
> - function
Color must not be omitted as explained above. Of course in case 'label'
is provided, it won't be validated in any way, thus allowing for any
combination. With the 'color' and/or 'function' DT properties you'll
get one of the following:
- color:function
- :function
- color:
Having considered all the above, I'd even propose to change the
delimiter for the new naming convention from ":" to "-", to make it
possible to distinguish between old and new naming convention.
> I suppose 'devicename' would then be automatically filled based on
> driver instance unless one defines 'no-devicename' or something like
> that for led definition.
devicename section is problematic in the LED class device name,
since it doesn't allow for having uniform userspace interface across
different platforms. Think of Android - I've seen they have their own
LED naming scheme which doesn't contain devicename section.
Also, please refer to the DT maintainer's opinion in this regard [0],
which actually drew my attention to the problem.
Please keep in mind that devicename has been so far used for
board vendor name or LED controller name.
> Personally I do not see the need for "color" in any led name. In my
> opinion the only thing needed here would be location prefix (where
> needed -- and it should be possible to disable that) and then logical
> name for the led.
You mean we don't need the color information at all?
And could you please explain what do you mean by "location prefix"?
>>>>> I don't think we want to do it in all cases.
>>>>>
>>>>> So, on my cellphone seeing lp5523:green:led is indeed not useful.
>>>>>
>>>>> But on notebook with usb keyboard attached, you need to keep the
>>>>> devicename to be able to distinguish capslock on internal keyboard and
>>>>> capslock on first USB keyboard and capslock on second USB keyboard.
>>>>>
>>>>> Taking look at the list of functions, here's stuff like "hdd" and
>>>>> "hdderr". I assume the first means hdd activity... If we can do it, it
>>>>> would be nicest to have "sda:green:activity" and maybe
>>>>> "sda:red:error". For a raid array with 8 drives...
>>>>>
>>>>> For example I have a router running linux. It has 4 lan ports, with
>>>>> correspondings LED, and an wan led.
>>>>>
>>>>> Having "green:lan1" to "green:lan4" and "green:wan" plus
>>>>> "red:wanerror" would work, but I'd really preffer
>>>>> "eth0:green:link"... "adsl0:green:link", "adsl0:red:error".
>>>>>
>>>>> There are now phones with flashes on both main and selfie
>>>>> cameras. Again, knowing which device is which is important. As is
>>>>> knowing which display is controlled by particular backlight.
>>>>
>>>> It's overcomplicating the naming again. In every case you can tweak
>>>> the function name to eth0_link, eth1_link etc.
>>>
>>> Well, but in such case it would be good to keep existing scheme.
>>>
>>> My system looks like this:
>>>
>>> input16::capslock tpacpi::bay_active tpacpi::standby
>>> input16::numlock tpacpi::dock_active tpacpi::thinklight
>>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
>>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
>>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
>>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
>>>
>>> I agree that we should get rid of "tpacpi:" part in some cases. But
>>> it does not make sense to get rid of "input16:" part -- it tells you
>>> if the LED is on USB or on built-in keyboard.
>>>
>>> Ideally, tpacpi::thinklight would be input5::frontlight (as it is
>>> frontlight for the keyboard).
>>>
>>> Yes we should simplify, but it still needs to work in all cases.
>>
>> Well, label is not being removed. You still can use it an the old
>> fashion, even when using new led_compose_name().
>>
>> Maybe removing the description of the old LED naming from
>> Documentation/leds/leds-class.txt was too drastic move.
>> I'll keep it next to the new one, and only add a note that
>> it is kept only for backwards compatibility.
>
> With above proposal for naming it should match more or less everyone's
> needs?
>
> Simple naming for embedded device makers and more advanced for server
> system makers.
>
> No need to say that something is legacy or backwards compatibility feature.
[0]
https://www.mail-archive.com/[email protected]/msg1559757.html
--
Best regards,
Jacek Anaszewski
Hi,
On 11/12/2018 11:35 AM, Pavel Machek wrote:
> Hi!
>
>>>> It's overcomplicating the naming again. In every case you can tweak
>>>> the function name to eth0_link, eth1_link etc.
>>>
>>> Well, but in such case it would be good to keep existing scheme.
>>>
>>> My system looks like this:
>>>
>>> input16::capslock tpacpi::bay_active tpacpi::standby
>>> input16::numlock tpacpi::dock_active tpacpi::thinklight
>>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
>>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
>>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
>>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
>>>
>>> I agree that we should get rid of "tpacpi:" part in some cases. But
>>> it does not make sense to get rid of "input16:" part -- it tells you
>>> if the LED is on USB or on built-in keyboard.
>>>
>>> Ideally, tpacpi::thinklight would be input5::frontlight (as it is
>>> frontlight for the keyboard).
>>>
>>> Yes we should simplify, but it still needs to work in all cases.
>>
>> Well, label is not being removed. You still can use it an the old
>> fashion, even when using new led_compose_name().
>>
>> Maybe removing the description of the old LED naming from
>> Documentation/leds/leds-class.txt was too drastic move.
>> I'll keep it next to the new one, and only add a note that
>> it is kept only for backwards compatibility.
>
> I agree that removing it is "just too drastic".
>
> But it is not just for backwards compatibility. See my examples above,
> it is needed to tell which device the LED is asociated with, and it is
> absolutely required for USB devices (for example).
For USB devices there is already ledtrig-usbport available, which
provides sysfs interface for defining and reading the usb ports,
the status of which the LED indicates. Since the USB devices can be
attached/removed dynamically, it would be impossible to reflect
the associations in the LED class device name.
> And even for "embedded" stuff like routers, we want eth0:green:link,
> eth0:yellow:activity and not some kind of hack.
eth0 is not something you can be certain of at the stage of defining DT
node.
> Ideally, colors would come from fixed list, functions would come from
> fixed list, and device part would come from name used elsewhere in the
> kernel.
>
> (And yes, it probably means we should have something in device tree to
> link LED to its device. device = "name" would be good start...)
Why would you need such link?
--
Best regards,
Jacek Anaszewski
Hi Vesa,
On 11/10/2018 06:19 PM, Vesa Jääskeläinen wrote:
> Hi Jacek,
>
> On 09/11/2018 22.42, Jacek Anaszewski wrote:
>> Hi Vesa,
>>
>> On 11/09/2018 09:32 AM, Vesa Jääskeläinen wrote:
>>> On 07/11/2018 0.07, Jacek Anaszewski wrote:
>>>> Introduce dedicated properties for conveying information about
>>>> LED function and color. Mark old "label" property as deprecated.
>>>>
>>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>>> Cc: Baolin Wang <[email protected]>
>>>> Cc: Daniel Mack <[email protected]>
>>>> Cc: Dan Murphy <[email protected]>
>>>> Cc: Linus Walleij <[email protected]>
>>>> Cc: Oleh Kravchenko <[email protected]>
>>>> Cc: Sakari Ailus <[email protected]>
>>>> Cc: Simon Shields <[email protected]>
>>>> Cc: Xiaotong Lu <[email protected]>
>>>> ---
>>>> Documentation/devicetree/bindings/leds/common.txt | 52
>>>> +++++++++++++++++++----
>>>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/leds/common.txt
>>>> b/Documentation/devicetree/bindings/leds/common.txt
>>>> index aa13998..3efc826 100644
>>>> --- a/Documentation/devicetree/bindings/leds/common.txt
>>>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>>>> @@ -10,14 +10,20 @@ can influence the way of the LED device
>>>> initialization, the LED components
>>>> have to be tightly coupled with the LED device binding. They are
>>>> represented
>>>> by child nodes of the parent LED device binding.
>>>> +
>>>> Optional properties for child nodes:
>>>> - led-sources : List of device current outputs the LED is connected
>>>> to. The
>>>> outputs are identified by the numbers that must be defined
>>>> in the LED device binding documentation.
>>>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed
>>>> definitions
>>>> + from the header include/dt-bindings/leds/functions.h.
>>>> + If there is no matching LED_FUNCTION available, add a new one.
>>>> +- color : Color of the LED.
>>>
>>> We have had for years out-of-tree patch for multi color gpio led driver
>>> which extends this concept with multiple colors. Then in sysfs there has
>>> been possibility to control the color and otherwise use blinking or
>>> other features.
>>>
>>> Our need is multi color status led of the device which includes
>>> different kind of blinkings and colors on different situations.
>>>
>>> Current in-tree gpio led driver just wasn't atomic enough and a bit
>>> clumsy interface for handling this.
>>>
>>> Now that this is being looked at could we come up with solution that we
>>> could define multiple colors for one led in device tree and then we
>>> could work on getting the driver upstreamed?
>>>
>>> What we did was generally:
>>>
>>> leds-multi {
>>> compatible = "gpio-multi-leds";
>>>
>>> status {
>>> gpios = <...>;
>>> linux,default-trigger = "none";
>>> deafult-state = "keep";
>>>
>>> color-red {
>>> pin-mask = <0x01>;
>>> };
>>>
>>> color-green {
>>> pin-mask = <0x02>;
>>> };
>>>
>>> color-orange {
>>> pin-mask = <0x03>;
>>> };
>>> };
>>> };
>>>
>>
>> Device Tree node implementation doesn't actually say too much
>> about the sysfs interface you came up with, which is most vital
>> in this case.
>
> In our case it is very simple. There is "color" named sysfs node under
> gpio instance.
>
> It creates own led instance for each children in this case it is named
> as "status" and then uses properties under it to define operation.
>
> Currently we do have fixed list of color names in driver to require
> "standardized" names but that could be easily changed to be dynamic.
>
> Driver registers all GPIOs defined in "gpios" under the instance.
>
> So one can say:
>
> echo "orange" > color
>
> This setting goes to the driver, it figures out logical name "orange"
> and the configure all listed GPIO's to its "pin-mask" state. Polarity of
> the GPIO's is configured in GPIO definition so this is more or less turn
> this particular pin to activate state.
>
> So in this case it changes led's color to orange and still lets one to
> use standard led triggers. Eg. set periodic blinking or so.
>
> If one cat's "color" it lists all available colors for user and shows
> which one is active.
>
> When brightness is configured as zero the all registered go to off state
> and when non-zero then it goes to state what ever is configured with
> "color" sysfs entry.
>
>> Support for RGB LEDs, or other variations of LED synchronization
>> have been approached several times, but without satisfying result
>> so far.
>>
>> Generally the problem boils down to the issue of how triggers
>> should handle multiple synchronized LED class devices in a backwards
>> compatible way with monochrome LEDs.
>>
>> At some point the HSV [0] approach was proposed, but there was a problem
>> with getting uniform colors across devices. Especially white.
>> Certainly a calibration mechanism would be required.
>>
>> [0] https://lkml.org/lkml/2017/8/30/423
>
> We do not usually use PWM controlled leds so our calibration has been HW
> engineer tuning the resistors for the leds to get acceptable color for
> different colors variations.
>
> If one wants to have fixed colors for such device then one could use
> this similar method to define them or/and free form interface to enter
> RGB values there. Thou with PWM RGB leds you probably want to have more
> animation there which probably would require some additional support code.
>
> One way to do atomic PWM RGB color change with sysfs could be:
>
> echo "21 223 242" > color
>
> or
>
> echo "21 223 242" > rgb
>
> or:
>
> echo "r:21 g:232 b:242" > color (or something similar)
>
> and if there is know registered name then just write it to "color" which
> would pick registered color rgb values to led instances rgb value.
>
> Now for PWM RGB led one could use "brightness" and "rgb" value to
> calculate actual color with some color space formula (like hsv in [0]).
>
> Doing white with RGB LED is a bit hard so usually you want to get RGBW
> LED (or RGBAW LED) if "real" white is something that is needed. This
> could then be "rgbw" entry and "color" to pick from fixed set.
>
> These presets in device tree for "color" could be considered one way of
> doing calibration for particular hardware.
>
> So in device tree for RGB PWM led it could be like:
>
> color-orange {
> rgb = <249 197 9>
> }
>
> color-warm-white {
> rgb = <255 253 249>
> }
>
> How would that sound like?
Thank you for the description of your approach.
Predefined DT color definitions make an interesting option. Nonetheless,
your design assumes that for RGB LEDs max_brightness would have to be
always 1.
While it would solve the issue, it wouldn't allow to benefit from
the whole potential of RGB LEDs - think of having adjustable "color
brightness" (like in HSV color model).
How abut allowing for providing an array of color intensity/brightness
levels per each color? In the simplest case there could be a single
level per color, but it should be possible to provide up to 255 levels.
--
Best regards,
Jacek Anaszewski
Hi Vesa,
On 11/12/2018 01:25 AM, Vesa Jääskeläinen wrote:
> Hi Jacek,
>
> On 07/11/2018 0.07, Jacek Anaszewski wrote:
>> Add common LED function definitions for use in Device Tree.
>> The function names were extracted from existing dts files
>> after eliminating oddities.
>
> Is your intent here is to standardize the function definitions and to
> aid in that is to specify list of string defines?
The calls for LED names standardization emerged some time go, and this
is just a submission of the subject for a discussion.
> Without a meaning what all of those mean it does complete the original
> goal.
>
> In your list there are many things that could easily have multiple
> meanings for different audiences.
>
> Some examples:
>
> #define LED_FUNCTION_2G "2g"
> - Does this mean that 2 metric grams has been detected in scale or
> cellular 2G connectivity?
Most probably the latter. Should we have the generic macro for it
is another question. Actually I found it in the leds-tlc591xx.txt
bindings. There are also "wlan_2g" occurrences in the armada385-linksys*
dts files.
> #define LED_FUNCTION_ALL "all"
> - This doesn't ring a bell to me what it could be in reality. All leds
> on doesn't sound right.
Yeah, I must admit I didn't spend too much time assessing how much
all of them make sense. I just wanted we had more complete picture
of what functions are pre-existing in the bindings and dts files.
> #define LED_FUNCTION_AUX "aux"
> - There can be many things aux and multiple aux things in one device.
>
> #define LED_FUNCTION_HD "hd"
> - Is there a high definition video playing? Or audio? Or harddisk
> failure led?
>
> You have already come up with long list of items. I am just wondering
> what is the logic in order to get to "common" list?
>
> Can you just add custom items in device tree without being in the list?
>
> Would it be better to start with a short simple list with meanings
> defined properly?
This seems to be the most reasonable approach. My first thought was
to provide function definitions for as many as possible from the
pre-existing ones, but it is not making too much sense as it tunes out.
> When do you then remove entries from the list? Let's say 3G networks are
> currently getting turned off world wide which kinda deprecates the term
> from definitions and probably should be then removed from the list (if
> it would be there).
>
> Is there planned to be some auto connection from function to some other
> automated functionality?
One proposition was to register the LED for a trigger events basing on
the function name, like e.g "heartbeat".
> Or why wouldn't the label keyword be enough as
> it seems to be exactly the same thing? (without the common list -- which
> could be implemented for label too if seen as a good thing)
LED_FUNCTION definitions are not meant to be limited for use only
with color:name scheme, if that's what you had on mind.
--
Best regards,
Jacek Anaszewski
Hi!
> >>> My system looks like this:
> >>>
> >>> input16::capslock tpacpi::bay_active tpacpi::standby
> >>> input16::numlock tpacpi::dock_active tpacpi::thinklight
> >>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
> >>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
> >>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
> >>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
> > But it is not just for backwards compatibility. See my examples above,
> > it is needed to tell which device the LED is asociated with, and it is
> > absolutely required for USB devices (for example).
>
> For USB devices there is already ledtrig-usbport available, which
> provides sysfs interface for defining and reading the usb ports,
> the status of which the LED indicates. Since the USB devices can be
> attached/removed dynamically, it would be impossible to reflect
> the associations in the LED class device name.
I'm not talking USB activity. I'm talking USB devices with LEDs on
them, like for example keyboards.
Please take a look at example above. input16::numlock ;
input5::numlock . You absolutely need device part.
> > And even for "embedded" stuff like routers, we want eth0:green:link,
> > eth0:yellow:activity and not some kind of hack.
>
> eth0 is not something you can be certain of at the stage of defining DT
> node.
In the common case DT is used for, yes, you can, because whole system
is in one box.
(And really DT does not matter. We are talking kernel <-> user
interface here).
> > Ideally, colors would come from fixed list, functions would come from
> > fixed list, and device part would come from name used elsewhere in the
> > kernel.
> >
> > (And yes, it probably means we should have something in device tree to
> > link LED to its device. device = "name" would be good start...)
>
> Why would you need such link?
Because userspace needs that information?
Say you have raid array, with "error" leds for each drive (your list
already contains "hdderr"). Now userland detects problem with hdparm
on /dev/sdi. It would like to turn on corresponding LED.
How do you propose we do that?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On 11/12/2018 08:05 PM, Pavel Machek wrote:
> Hi!
>
>>>>> My system looks like this:
>>>>>
>>>>> input16::capslock tpacpi::bay_active tpacpi::standby
>>>>> input16::numlock tpacpi::dock_active tpacpi::thinklight
>>>>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
>>>>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
>>>>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
>>>>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
>
>>> But it is not just for backwards compatibility. See my examples above,
>>> it is needed to tell which device the LED is asociated with, and it is
>>> absolutely required for USB devices (for example).
>>
>> For USB devices there is already ledtrig-usbport available, which
>> provides sysfs interface for defining and reading the usb ports,
>> the status of which the LED indicates. Since the USB devices can be
>> attached/removed dynamically, it would be impossible to reflect
>> the associations in the LED class device name.
>
> I'm not talking USB activity. I'm talking USB devices with LEDs on
> them, like for example keyboards.
>
> Please take a look at example above. input16::numlock ;
> input5::numlock . You absolutely need device part.
It would be redundant since there is "device" symbolic link
created in given LED class device sysfs directory, pointing to the
corresponding input device directory, like in case of my USB keyboard:
#/sys/class/leds/input5::scrolllock$ ls -l
total 0
-rw-r--r-- 1 root root 4096 Nov 12 20:22 brightness
lrwxrwxrwx 1 root root 0 Nov 12 20:22 device -> ../../input5
-r--r--r-- 1 root root 4096 Nov 12 20:22 max_brightness
drwxr-xr-x 2 root root 0 Nov 12 20:22 power
lrwxrwxrwx 1 root root 0 Nov 12 20:04 subsystem ->
../../../../../../../../../../../class/leds
-rw-r--r-- 1 root root 4096 Nov 12 20:22 trigger
>>> And even for "embedded" stuff like routers, we want eth0:green:link,
>>> eth0:yellow:activity and not some kind of hack.
>>
>> eth0 is not something you can be certain of at the stage of defining DT
>> node.
>
> In the common case DT is used for, yes, you can, because whole system
> is in one box.
Only when all kernel modules are built-in.
> (And really DT does not matter. We are talking kernel <-> user
> interface here).
OK, I was fixed on the devicename understood as LED controller name.
>>> Ideally, colors would come from fixed list, functions would come from
>>> fixed list, and device part would come from name used elsewhere in the
>>> kernel.
>>>
>>> (And yes, it probably means we should have something in device tree to
>>> link LED to its device. device = "name" would be good start...)
>>
>> Why would you need such link?
>
> Because userspace needs that information?
>
> Say you have raid array, with "error" leds for each drive (your list
> already contains "hdderr"). Now userland detects problem with hdparm
> on /dev/sdi. It would like to turn on corresponding LED.
>
> How do you propose we do that?
Similarly as in case of USB keyboard.
--
Best regards,
Jacek Anaszewski
On Sun, Nov 11, 2018 at 1:03 PM Pavel Machek <[email protected]> wrote:
> > -"devicename:colour:function"
> > +"colour:function"
>
> I don't think we want to do it in all cases.
>
> So, on my cellphone seeing lp5523:green:led is indeed not useful.
>
> But on notebook with usb keyboard attached, you need to keep the
> devicename to be able to distinguish capslock on internal keyboard and
> capslock on first USB keyboard and capslock on second USB keyboard.
I agree with Pavel.
I ran into this when connecting two identical keyboards to the
same machine. The driver worked fine up until it tries
to create two sysfs entries with the same name for capslock.
BOOM!
In this case I suggest "serialnumber:color:capslock" and
similar.
The important point is the string must be unique for each
plugged device.
Yours,
Linus Walleij
On Mon, Nov 12, 2018 at 1:02 AM Vesa Jääskeläinen <[email protected]> wrote:
> Couldn't we have here multiple variants that would then be chosen based
> on device tree definition?
It needs to be subsystem specific or something.
What you say make sense for things based on device
tree.
The problem hit me on an Intel laptop with several
USB keyboards.
OK maybe I am stupid for plugging in two USB keyboards,
but we should definately support it. Input/HID supports it
well.
Yours,
Linus Walleij
On Mon 2018-11-12 21:11:32, Jacek Anaszewski wrote:
> On 11/12/2018 08:05 PM, Pavel Machek wrote:
> > Hi!
> >
> >>>>> My system looks like this:
> >>>>>
> >>>>> input16::capslock tpacpi::bay_active tpacpi::standby
> >>>>> input16::numlock tpacpi::dock_active tpacpi::thinklight
> >>>>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
> >>>>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
> >>>>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
> >>>>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
> >
> >>> But it is not just for backwards compatibility. See my examples above,
> >>> it is needed to tell which device the LED is asociated with, and it is
> >>> absolutely required for USB devices (for example).
> >>
> >> For USB devices there is already ledtrig-usbport available, which
> >> provides sysfs interface for defining and reading the usb ports,
> >> the status of which the LED indicates. Since the USB devices can be
> >> attached/removed dynamically, it would be impossible to reflect
> >> the associations in the LED class device name.
> >
> > I'm not talking USB activity. I'm talking USB devices with LEDs on
> > them, like for example keyboards.
> >
> > Please take a look at example above. input16::numlock ;
> > input5::numlock . You absolutely need device part.
>
> It would be redundant since there is "device" symbolic link
> created in given LED class device sysfs directory, pointing to the
> corresponding input device directory, like in case of my USB
> keyboard:
You are right I forgot about the device symlink, and it partly helps
with the USB keyboard case...
But you still need the device part. Sysfs will not like two
directories named "::numlock".
> #/sys/class/leds/input5::scrolllock$ ls -l
> total 0
> -rw-r--r-- 1 root root 4096 Nov 12 20:22 brightness
> lrwxrwxrwx 1 root root 0 Nov 12 20:22 device -> ../../input5
> -r--r--r-- 1 root root 4096 Nov 12 20:22 max_brightness
> drwxr-xr-x 2 root root 0 Nov 12 20:22 power
> lrwxrwxrwx 1 root root 0 Nov 12 20:04 subsystem ->
> ../../../../../../../../../../../class/leds
> -rw-r--r-- 1 root root 4096 Nov 12 20:22 trigger
> > Because userspace needs that information?
> >
> > Say you have raid array, with "error" leds for each drive (your list
> > already contains "hdderr"). Now userland detects problem with hdparm
> > on /dev/sdi. It would like to turn on corresponding LED.
> >
> > How do you propose we do that?
>
> Similarly as in case of USB keyboard.
Not really, I'm afraid. Hard drives have no red LEDs on them (and the
LED would not be visible, anyway) so the "device" symlink in such case
would point to some kind of i2c LED controller.
Eventually we'll need to have two devices for each LED. "Controller
this is on" -- in device symlink and "device this talks about".
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
> > Couldn't we have here multiple variants that would then be chosen based
> > on device tree definition?
>
> It needs to be subsystem specific or something.
> What you say make sense for things based on device
> tree.
>
> The problem hit me on an Intel laptop with several
> USB keyboards.
>
> OK maybe I am stupid for plugging in two USB keyboards,
> but we should definately support it. Input/HID supports it
> well.
Plugging two USB keyboards should be supported.
Can we get some details... kernel version, architecture, maybe
.config, where/how it fails?
On my systems, keyboard leds are prefixed with device name, so I see
no chance for duplicities...
input5::capslock/
input5::numlock/
input5::scrolllock/
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi Jacek,
On 12/11/2018 18.02, Jacek Anaszewski wrote:
>>> Support for RGB LEDs, or other variations of LED synchronization
>>> have been approached several times, but without satisfying result
>>> so far.
>>>
>>> Generally the problem boils down to the issue of how triggers
>>> should handle multiple synchronized LED class devices in a backwards
>>> compatible way with monochrome LEDs.
>>>
>>> At some point the HSV [0] approach was proposed, but there was a problem
>>> with getting uniform colors across devices. Especially white.
>>> Certainly a calibration mechanism would be required.
>>>
>>> [0] https://lkml.org/lkml/2017/8/30/423
>>
>> We do not usually use PWM controlled leds so our calibration has been HW
>> engineer tuning the resistors for the leds to get acceptable color for
>> different colors variations.
>>
>> If one wants to have fixed colors for such device then one could use
>> this similar method to define them or/and free form interface to enter
>> RGB values there. Thou with PWM RGB leds you probably want to have more
>> animation there which probably would require some additional support code.
>>
>> One way to do atomic PWM RGB color change with sysfs could be:
>>
>> echo "21 223 242" > color
>>
>> or
>>
>> echo "21 223 242" > rgb
>>
>> or:
>>
>> echo "r:21 g:232 b:242" > color (or something similar)
>>
>> and if there is know registered name then just write it to "color" which
>> would pick registered color rgb values to led instances rgb value.
>>
>> Now for PWM RGB led one could use "brightness" and "rgb" value to
>> calculate actual color with some color space formula (like hsv in [0]).
>>
>> Doing white with RGB LED is a bit hard so usually you want to get RGBW
>> LED (or RGBAW LED) if "real" white is something that is needed. This
>> could then be "rgbw" entry and "color" to pick from fixed set.
>>
>> These presets in device tree for "color" could be considered one way of
>> doing calibration for particular hardware.
>>
>> So in device tree for RGB PWM led it could be like:
>>
>> color-orange {
>> rgb = <249 197 9>
>> }
>>
>> color-warm-white {
>> rgb = <255 253 249>
>> }
>>
>> How would that sound like?
>
> Thank you for the description of your approach.
>
> Predefined DT color definitions make an interesting option. Nonetheless,
> your design assumes that for RGB LEDs max_brightness would have to be
> always 1.
>
> While it would solve the issue, it wouldn't allow to benefit from
> the whole potential of RGB LEDs - think of having adjustable "color
> brightness" (like in HSV color model).
What I tried to describe above was that these could also work with HSV
model also with larger brigtness values too.
Let's say we do following sequence to change from off state to user
configured intensity value:
# Turn off leds
echo 0 > brightness
# Select requested color
echo "orange" > color
# Use configured LED intensity from user configuration
echo 84 > brightness
Driver would now use rgb value <249 197 9> and brightness <84> to
calculate (with HSV solution) real PWM values for the led component
colors. With led controller this is probably easier to get linear
feedback but for generic PWM controller you may want to utilize PWM
curve feature like defined for backlight driver.
When thinking this I instantly see my self with thinking PS4's
sliding/pulsing color animation for orange/blue/white. And controlling
this animation steps manually from user space probably is not the best
idea so like with blinking you would need more accurately timed action
within kernel I suppose (or hardware with the support).
With that idea forward:
# Turning animation sequencer off causes instant changes for values
echo "off" > animation-sequencer
# User 1 second for animation (no effect yet as sequencer is off)
echo 1000 > animation-time-ms (or so)
# Turn off leds (instance change)
echo 0 > brightness
# Select requested color (instant change)
echo "orange" > color
# Change to linear animation sequencer
echo "linear" > animation-sequencer
# Now everything from this point is subject to animation sequencer
# Sequencer remember active state and next state (as seen in sysfs)
# Use configured LED intensity from user configuration (no effect yet)
echo 84 > brightness
# Trigger transition sequence
echo load > animation-sequencer
# This would cause 1 second animation from black to orange with user
intensivity of 84
# Wait for transition to complete and some extra
sleep 4
# Change color to blue with animation
echo "blue" > color
echo load > animation-sequencer
# This would cause driver to change from orange to blue in current
intensivity level during 1 second period
# -- end --
Now that went a bit ahead of time but I believe it demonstrates the
potential for this approach with combined with HSL functionality for future.
> How abut allowing for providing an array of color intensity/brightness
> levels per each color? In the simplest case there could be a single
> level per color, but it should be possible to provide up to 255 levels.
I believe that brightness and color should be separate topics.
We have in our devices option in user interface to configure intesivity
for backlight and in one device also intensivity for status led (this is
the only PWM led we have :)). (I believe this might be currently
implemented without actual led driver and directly use PWM interface)
Even in when reduced intensivity we want the color to be set to
specified value even thou it would not be as bright as full intensivity
would be.
What do you think?
Thanks,
Vesa Jääskeläinen
Hi Vesa,
On 11/13/2018 08:10 AM, Vesa Jääskeläinen wrote:
> Hi Jacek,
>
> On 12/11/2018 18.02, Jacek Anaszewski wrote:
>>>> Support for RGB LEDs, or other variations of LED synchronization
>>>> have been approached several times, but without satisfying result
>>>> so far.
>>>>
>>>> Generally the problem boils down to the issue of how triggers
>>>> should handle multiple synchronized LED class devices in a backwards
>>>> compatible way with monochrome LEDs.
>>>>
>>>> At some point the HSV [0] approach was proposed, but there was a
>>>> problem
>>>> with getting uniform colors across devices. Especially white.
>>>> Certainly a calibration mechanism would be required.
>>>>
>>>> [0] https://lkml.org/lkml/2017/8/30/423
>>>
>>> We do not usually use PWM controlled leds so our calibration has been HW
>>> engineer tuning the resistors for the leds to get acceptable color for
>>> different colors variations.
>>>
>>> If one wants to have fixed colors for such device then one could use
>>> this similar method to define them or/and free form interface to enter
>>> RGB values there. Thou with PWM RGB leds you probably want to have more
>>> animation there which probably would require some additional support
>>> code.
>>>
>>> One way to do atomic PWM RGB color change with sysfs could be:
>>>
>>> echo "21 223 242" > color
>>>
>>> or
>>>
>>> echo "21 223 242" > rgb
>>>
>>> or:
>>>
>>> echo "r:21 g:232 b:242" > color (or something similar)
>>>
>>> and if there is know registered name then just write it to "color" which
>>> would pick registered color rgb values to led instances rgb value.
>>>
>>> Now for PWM RGB led one could use "brightness" and "rgb" value to
>>> calculate actual color with some color space formula (like hsv in [0]).
>>>
>>> Doing white with RGB LED is a bit hard so usually you want to get RGBW
>>> LED (or RGBAW LED) if "real" white is something that is needed. This
>>> could then be "rgbw" entry and "color" to pick from fixed set.
>>>
>>> These presets in device tree for "color" could be considered one way of
>>> doing calibration for particular hardware.
>>>
>>> So in device tree for RGB PWM led it could be like:
>>>
>>> color-orange {
>>> rgb = <249 197 9>
>>> }
>>>
>>> color-warm-white {
>>> rgb = <255 253 249>
>>> }
>>>
>>> How would that sound like?
>>
>> Thank you for the description of your approach.
>>
>> Predefined DT color definitions make an interesting option. Nonetheless,
>> your design assumes that for RGB LEDs max_brightness would have to be
>> always 1.
>>
>> While it would solve the issue, it wouldn't allow to benefit from
>> the whole potential of RGB LEDs - think of having adjustable "color
>> brightness" (like in HSV color model).
>
> What I tried to describe above was that these could also work with HSV
> model also with larger brigtness values too.
>
> Let's say we do following sequence to change from off state to user
> configured intensity value:
>
> # Turn off leds
> echo 0 > brightness
>
> # Select requested color
> echo "orange" > color
>
> # Use configured LED intensity from user configuration
> echo 84 > brightness
>
> Driver would now use rgb value <249 197 9> and brightness <84> to
> calculate (with HSV solution) real PWM values for the led component
> colors. With led controller this is probably easier to get linear
> feedback but for generic PWM controller you may want to utilize PWM
> curve feature like defined for backlight driver.
>
> When thinking this I instantly see my self with thinking PS4's
> sliding/pulsing color animation for orange/blue/white. And controlling
> this animation steps manually from user space probably is not the best
> idea so like with blinking you would need more accurately timed action
> within kernel I suppose (or hardware with the support).
>
> With that idea forward:
>
> # Turning animation sequencer off causes instant changes for values
> echo "off" > animation-sequencer
>
> # User 1 second for animation (no effect yet as sequencer is off)
> echo 1000 > animation-time-ms (or so)
>
> # Turn off leds (instance change)
> echo 0 > brightness
>
> # Select requested color (instant change)
> echo "orange" > color
>
> # Change to linear animation sequencer
> echo "linear" > animation-sequencer
>
> # Now everything from this point is subject to animation sequencer
> # Sequencer remember active state and next state (as seen in sysfs)
>
> # Use configured LED intensity from user configuration (no effect yet)
> echo 84 > brightness
>
> # Trigger transition sequence
> echo load > animation-sequencer
>
> # This would cause 1 second animation from black to orange with user
> intensivity of 84
>
> # Wait for transition to complete and some extra
> sleep 4
>
> # Change color to blue with animation
> echo "blue" > color
> echo load > animation-sequencer
>
> # This would cause driver to change from orange to blue in current
> intensivity level during 1 second period
>
> # -- end --
>
> Now that went a bit ahead of time but I believe it demonstrates the
> potential for this approach with combined with HSL functionality for
> future.
We have just contributed pattern trigger - it could be adjusted
to RGB LED purposes too.
See drivers/leds/trigger/ledtrig-pattern.c and
Documentation/ABI/testing/sysfs-class-led-trigger-pattern in
Linus' tree.
>> How abut allowing for providing an array of color intensity/brightness
>> levels per each color? In the simplest case there could be a single
>> level per color, but it should be possible to provide up to 255 levels.
>
> I believe that brightness and color should be separate topics.
I didn't make myself clear enough - I like the approach with the
color sysfs file. By the "color brightness" I mean color arrays,
that would have to be defined per each color. Elements of such an
array would make the "color brightness/lightness" range.
> We have in our devices option in user interface to configure intesivity
> for backlight and in one device also intensivity for status led (this is
> the only PWM led we have :)). (I believe this might be currently
> implemented without actual led driver and directly use PWM interface)
>
> Even in when reduced intensivity we want the color to be set to
> specified value even thou it would not be as bright as full intensivity
> would be.
>
> What do you think?
I think that we've just agreed the preliminary requirements for
a new RGB LED class interface.
--
Best regards,
Jacek Anaszewski
On 11/12/2018 10:23 PM, Linus Walleij wrote:
> On Sun, Nov 11, 2018 at 1:03 PM Pavel Machek <[email protected]> wrote:
>
>>> -"devicename:colour:function"
>>> +"colour:function"
>>
>> I don't think we want to do it in all cases.
>>
>> So, on my cellphone seeing lp5523:green:led is indeed not useful.
>>
>> But on notebook with usb keyboard attached, you need to keep the
>> devicename to be able to distinguish capslock on internal keyboard and
>> capslock on first USB keyboard and capslock on second USB keyboard.
>
> I agree with Pavel.
>
> I ran into this when connecting two identical keyboards to the
> same machine. The driver worked fine up until it tries
> to create two sysfs entries with the same name for capslock.
> BOOM!
What kernel version did you use? LED core has had a protection
against name clash since the commit:
commit a96aa64cb5723d941de879a9cd1fea025d6acb1b
Author: Ricardo Ribalda Delgado <[email protected]>
Date: Mon Mar 30 10:45:59 2015 -0700
leds/led-class: Handle LEDs with the same name
The current code expected that every LED had an unique name. This is a
legit expectation when the device tree can no be modified or extended.
But with device tree overlays this requirement can be easily broken.
This patch finds out if the name is already in use and adds the suffix
_1, _2... if not.
Signed-off-by: Ricardo Ribalda Delgado <[email protected]>
Reported-by: Geert Uytterhoeven <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
> In this case I suggest "serialnumber:color:capslock" and
> similar.
>
> The important point is the string must be unique for each
> plugged device.
--
Best regards,
Jacek Anaszewski
On 11/12/2018 07:27 PM, Rob Herring wrote:
> On Tue, Nov 06, 2018 at 11:07:12PM +0100, Jacek Anaszewski wrote:
>> Introduce dedicated properties for conveying information about
>> LED function and color. Mark old "label" property as deprecated.
>>
>> Signed-off-by: Jacek Anaszewski <[email protected]>
>> Cc: Baolin Wang <[email protected]>
>> Cc: Daniel Mack <[email protected]>
>> Cc: Dan Murphy <[email protected]>
>> Cc: Linus Walleij <[email protected]>
>> Cc: Oleh Kravchenko <[email protected]>
>> Cc: Sakari Ailus <[email protected]>
>> Cc: Simon Shields <[email protected]>
>> Cc: Xiaotong Lu <[email protected]>
>> ---
>> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
>> index aa13998..3efc826 100644
>> --- a/Documentation/devicetree/bindings/leds/common.txt
>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
>> have to be tightly coupled with the LED device binding. They are represented
>> by child nodes of the parent LED device binding.
>>
>> +
>> Optional properties for child nodes:
>> - led-sources : List of device current outputs the LED is connected to. The
>> outputs are identified by the numbers that must be defined
>> in the LED device binding documentation.
>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
>> + from the header include/dt-bindings/leds/functions.h.
>> + If there is no matching LED_FUNCTION available, add a new one.
>> +- color : Color of the LED.
>> - label : The label for this LED. If omitted, the label is taken from the node
>> name (excluding the unit address). It has to uniquely identify
>> a device, i.e. no other LED class device can be assigned the same
>> - label.
>> + label. This property is deprecated - use 'function' and 'color'
>> + properties instead.
>
> I don't know if I'd go as far a deprecating.
>
> One thing to consider is how we handle multiple of the same function? Do
> we allow an index on function names? What if an index isn't meaningful
> and we need "front" vs. "rear" for example? Maybe label is still needed
> there.
I believe that 'label' property with its old semantics must be preserved
for backwards compatibility - it so far has been used inconsistently for
conveying variations of devicename:color:function sections. If provided,
then it's been taken as-is for LED class device name, or concatenated
with the devicename hard-coded in the driver.
Regarding the differentiation between the LEDs with functions of
same kind - OK, I agree, we will need another section.
What seems to fits the best is the reference to the device it is
logically associated with.
The question is whether the devicename should be provided in DT
literally, or by phandle, and then retrieved in runtime, basing on the
sysfs entry, like in case of input-leds bridge which for USB keyboard
creates LEDs named e.g.:
input5::capslock
input5::numlock
input5::scrolllock
Probably we will have to allow for some flexibility in this regard,
to allow for providing devicename literally like "rear", "front",
or like above input case.
--
Best regards,
Jacek Anaszewski
On 11/12/2018 11:06 PM, Pavel Machek wrote:
> On Mon 2018-11-12 21:11:32, Jacek Anaszewski wrote:
>> On 11/12/2018 08:05 PM, Pavel Machek wrote:
>>> Hi!
>>>
>>>>>>> My system looks like this:
>>>>>>>
>>>>>>> input16::capslock tpacpi::bay_active tpacpi::standby
>>>>>>> input16::numlock tpacpi::dock_active tpacpi::thinklight
>>>>>>> input16::scrolllock tpacpi::dock_batt tpacpi::thinkvantage
>>>>>>> input5::capslock tpacpi::dock_status1 tpacpi::unknown_led
>>>>>>> input5::numlock tpacpi::dock_status2 tpacpi::unknown_led2
>>>>>>> input5::scrolllock tpacpi:green:batt tpacpi::unknown_led3
>>>
>>>>> But it is not just for backwards compatibility. See my examples above,
>>>>> it is needed to tell which device the LED is asociated with, and it is
>>>>> absolutely required for USB devices (for example).
>>>>
>>>> For USB devices there is already ledtrig-usbport available, which
>>>> provides sysfs interface for defining and reading the usb ports,
>>>> the status of which the LED indicates. Since the USB devices can be
>>>> attached/removed dynamically, it would be impossible to reflect
>>>> the associations in the LED class device name.
>>>
>>> I'm not talking USB activity. I'm talking USB devices with LEDs on
>>> them, like for example keyboards.
>>>
>>> Please take a look at example above. input16::numlock ;
>>> input5::numlock . You absolutely need device part.
>>
>> It would be redundant since there is "device" symbolic link
>> created in given LED class device sysfs directory, pointing to the
>> corresponding input device directory, like in case of my USB
>> keyboard:
>
> You are right I forgot about the device symlink, and it partly helps
> with the USB keyboard case...
>
> But you still need the device part. Sysfs will not like two
> directories named "::numlock".
LED core has a protection against that. See my reply to Linus.
>
>> #/sys/class/leds/input5::scrolllock$ ls -l
>> total 0
>> -rw-r--r-- 1 root root 4096 Nov 12 20:22 brightness
>> lrwxrwxrwx 1 root root 0 Nov 12 20:22 device -> ../../input5
>> -r--r--r-- 1 root root 4096 Nov 12 20:22 max_brightness
>> drwxr-xr-x 2 root root 0 Nov 12 20:22 power
>> lrwxrwxrwx 1 root root 0 Nov 12 20:04 subsystem ->
>> ../../../../../../../../../../../class/leds
>> -rw-r--r-- 1 root root 4096 Nov 12 20:22 trigger
>
>>> Because userspace needs that information?
>>>
>>> Say you have raid array, with "error" leds for each drive (your list
>>> already contains "hdderr"). Now userland detects problem with hdparm
>>> on /dev/sdi. It would like to turn on corresponding LED.
>>>
>>> How do you propose we do that?
>>
>> Similarly as in case of USB keyboard.
>
> Not really, I'm afraid. Hard drives have no red LEDs on them (and the
> LED would not be visible, anyway) so the "device" symlink in such case
> would point to some kind of i2c LED controller.
>
> Eventually we'll need to have two devices for each LED. "Controller
> this is on" -- in device symlink and "device this talks about".
After thinking it over I agree - we will still need devicename part
Please refer to my reply to Rob.
--
Best regards,
Jacek Anaszewski
Hi Pavel,
On Mon, Nov 12, 2018 at 11:07 PM Pavel Machek <[email protected]> wrote:
> Not really, I'm afraid. Hard drives have no red LEDs on them (and the
> LED would not be visible, anyway) so the "device" symlink in such case
> would point to some kind of i2c LED controller.
I've seen hard drives with LEDs on the PCB.
External USB enclosures with hard drives typically have LEDs, too.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Tue 2018-11-13 22:38:49, Geert Uytterhoeven wrote:
> Hi Pavel,
>
> On Mon, Nov 12, 2018 at 11:07 PM Pavel Machek <[email protected]> wrote:
> > Not really, I'm afraid. Hard drives have no red LEDs on them (and the
> > LED would not be visible, anyway) so the "device" symlink in such case
> > would point to some kind of i2c LED controller.
>
> I've seen hard drives with LEDs on the PCB.
Me too.
> External USB enclosures with hard drives typically have LEDs, too.
Yes, but typically neither are OS controlled.
I'm thinking home NAS system; it may have per-disk LEDs and they'll
probably be on some kind of dedicated LED controller.
Anyway, my point is that "device that controls this LED" is often
different from "device this LED is about".
Regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue, Nov 13, 2018 at 8:55 PM Jacek Anaszewski
<[email protected]> wrote:
> LED core has had a protection
> against name clash since the commit:
>
> commit a96aa64cb5723d941de879a9cd1fea025d6acb1b
> Author: Ricardo Ribalda Delgado <[email protected]>
> Date: Mon Mar 30 10:45:59 2015 -0700
>
> leds/led-class: Handle LEDs with the same name
Oh neat!
I guess the sysfs clashes I have seen can have been other
stuff then, but it was a while back, I don't think it was so far
back as this patch.
Yours,
Linus Walleij
On Tue, Nov 6, 2018 at 11:07 PM Jacek Anaszewski
<[email protected]> wrote:
> +#define LED_FUNCTION_DISK "disk"
I recently added triggers for "disk-read" and "disk-write".
This was because the D-Link DNS-313 does have dedicated
LEDs for each usecase, and so does DIR-685.
So I think you may need
LED_FUNCTION_DISK_READ "disk-read"
and
LED_FUNCTION_DISK_WRITE "disk-write"
to cover these cases.
Yours,
Linus Walleij
On 11/13/2018 09:57 PM, Jacek Anaszewski wrote:
> On 11/12/2018 07:27 PM, Rob Herring wrote:
>> On Tue, Nov 06, 2018 at 11:07:12PM +0100, Jacek Anaszewski wrote:
>>> Introduce dedicated properties for conveying information about
>>> LED function and color. Mark old "label" property as deprecated.
>>>
>>> Signed-off-by: Jacek Anaszewski <[email protected]>
>>> Cc: Baolin Wang <[email protected]>
>>> Cc: Daniel Mack <[email protected]>
>>> Cc: Dan Murphy <[email protected]>
>>> Cc: Linus Walleij <[email protected]>
>>> Cc: Oleh Kravchenko <[email protected]>
>>> Cc: Sakari Ailus <[email protected]>
>>> Cc: Simon Shields <[email protected]>
>>> Cc: Xiaotong Lu <[email protected]>
>>> ---
>>> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
>>> 1 file changed, 44 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
>>> index aa13998..3efc826 100644
>>> --- a/Documentation/devicetree/bindings/leds/common.txt
>>> +++ b/Documentation/devicetree/bindings/leds/common.txt
>>> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
>>> have to be tightly coupled with the LED device binding. They are represented
>>> by child nodes of the parent LED device binding.
>>>
>>> +
>>> Optional properties for child nodes:
>>> - led-sources : List of device current outputs the LED is connected to. The
>>> outputs are identified by the numbers that must be defined
>>> in the LED device binding documentation.
>>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
>>> + from the header include/dt-bindings/leds/functions.h.
>>> + If there is no matching LED_FUNCTION available, add a new one.
>>> +- color : Color of the LED.
>>> - label : The label for this LED. If omitted, the label is taken from the node
>>> name (excluding the unit address). It has to uniquely identify
>>> a device, i.e. no other LED class device can be assigned the same
>>> - label.
>>> + label. This property is deprecated - use 'function' and 'color'
>>> + properties instead.
>>
>> I don't know if I'd go as far a deprecating.
>>
>> One thing to consider is how we handle multiple of the same function? Do
>> we allow an index on function names? What if an index isn't meaningful
>> and we need "front" vs. "rear" for example? Maybe label is still needed
>> there.
>
> I believe that 'label' property with its old semantics must be preserved
> for backwards compatibility - it so far has been used inconsistently for
> conveying variations of devicename:color:function sections. If provided,
> then it's been taken as-is for LED class device name, or concatenated
> with the devicename hard-coded in the driver.
>
> Regarding the differentiation between the LEDs with functions of
> same kind - OK, I agree, we will need another section.
>
> What seems to fits the best is the reference to the device it is
> logically associated with.
>
> The question is whether the devicename should be provided in DT
> literally, or by phandle, and then retrieved in runtime, basing on the
> sysfs entry, like in case of input-leds bridge which for USB keyboard
> creates LEDs named e.g.:
>
> input5::capslock
> input5::numlock
> input5::scrolllock
>
> Probably we will have to allow for some flexibility in this regard,
> to allow for providing devicename literally like "rear", "front",
> or like above input case.
I must admit I have a dilemma with this devicename part.
Thinking more of it - the semantics of that section of LED
class device name needs to be precise. Currently there seem
to be two types of device names considered:
1) descriptive name like in case of flash -
front-camera::flash, rear-camera::flash, which would allow
for providing arbitrary devicenames, i.e. it would not improve
LED naming too much, which was the aim of this patch set
2) name representing hardware relation or user-defined relation between
some device and the LED class device, like in above keyboard
LED case:
- input5::numlock
or for hard disk:
- sda1::hdderr,
In the hdderr case Pavel mentioned the arrangement where the LED
is not a part of the hard disk, so the relation would have to be
defined in DT.
For the flash case the devicename part would be matching /dev/videoN
device.
I'm in favour of the option 2) since it seems to be more precise.
In this case we would need a mechanism for asynchronous LED class
device registration which would register a LED only after the
associated device has been probed and its name is known.
The mechanism would be a simpler form of
drivers/media/v4l2-core/v4l2-async.c.
In the LED DT node we would need a property holding a phandle
to the associated device. Then, in the runtime the related device
would call led_register_associated_device(struct device_node*,
struct device*) which would in turn match the device_node with
the phandle assigned to the property in the LED DT node. Having
the struct device of the associated device we could retrieve
device node name from dev->kobj.
We would also probably need different DT properties for different
types of devices, since e.g. for network case the network interface
name would fit better for the LED name, than the phy name,
and we would need to know what type of device name we're going
to look for.
Pavel gave following examples:
eth0:green:link
adsl0:green:link
adsl0:red:error
So we would have e.g.:
associated-vl42-device = <&camera1>;
associated-network-device = <&phy1>;
associated-block-device = <&phy1>;
Currently I have no idea how to obtain related network interface
name by struct device related to the network device phy, but
I believe it is possible.
I'm open to suggestions on what direction it should go.
I only wonder if such a solution wouldn't be an over-engineering.
Other ideas are welcome.
--
Best regards,
Jacek Anaszewski
On Tue, Nov 27, 2018 at 2:38 PM Jacek Anaszewski
<[email protected]> wrote:
>
> On 11/13/2018 09:57 PM, Jacek Anaszewski wrote:
> > On 11/12/2018 07:27 PM, Rob Herring wrote:
> >> On Tue, Nov 06, 2018 at 11:07:12PM +0100, Jacek Anaszewski wrote:
> >>> Introduce dedicated properties for conveying information about
> >>> LED function and color. Mark old "label" property as deprecated.
> >>>
> >>> Signed-off-by: Jacek Anaszewski <[email protected]>
> >>> Cc: Baolin Wang <[email protected]>
> >>> Cc: Daniel Mack <[email protected]>
> >>> Cc: Dan Murphy <[email protected]>
> >>> Cc: Linus Walleij <[email protected]>
> >>> Cc: Oleh Kravchenko <[email protected]>
> >>> Cc: Sakari Ailus <[email protected]>
> >>> Cc: Simon Shields <[email protected]>
> >>> Cc: Xiaotong Lu <[email protected]>
> >>> ---
> >>> Documentation/devicetree/bindings/leds/common.txt | 52 +++++++++++++++++++----
> >>> 1 file changed, 44 insertions(+), 8 deletions(-)
> >>>
> >>> diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
> >>> index aa13998..3efc826 100644
> >>> --- a/Documentation/devicetree/bindings/leds/common.txt
> >>> +++ b/Documentation/devicetree/bindings/leds/common.txt
> >>> @@ -10,14 +10,20 @@ can influence the way of the LED device initialization, the LED components
> >>> have to be tightly coupled with the LED device binding. They are represented
> >>> by child nodes of the parent LED device binding.
> >>>
> >>> +
> >>> Optional properties for child nodes:
> >>> - led-sources : List of device current outputs the LED is connected to. The
> >>> outputs are identified by the numbers that must be defined
> >>> in the LED device binding documentation.
> >>> +- function: LED functon. Use one of the LED_FUNCTION_* prefixed definitions
> >>> + from the header include/dt-bindings/leds/functions.h.
> >>> + If there is no matching LED_FUNCTION available, add a new one.
> >>> +- color : Color of the LED.
> >>> - label : The label for this LED. If omitted, the label is taken from the node
> >>> name (excluding the unit address). It has to uniquely identify
> >>> a device, i.e. no other LED class device can be assigned the same
> >>> - label.
> >>> + label. This property is deprecated - use 'function' and 'color'
> >>> + properties instead.
> >>
> >> I don't know if I'd go as far a deprecating.
> >>
> >> One thing to consider is how we handle multiple of the same function? Do
> >> we allow an index on function names? What if an index isn't meaningful
> >> and we need "front" vs. "rear" for example? Maybe label is still needed
> >> there.
> >
> > I believe that 'label' property with its old semantics must be preserved
> > for backwards compatibility - it so far has been used inconsistently for
> > conveying variations of devicename:color:function sections. If provided,
> > then it's been taken as-is for LED class device name, or concatenated
> > with the devicename hard-coded in the driver.
> >
> > Regarding the differentiation between the LEDs with functions of
> > same kind - OK, I agree, we will need another section.
> >
> > What seems to fits the best is the reference to the device it is
> > logically associated with.
> >
> > The question is whether the devicename should be provided in DT
> > literally, or by phandle, and then retrieved in runtime, basing on the
> > sysfs entry, like in case of input-leds bridge which for USB keyboard
> > creates LEDs named e.g.:
> >
> > input5::capslock
> > input5::numlock
> > input5::scrolllock
> >
> > Probably we will have to allow for some flexibility in this regard,
> > to allow for providing devicename literally like "rear", "front",
> > or like above input case.
>
> I must admit I have a dilemma with this devicename part.
> Thinking more of it - the semantics of that section of LED
> class device name needs to be precise. Currently there seem
> to be two types of device names considered:
>
> 1) descriptive name like in case of flash -
> front-camera::flash, rear-camera::flash, which would allow
> for providing arbitrary devicenames, i.e. it would not improve
> LED naming too much, which was the aim of this patch set
> 2) name representing hardware relation or user-defined relation between
> some device and the LED class device, like in above keyboard
> LED case:
>
> - input5::numlock
>
> or for hard disk:
>
> - sda1::hdderr,
>
> In the hdderr case Pavel mentioned the arrangement where the LED
> is not a part of the hard disk, so the relation would have to be
> defined in DT.
> For the flash case the devicename part would be matching /dev/videoN
> device.
>
> I'm in favour of the option 2) since it seems to be more precise.
> In this case we would need a mechanism for asynchronous LED class
> device registration which would register a LED only after the
> associated device has been probed and its name is known.
> The mechanism would be a simpler form of
> drivers/media/v4l2-core/v4l2-async.c.
>
> In the LED DT node we would need a property holding a phandle
> to the associated device. Then, in the runtime the related device
> would call led_register_associated_device(struct device_node*,
> struct device*) which would in turn match the device_node with
> the phandle assigned to the property in the LED DT node. Having
> the struct device of the associated device we could retrieve
> device node name from dev->kobj.
>
> We would also probably need different DT properties for different
> types of devices, since e.g. for network case the network interface
> name would fit better for the LED name, than the phy name,
> and we would need to know what type of device name we're going
> to look for.
>
> Pavel gave following examples:
>
> eth0:green:link
> adsl0:green:link
> adsl0:red:error
>
> So we would have e.g.:
>
> associated-vl42-device = <&camera1>;
> associated-network-device = <&phy1>;
> associated-block-device = <&phy1>;
Variable property names are kind of a pain to parse.
Perhaps when LEDs are associated with a device, we shouldn't care
within the context of the LED subsystem what the name is. The
association is more important and if you have that exposed, then you
don't really need to care what the name is. You still have to deal
with a device with more than 1 LED, but that becomes a problem local
to that device.
What I'm getting at is following a more standard binding pattern of
providers and consumers like we have for gpios, clocks, etc. So we'd
have something like this:
ethernet {
...
leds = <&green_led>, <&red_led>;
led-names = "link", "err";
};
We can still support defining LED names as we've done, but we don't
have to come up with some elaborate naming convention that covers
every single case.
Rob
Hi!
> > Pavel gave following examples:
> >
> > eth0:green:link
> > adsl0:green:link
> > adsl0:red:error
> >
> > So we would have e.g.:
> >
> > associated-vl42-device = <&camera1>;
> > associated-network-device = <&phy1>;
> > associated-block-device = <&phy1>;
>
> Variable property names are kind of a pain to parse.
Ok, would it be enough to have associated-device = <&whatever>?
> Perhaps when LEDs are associated with a device, we shouldn't care
> within the context of the LED subsystem what the name is. The
> association is more important and if you have that exposed, then you
> don't really need to care what the name is. You still have to deal
> with a device with more than 1 LED, but that becomes a problem local
> to that device.
>
> What I'm getting at is following a more standard binding pattern of
> providers and consumers like we have for gpios, clocks, etc. So we'd
> have something like this:
>
> ethernet {
> ...
> leds = <&green_led>, <&red_led>;
> led-names = "link", "err";
> };
Basically every single device could have a LED associated with it
("activity"). Would doing it like this mean we'd have to modify every
single driver to parse leds / led-names properties?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Fri, Nov 30, 2018 at 3:08 PM Pavel Machek <[email protected]> wrote:
>
> Hi!
>
> > > Pavel gave following examples:
> > >
> > > eth0:green:link
> > > adsl0:green:link
> > > adsl0:red:error
> > >
> > > So we would have e.g.:
> > >
> > > associated-vl42-device = <&camera1>;
> > > associated-network-device = <&phy1>;
> > > associated-block-device = <&phy1>;
> >
> > Variable property names are kind of a pain to parse.
>
> Ok, would it be enough to have associated-device = <&whatever>?
Yeah, but I though you needed the device type name in there.
> > Perhaps when LEDs are associated with a device, we shouldn't care
> > within the context of the LED subsystem what the name is. The
> > association is more important and if you have that exposed, then you
> > don't really need to care what the name is. You still have to deal
> > with a device with more than 1 LED, but that becomes a problem local
> > to that device.
> >
> > What I'm getting at is following a more standard binding pattern of
> > providers and consumers like we have for gpios, clocks, etc. So we'd
> > have something like this:
> >
> > ethernet {
> > ...
> > leds = <&green_led>, <&red_led>;
> > led-names = "link", "err";
> > };
>
> Basically every single device could have a LED associated with it
> ("activity"). Would doing it like this mean we'd have to modify every
> single driver to parse leds / led-names properties?
Normally, that's how properties like this would work. A driver is also
what knows how the leds should function. A driver can retrieve the led
and associate it with the 'foo-bar' function. The 'foo-bar' function
then doesn't have to be defined in DT nor exposed to userspace. It
wouldn't even have to be driver specific. The driver's subsystem could
handle it all if the led functions are standardized. Though then you'd
be back to needing standard names for 'led-names', but that's no worse
that trigger names. This model would also allow getting rid of
'linux,default-trigger' properties in a lot of cases which wouldn't be
a bad thing.
However, having drivers handle this is not required. You can iterate
thru the tree for nodes with 'leds' and find the node which has a
phandle to the led node you care about. Sure, it's not that efficient,
but it does work and it's only done once. Basically, as long as the
linkage is there, we can make it work. I think using
'associated-device' might work better for the current implementation
of Linux LED support, but leds/led-names would be more inline with
other DT bindings. The current Linux implementation shouldn't dictate
the binding design.
Rob
On 11/30/2018 11:19 PM, Rob Herring wrote:
> On Fri, Nov 30, 2018 at 3:08 PM Pavel Machek <[email protected]> wrote:
>>
>> Hi!
>>
>>>> Pavel gave following examples:
>>>>
>>>> eth0:green:link
>>>> adsl0:green:link
>>>> adsl0:red:error
>>>>
>>>> So we would have e.g.:
>>>>
>>>> associated-vl42-device = <&camera1>;
>>>> associated-network-device = <&phy1>;
>>>> associated-block-device = <&phy1>;
>>>
>>> Variable property names are kind of a pain to parse.
>>
>> Ok, would it be enough to have associated-device = <&whatever>?
>
> Yeah, but I though you needed the device type name in there.
>
>>> Perhaps when LEDs are associated with a device, we shouldn't care
>>> within the context of the LED subsystem what the name is. The
>>> association is more important and if you have that exposed, then you
>>> don't really need to care what the name is. You still have to deal
>>> with a device with more than 1 LED, but that becomes a problem local
>>> to that device.
>>>
>>> What I'm getting at is following a more standard binding pattern of
>>> providers and consumers like we have for gpios, clocks, etc. So we'd
>>> have something like this:
>>>
>>> ethernet {
>>> ...
>>> leds = <&green_led>, <&red_led>;
>>> led-names = "link", "err";
>>> };
>>
>> Basically every single device could have a LED associated with it
>> ("activity"). Would doing it like this mean we'd have to modify every
>> single driver to parse leds / led-names properties?
>
> Normally, that's how properties like this would work. A driver is also
> what knows how the leds should function.
This is not true in case of associations where LED controller is
an independent device, as in Pavel's example [0].
> A driver can retrieve the led
> and associate it with the 'foo-bar' function. The 'foo-bar' function
> then doesn't have to be defined in DT nor exposed to userspace. It
> wouldn't even have to be driver specific. The driver's subsystem could
> handle it all if the led functions are standardized. Though then you'd
> be back to needing standard names for 'led-names', but that's no worse
> that trigger names. This model would also allow getting rid of
> 'linux,default-trigger' properties in a lot of cases which wouldn't be
> a bad thing.
>
> However, having drivers handle this is not required. You can iterate
> thru the tree for nodes with 'leds' and find the node which has a
> phandle to the led node you care about.
This way of discovering associations between devices and LEDs
would be more reliable than by devicename part of LED class device
as discussed previously.
However, I've just tried to verify how it works, but
I can't find the way to get the of_node phandle from sysfs.
The "of_node" link in per-device dirs in /sys/devices point
to the directories containing DT properties of the node, but
I see no way to obtain the node phandle.
> Sure, it's not that efficient,
> but it does work and it's only done once. Basically, as long as the
> linkage is there, we can make it work. I think using
> 'associated-device' might work better for the current implementation
> of Linux LED support, but leds/led-names would be more inline with
> other DT bindings. The current Linux implementation shouldn't dictate
> the binding design.
[0] https://lkml.org/lkml/2018/11/13/103
--
Best regards,
Jacek Anaszewski
On Sat, Dec 1, 2018 at 3:17 PM Jacek Anaszewski
<[email protected]> wrote:
>
> On 11/30/2018 11:19 PM, Rob Herring wrote:
> > On Fri, Nov 30, 2018 at 3:08 PM Pavel Machek <[email protected]> wrote:
> >>
> >> Hi!
> >>
> >>>> Pavel gave following examples:
> >>>>
> >>>> eth0:green:link
> >>>> adsl0:green:link
> >>>> adsl0:red:error
> >>>>
> >>>> So we would have e.g.:
> >>>>
> >>>> associated-vl42-device = <&camera1>;
> >>>> associated-network-device = <&phy1>;
> >>>> associated-block-device = <&phy1>;
> >>>
> >>> Variable property names are kind of a pain to parse.
> >>
> >> Ok, would it be enough to have associated-device = <&whatever>?
> >
> > Yeah, but I though you needed the device type name in there.
> >
> >>> Perhaps when LEDs are associated with a device, we shouldn't care
> >>> within the context of the LED subsystem what the name is. The
> >>> association is more important and if you have that exposed, then you
> >>> don't really need to care what the name is. You still have to deal
> >>> with a device with more than 1 LED, but that becomes a problem local
> >>> to that device.
> >>>
> >>> What I'm getting at is following a more standard binding pattern of
> >>> providers and consumers like we have for gpios, clocks, etc. So we'd
> >>> have something like this:
> >>>
> >>> ethernet {
> >>> ...
> >>> leds = <&green_led>, <&red_led>;
> >>> led-names = "link", "err";
> >>> };
> >>
> >> Basically every single device could have a LED associated with it
> >> ("activity"). Would doing it like this mean we'd have to modify every
> >> single driver to parse leds / led-names properties?
> >
> > Normally, that's how properties like this would work. A driver is also
> > what knows how the leds should function.
>
> This is not true in case of associations where LED controller is
> an independent device, as in Pavel's example [0].
I'm not really following how the HDD example is different. The parent
of an LED would be the controller. The link to the led node would be
in the disk controller node. Though maybe if things get complicated
enough, we'd want to describe the drives or drive bays in DT.
> > A driver can retrieve the led
> > and associate it with the 'foo-bar' function. The 'foo-bar' function
> > then doesn't have to be defined in DT nor exposed to userspace. It
> > wouldn't even have to be driver specific. The driver's subsystem could
> > handle it all if the led functions are standardized. Though then you'd
> > be back to needing standard names for 'led-names', but that's no worse
> > that trigger names. This model would also allow getting rid of
> > 'linux,default-trigger' properties in a lot of cases which wouldn't be
> > a bad thing.
> >
> > However, having drivers handle this is not required. You can iterate
> > thru the tree for nodes with 'leds' and find the node which has a
> > phandle to the led node you care about.
>
> This way of discovering associations between devices and LEDs
> would be more reliable than by devicename part of LED class device
> as discussed previously.
>
> However, I've just tried to verify how it works, but
> I can't find the way to get the of_node phandle from sysfs.
>
> The "of_node" link in per-device dirs in /sys/devices point
> to the directories containing DT properties of the node, but
> I see no way to obtain the node phandle.
You probably don't want to be doing this in userspace. It's possible,
but you've got to read the 'leds' property to get the phandle and then
walk the tree to find the node with the matching phandle property
value (i.e. reimplement what the kernel does). You'd probably would
instead want to define a LED specific symlink sysfs attr either in the
associated device to the led device or vice versa.
Rob
Hi!
> > >> Basically every single device could have a LED associated with it
> > >> ("activity"). Would doing it like this mean we'd have to modify every
> > >> single driver to parse leds / led-names properties?
> > >
> > > Normally, that's how properties like this would work. A driver is also
> > > what knows how the leds should function.
> >
> > This is not true in case of associations where LED controller is
> > an independent device, as in Pavel's example [0].
>
> I'm not really following how the HDD example is different. The parent
> of an LED would be the controller. The link to the led node would be
> in the disk controller node. Though maybe if things get complicated
> enough, we'd want to describe the drives or drive bays in DT.
We were talking case where the LED is on GPIO somewhere. And yes,
drive bays would be similar.
And.. often you have a single LED for multiple harddrives, too. Fun
:-).
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
> > We would also probably need different DT properties for different
> > types of devices, since e.g. for network case the network interface
> > name would fit better for the LED name, than the phy name,
> > and we would need to know what type of device name we're going
> > to look for.
> >
> > Pavel gave following examples:
> >
> > eth0:green:link
> > adsl0:green:link
> > adsl0:red:error
> >
> > So we would have e.g.:
> >
> > associated-vl42-device = <&camera1>;
> > associated-network-device = <&phy1>;
> > associated-block-device = <&phy1>;
>
> Variable property names are kind of a pain to parse.
>
> Perhaps when LEDs are associated with a device, we shouldn't care
> within the context of the LED subsystem what the name is. The
> association is more important and if you have that exposed, then you
> don't really need to care what the name is. You still have to deal
> with a device with more than 1 LED, but that becomes a problem local
> to that device.
>
> What I'm getting at is following a more standard binding pattern of
> providers and consumers like we have for gpios, clocks, etc. So we'd
> have something like this:
>
> ethernet {
> ...
> leds = <&green_led>, <&red_led>;
> led-names = "link", "err";
> };
>
> We can still support defining LED names as we've done, but we don't
> have to come up with some elaborate naming convention that covers
> every single case.
I see that it would be more consistent with how gpios work, but I'm
afraid this does not fit LEDs properly.
With power LED, you want to be able to say "this is just on". Some
poeple like heartbeat, and have LED for that. There may be LED for
"disk activity", meaning activity on any harddrive. And there may be
activity LED for specific disk.
Only in the last case it would be suitable to have LED reference as a
child of an device...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Wed, Dec 12, 2018 at 3:59 AM Pavel Machek <[email protected]> wrote:
>
> Hi!
>
> > > We would also probably need different DT properties for different
> > > types of devices, since e.g. for network case the network interface
> > > name would fit better for the LED name, than the phy name,
> > > and we would need to know what type of device name we're going
> > > to look for.
> > >
> > > Pavel gave following examples:
> > >
> > > eth0:green:link
> > > adsl0:green:link
> > > adsl0:red:error
> > >
> > > So we would have e.g.:
> > >
> > > associated-vl42-device = <&camera1>;
> > > associated-network-device = <&phy1>;
> > > associated-block-device = <&phy1>;
> >
> > Variable property names are kind of a pain to parse.
> >
> > Perhaps when LEDs are associated with a device, we shouldn't care
> > within the context of the LED subsystem what the name is. The
> > association is more important and if you have that exposed, then you
> > don't really need to care what the name is. You still have to deal
> > with a device with more than 1 LED, but that becomes a problem local
> > to that device.
> >
> > What I'm getting at is following a more standard binding pattern of
> > providers and consumers like we have for gpios, clocks, etc. So we'd
> > have something like this:
> >
> > ethernet {
> > ...
> > leds = <&green_led>, <&red_led>;
> > led-names = "link", "err";
> > };
> >
> > We can still support defining LED names as we've done, but we don't
> > have to come up with some elaborate naming convention that covers
> > every single case.
>
> I see that it would be more consistent with how gpios work, but I'm
> afraid this does not fit LEDs properly.
>
> With power LED, you want to be able to say "this is just on". Some
> poeple like heartbeat, and have LED for that. There may be LED for
> "disk activity", meaning activity on any harddrive. And there may be
> activity LED for specific disk.
>
> Only in the last case it would be suitable to have LED reference as a
> child of an device...
Right. For all the other cases, why do you need any link with a
device? What we have today is sufficient and can continue to be
supported. A link to a device is only used if the led is associated
with a particular device.
Rob
On Wed 2018-12-12 07:56:20, Rob Herring wrote:
> On Wed, Dec 12, 2018 at 3:59 AM Pavel Machek <[email protected]> wrote:
> >
> > Hi!
> >
> > > > We would also probably need different DT properties for different
> > > > types of devices, since e.g. for network case the network interface
> > > > name would fit better for the LED name, than the phy name,
> > > > and we would need to know what type of device name we're going
> > > > to look for.
> > > >
> > > > Pavel gave following examples:
> > > >
> > > > eth0:green:link
> > > > adsl0:green:link
> > > > adsl0:red:error
> > > >
> > > > So we would have e.g.:
> > > >
> > > > associated-vl42-device = <&camera1>;
> > > > associated-network-device = <&phy1>;
> > > > associated-block-device = <&phy1>;
> > >
> > > Variable property names are kind of a pain to parse.
> > >
> > > Perhaps when LEDs are associated with a device, we shouldn't care
> > > within the context of the LED subsystem what the name is. The
> > > association is more important and if you have that exposed, then you
> > > don't really need to care what the name is. You still have to deal
> > > with a device with more than 1 LED, but that becomes a problem local
> > > to that device.
> > >
> > > What I'm getting at is following a more standard binding pattern of
> > > providers and consumers like we have for gpios, clocks, etc. So we'd
> > > have something like this:
> > >
> > > ethernet {
> > > ...
> > > leds = <&green_led>, <&red_led>;
> > > led-names = "link", "err";
> > > };
> > >
> > > We can still support defining LED names as we've done, but we don't
> > > have to come up with some elaborate naming convention that covers
> > > every single case.
> >
> > I see that it would be more consistent with how gpios work, but I'm
> > afraid this does not fit LEDs properly.
> >
> > With power LED, you want to be able to say "this is just on". Some
> > poeple like heartbeat, and have LED for that. There may be LED for
> > "disk activity", meaning activity on any harddrive. And there may be
> > activity LED for specific disk.
> >
> > Only in the last case it would be suitable to have LED reference as a
> > child of an device...
>
> Right. For all the other cases, why do you need any link with a
> device? What we have today is sufficient and can continue to be
> supported. A link to a device is only used if the led is associated
> with a particular device.
Right, so the link is only needed in some cases. So unlike your
example, we would have:
led1 { led-meaning = "heartbeat"; }
led2 { led-meaning = "link"; }
led3 { led-meaning = "err"; }
led4 { led-meaning = "activity"; what-activity = "all_harddisks"; }
ethernet { leds = < &led2, &led3 >; }
Dunno. I'd expect all the LED description in the LED node, not part of
the description there and back link from the device...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
On Tue, Dec 11, 2018 at 6:27 PM Rob Herring <[email protected]> wrote:
> On Sat, Dec 1, 2018 at 3:17 PM Jacek Anaszewski
> <[email protected]> wrote:
> > This is not true in case of associations where LED controller is
> > an independent device, as in Pavel's example [0].
>
> I'm not really following how the HDD example is different. The parent
> of an LED would be the controller. The link to the led node would be
> in the disk controller node. Though maybe if things get complicated
> enough, we'd want to describe the drives or drive bays in DT.
Not talking about this in specific, but I will need to add DT bindings
for ATA master/slave, in order to add a temperature zone
for each drive (one sensor in each drive) in my in-progress
hwmon-over-SCSI-emulation-ATA-sensors such that:
ata-controller {
ata-master {
};
ata-slave {
};
};
I haven't looked closer at this topology yet, but we definatelt
need nodes for each physical connector out of an ATA
master, somehow, so they can act as a sensor/temperature
zone.
Yours,
Linus Walleij
On 12/12/18 7:32 PM, Pavel Machek wrote:
> On Wed 2018-12-12 07:56:20, Rob Herring wrote:
>> On Wed, Dec 12, 2018 at 3:59 AM Pavel Machek <[email protected]> wrote:
>>>
>>> Hi!
>>>
>>>>> We would also probably need different DT properties for different
>>>>> types of devices, since e.g. for network case the network interface
>>>>> name would fit better for the LED name, than the phy name,
>>>>> and we would need to know what type of device name we're going
>>>>> to look for.
>>>>>
>>>>> Pavel gave following examples:
>>>>>
>>>>> eth0:green:link
>>>>> adsl0:green:link
>>>>> adsl0:red:error
>>>>>
>>>>> So we would have e.g.:
>>>>>
>>>>> associated-vl42-device = <&camera1>;
>>>>> associated-network-device = <&phy1>;
>>>>> associated-block-device = <&phy1>;
>>>>
>>>> Variable property names are kind of a pain to parse.
>>>>
>>>> Perhaps when LEDs are associated with a device, we shouldn't care
>>>> within the context of the LED subsystem what the name is. The
>>>> association is more important and if you have that exposed, then you
>>>> don't really need to care what the name is. You still have to deal
>>>> with a device with more than 1 LED, but that becomes a problem local
>>>> to that device.
>>>>
>>>> What I'm getting at is following a more standard binding pattern of
>>>> providers and consumers like we have for gpios, clocks, etc. So we'd
>>>> have something like this:
>>>>
>>>> ethernet {
>>>> ...
>>>> leds = <&green_led>, <&red_led>;
>>>> led-names = "link", "err";
>>>> };
>>>>
>>>> We can still support defining LED names as we've done, but we don't
>>>> have to come up with some elaborate naming convention that covers
>>>> every single case.
>>>
>>> I see that it would be more consistent with how gpios work, but I'm
>>> afraid this does not fit LEDs properly.
>>>
>>> With power LED, you want to be able to say "this is just on". Some
>>> poeple like heartbeat, and have LED for that. There may be LED for
>>> "disk activity", meaning activity on any harddrive. And there may be
>>> activity LED for specific disk.
>>>
>>> Only in the last case it would be suitable to have LED reference as a
>>> child of an device...
>>
>> Right. For all the other cases, why do you need any link with a
>> device? What we have today is sufficient and can continue to be
>> supported. A link to a device is only used if the led is associated
>> with a particular device.
>
> Right, so the link is only needed in some cases. So unlike your
> example, we would have:
>
> led1 { led-meaning = "heartbeat"; }
> led2 { led-meaning = "link"; }
> led3 { led-meaning = "err"; }
> led4 { led-meaning = "activity"; what-activity = "all_harddisks"; }
> ethernet { leds = < &led2, &led3 >; }
>
> Dunno. I'd expect all the LED description in the LED node, not part of
> the description there and back link from the device
Driven by the feeling that it's all going in a wrong direction
I've done a bit more analysis - please refer below to my conclusions.
We already have a means for associating LEDs connected to standalone LED
controllers with other devices - this is LED trigger mechanism.
The association can be discovered by reading "trigger" sysfs file.
Device drivers can even create their own custom triggers, comprising
device node name or phy name in their names, which are known only during
driver probing, which allows to better describe the association than the
generic ones.
When it comes to devices with built-in LEDs - let's check how network
devices handle their LEDs. I've looked into ralink wireless driver:
drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
It registers its LEDs in rt2x00leds_register(),
and composes names according to the following pattern:
snprintf(name, sizeof(name), "%s-%s::assoc",
rt2x00dev->ops->name, phy_name);
snprintf(name, sizeof(name), "%s-%s::quality",
rt2x00dev->ops->name, phy_name);
snprintf(name, sizeof(name), "%s-%s::radio",
rt2x00dev->ops->name, phy_name);
which results in the following LED names for wifi dongle:
rt73usb-phy16::assoc ->
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/leds/rt73usb-phy16::assoc
rt73usb-phy16::quality ->
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/leds/rt73usb-phy16::quality
rt73usb-phy16::radio ->
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/leds/rt73usb-phy16::radio
As it is shown, each entry under /sys/class/CLASS_NAME is a symbolic
link to the class device sub-directory located in the parent device
directory. In this case, even if we hadn't phy name in the LED name,
we could retrieve it by traversing parent device directory in the
sysfs:
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/ieee80211/phy16/
We have also available additional device and driver specific info
in the uevent file:
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/uevent:DEVTYPE=usb_interface
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/uevent:DRIVER=rt73usb
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/uevent:PRODUCT=148f/2573/1
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/uevent:TYPE=0/0/0
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/uevent:INTERFACE=255/255/255
../../devices/pci0000:00/0000:00:14.0/usb2/2-8/2-8:1.0/uevent:MODALIAS=usb:v148Fp2573d0001dc00dsc00dp00icFFiscFFipFFin00
In addition to that the driver registers also its own triggers,
that associate the LEDs it exposes with the particular phy and the
function: phy16rx phy16tx phy16assoc phy16radio.
This is the pattern to be followed also in case user wants to
associate standalone LEDs with the device. Driver of a device
that lacks onboard LEDs would have to register suitable trigger
and that's it.
In case of keyboard LEDs we have similar symlinks:
input0::capslock ->
../../devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/0003:1C4F:0002.0001/input/input0/input0::capslock
input0::numlock ->
../../devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/0003:1C4F:0002.0001/input/input0/input0::numlock
input0::scrolllock ->
../../devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/0003:1C4F:0002.0001/input/input0/input0::scrolllock
#cat
/sys/devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/0003:1C4F:0002.0001/uevent
DRIVER=hid-generic
HID_ID=0003:00001C4F:00000002
HID_NAME=SIGMACHIP USB Keyboard
HID_PHYS=usb-0000:00:14.0-3/input0
HID_UNIQ=
MODALIAS=hid:b0003g0001v00001C4Fp00000002
Having all the above it seems that we can safely remove devicename
section from LED class device naming pattern. Also no other links
in DT will be needed if we will entirely rely on LED trigger mechanism.
--
Best regards,
Jacek Anaszewski