Introduce the bindings for the Texas Instruments LP5036, LP5030, LP5024 and the LP5018
RGB LED device driver. The LP5036/3024/18 can control RGB LEDs individually
or as part of a control bank group. These devices have the ability
to adjust the mixing control for the RGB LEDs to obtain different colors
independent of the overall brightness of the LED grouping.
Datasheet:
http://www.ti.com/lit/ds/symlink/lp5024.pdf
http://www.ti.com/lit/ds/symlink/lp5036.pdf
Signed-off-by: Dan Murphy <[email protected]>
---
v2 - Added the LP5030/36 devices, defined the modules vs banked properties
renamed the file from lp5024 to lp50xx. - https://lore.kernel.org/patchwork/patch/1026514/
.../devicetree/bindings/leds/leds-lp50xx.txt | 143 ++++++++++++++++++
1 file changed, 143 insertions(+)
create mode 100644 Documentation/devicetree/bindings/leds/leds-lp50xx.txt
diff --git a/Documentation/devicetree/bindings/leds/leds-lp50xx.txt b/Documentation/devicetree/bindings/leds/leds-lp50xx.txt
new file mode 100644
index 000000000000..7bc6843ddba4
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lp50xx.txt
@@ -0,0 +1,143 @@
+* Texas Instruments - LP5018/24/30/36 RGB LED driver
+
+The LP50XX is multi-channel, I2C RGB LED Drivers that can group RGB LEDs into
+a LED group or control them individually.
+
+The difference in these RGB LED drivers is the number of supported RGB strings.
+
+Required properties:
+ - compatible:
+ "ti,lp5018"
+ "ti,lp5024"
+ "ti,lp5030"
+ "ti,lp5036"
+ - reg : I2C slave address
+ lp5018/24 - 0x28
+ lp5030/36 - 0x30
+ - #address-cells : 1
+ - #size-cells : 0
+
+Optional properties:
+ - enable-gpios : gpio pin to enable/disable the device.
+ - vled-supply : LED supply
+
+Required child properties:
+ - reg : Is the child node iteration.
+
+Required Child properties but only one should be defined per child:
+Either one of these two properties are required for each node. The
+property ti,led-bank takes precedence over the ti,led-module within the same
+node.
+
+ - ti,led-module : This property denotes the single LED module number
+ that will be controlled in the LED class instance.
+ - ti,led-bank : This property denotes the LED module numbers that will
+ be controlled as a single RGB cluster. Each LED module
+ number will be controlled by a single LED class instance.
+ There can only be one instance of the ti,led-bank
+ property for each device node.
+
+The LED outpus associated with the LED modules are defined in Table 1 of the
+corresponding data sheets.
+
+LP5018 - 6 Total RGB cluster LED outputs 0-5
+LP5024 - 8 Total RGB cluster LED outputs 0-7
+LP5030 - 10 Total RGB cluster LED outputs 0-9
+LP5036 - 12 Total RGB cluster LED outputs 0-11
+
+Optional child properties:
+ - label : see Documentation/devicetree/bindings/leds/common.txt
+ - linux,default-trigger :
+ see Documentation/devicetree/bindings/leds/common.txt
+
+Examples:
+LP5018 and LP5024 example:
+led-controller@29 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "ti,lp5024";
+ reg = <0x29>;
+ enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ vled-supply = <&vmmcsd_fixed>;
+
+ led@0 {
+ reg = <0>;
+ label = "led1_mod";
+ ti,led-module = <1>;
+ };
+
+ led@1 {
+ reg = <1>;
+ label = "banked_leds";
+ ti,led-bank = <0 2 5 3 >;
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "led4_mod";
+ ti,led-module = <4>;
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "led7_mod";
+ ti,led-module = <7>;
+ };
+
+ led@4 {
+ reg = <4>;
+ label = "led6_mod";
+ ti,led-module = <6>;
+ };
+};
+
+LP5030 and LP5036 example:
+led-controller@30 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "ti,lp5036";
+ reg = <0x30>;
+ enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ vled-supply = <&vmmcsd_fixed>;
+
+ led@0 {
+ reg = <0>;
+ label = "led1_mod";
+ ti,led-module = <1>;
+ };
+
+ led@1 {
+ reg = <1>;
+ label = "led_banked";
+ ti,led-bank = <0 2 5 3 9 10 >;
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "led4_mod";
+ ti,led-module = <4>;
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "led7_mod";
+ ti,led-module = <7>;
+ };
+
+ led@4 {
+ reg = <4>;
+ label = "led6_mod";
+ ti,led-module = <6>;
+ };
+
+ led@5 {
+ reg = <5>;
+ label = "led8_mod";
+ ti,led-module = <8>;
+ };
+};
+
+
+For more product information please see the link below:
+http://www.ti.com/lit/ds/symlink/lp5024.pdf
+http://www.ti.com/lit/ds/symlink/lp5036.pdf
--
2.20.1.98.gecbdaf0899
Introduce the LP5036/30/24/18 RGB LED driver.
The difference in these parts are the number of
LED outputs where the:
LP5036 can control 36 LEDs
LP5030 can control 30 LEDs
LP5024 can control 24 LEDs
LP5018 can control 18 LEDs
The device has the ability to group LED output into control banks
so that multiple LED banks can be controlled with the same mixing and
brightness. Inversely the LEDs can also be controlled independently.
Signed-off-by: Dan Murphy <[email protected]>
---
v2 - Changed the mix and module files to a single "color" file, added the LP5030
and LP5036 register mapping, added ABI documentation, updated the parsing of
DT and led sources to match DT, renamed driver to leds-lp50xx.c - https://lore.kernel.org/patchwork/patch/1026515/
Documentation/leds/leds-lp50xx.txt | 36 ++
drivers/leds/Kconfig | 7 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-lp50xx.c | 754 +++++++++++++++++++++++++++++
4 files changed, 798 insertions(+)
create mode 100644 Documentation/leds/leds-lp50xx.txt
create mode 100644 drivers/leds/leds-lp50xx.c
diff --git a/Documentation/leds/leds-lp50xx.txt b/Documentation/leds/leds-lp50xx.txt
new file mode 100644
index 000000000000..8b1b01dfdd22
--- /dev/null
+++ b/Documentation/leds/leds-lp50xx.txt
@@ -0,0 +1,36 @@
+LP5018/LP5024/LP5030/LP5036 Common Driver
+=================================================
+
+Authors: Dan Murphy <[email protected]>
+
+Description
+-----------
+The LP50XX RGB LED drivers have the ability to group multiple RGB cluster
+LEDs into a single group for simultaneous control or expose single RGB cluster
+for control. This device exposes different register interfaces to control
+the cluster brightness as well as the individual RGB LEDs color intensity.
+
+RGB Cluster Color Control
+-------------------------
+The LP50xx driver will expose a file called "color" for each LED class instance
+defined. This file will accept a 24-bit RGB value in which the the color of the
+RGB LEDs will be set.
+
+The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
+XX - Do not care ignored by the driver
+RR - is the 8 bit Red LED value
+GG - is the 8 bit Green LED value
+BB - is the 8 bit Blue LED value
+
+Example:
+LED module output 4 of the LP5024 will be a yellow color:
+echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
+
+LED module output 4 of the LP5024 will be dimmed 50%:
+echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
+
+LED banked RGBs of the LP5036 will be a white color:
+echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
+
+LED banked RGBs of the LP50364 will be dimmed 50%:
+echo 0x80 > /sys/class/leds/lp5036\:led_banked/brightness
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a72f97fca57b..5f413445a667 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -326,6 +326,13 @@ config LEDS_LP3952
To compile this driver as a module, choose M here: the
module will be called leds-lp3952.
+config LEDS_LP50XX
+ tristate "LED Support for TI LP5036/30/24/18 LED driver chip"
+ depends on LEDS_CLASS && REGMAP_I2C
+ help
+ If you say yes here you get support for the Texas Instruments
+ LP5036, LP5030, LP5024 and LP5018 LED driver.
+
config LEDS_LP55XX_COMMON
tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 4c1b0054f379..852eff0b773f 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o
+obj-$(CONFIG_LEDS_LP50XX) += leds-lp50xx.o
obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o
obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
new file mode 100644
index 000000000000..41bb2e0129c8
--- /dev/null
+++ b/drivers/leds/leds-lp50xx.c
@@ -0,0 +1,754 @@
+// SPDX-License-Identifier: GPL-2.0
+/* TI LP50XX LED chip family driver
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <uapi/linux/uleds.h>
+
+#define LP50XX_DEV_CFG0 0x00
+#define LP50XX_DEV_CFG1 0x01
+#define LP50XX_LED_CFG0 0x02
+
+/* LP5018 and LP5024 registers */
+#define LP5024_BNK_BRT 0x03
+#define LP5024_BNKA_CLR 0x04
+#define LP5024_BNKB_CLR 0x05
+#define LP5024_BNKC_CLR 0x06
+#define LP5024_LED0_BRT 0x07
+#define LP5024_LED1_BRT 0x08
+#define LP5024_LED2_BRT 0x09
+#define LP5024_LED3_BRT 0x0a
+#define LP5024_LED4_BRT 0x0b
+#define LP5024_LED5_BRT 0x0c
+#define LP5024_LED6_BRT 0x0d
+#define LP5024_LED7_BRT 0x0e
+
+#define LP5024_OUT0_CLR 0x0f
+#define LP5024_OUT1_CLR 0x10
+#define LP5024_OUT2_CLR 0x11
+#define LP5024_OUT3_CLR 0x12
+#define LP5024_OUT4_CLR 0x13
+#define LP5024_OUT5_CLR 0x14
+#define LP5024_OUT6_CLR 0x15
+#define LP5024_OUT7_CLR 0x16
+#define LP5024_OUT8_CLR 0x17
+#define LP5024_OUT9_CLR 0x18
+#define LP5024_OUT10_CLR 0x19
+#define LP5024_OUT11_CLR 0x1a
+#define LP5024_OUT12_CLR 0x1b
+#define LP5024_OUT13_CLR 0x1c
+#define LP5024_OUT14_CLR 0x1d
+#define LP5024_OUT15_CLR 0x1e
+#define LP5024_OUT16_CLR 0x1f
+#define LP5024_OUT17_CLR 0x20
+#define LP5024_OUT18_CLR 0x21
+#define LP5024_OUT19_CLR 0x22
+#define LP5024_OUT20_CLR 0x23
+#define LP5024_OUT21_CLR 0x24
+#define LP5024_OUT22_CLR 0x25
+#define LP5024_OUT23_CLR 0x26
+#define LP5024_RESET 0x27
+
+/* LP5030 and LP5036 registers */
+#define LP5036_LED_CFG1 0x03
+#define LP5036_BNK_BRT 0x04
+#define LP5036_BNKA_CLR 0x05
+#define LP5036_BNKB_CLR 0x06
+#define LP5036_BNKC_CLR 0x07
+#define LP5036_LED0_BRT 0x08
+#define LP5036_LED1_BRT 0x09
+#define LP5036_LED2_BRT 0x0a
+#define LP5036_LED3_BRT 0x0b
+#define LP5036_LED4_BRT 0x0c
+#define LP5036_LED5_BRT 0x0d
+#define LP5036_LED6_BRT 0x0e
+#define LP5036_LED7_BRT 0x0f
+#define LP5036_LED8_BRT 0x10
+#define LP5036_LED9_BRT 0x11
+#define LP5036_LED10_BRT 0x12
+#define LP5036_LED11_BRT 0x13
+
+#define LP5036_OUT0_CLR 0x14
+#define LP5036_OUT1_CLR 0x15
+#define LP5036_OUT2_CLR 0x16
+#define LP5036_OUT3_CLR 0x17
+#define LP5036_OUT4_CLR 0x18
+#define LP5036_OUT5_CLR 0x19
+#define LP5036_OUT6_CLR 0x1a
+#define LP5036_OUT7_CLR 0x1b
+#define LP5036_OUT8_CLR 0x1c
+#define LP5036_OUT9_CLR 0x1d
+#define LP5036_OUT10_CLR 0x1e
+#define LP5036_OUT11_CLR 0x1f
+#define LP5036_OUT12_CLR 0x20
+#define LP5036_OUT13_CLR 0x21
+#define LP5036_OUT14_CLR 0x22
+#define LP5036_OUT15_CLR 0x23
+#define LP5036_OUT16_CLR 0x24
+#define LP5036_OUT17_CLR 0x25
+#define LP5036_OUT18_CLR 0x26
+#define LP5036_OUT19_CLR 0x27
+#define LP5036_OUT20_CLR 0x28
+#define LP5036_OUT21_CLR 0x29
+#define LP5036_OUT22_CLR 0x2a
+#define LP5036_OUT23_CLR 0x2b
+#define LP5036_OUT24_CLR 0x2c
+#define LP5036_OUT25_CLR 0x2d
+#define LP5036_OUT26_CLR 0x2e
+#define LP5036_OUT27_CLR 0x2f
+#define LP5036_OUT28_CLR 0x30
+#define LP5036_OUT29_CLR 0x31
+#define LP5036_OUT30_CLR 0x32
+#define LP5036_OUT31_CLR 0x33
+#define LP5036_OUT32_CLR 0x34
+#define LP5036_OUT33_CLR 0x35
+#define LP5036_OUT34_CLR 0x36
+#define LP5036_OUT35_CLR 0x37
+#define LP5036_RESET 0x38
+
+#define LP50XX_SW_RESET 0xff
+
+#define LP50XX_CHIP_EN BIT(6)
+
+#define LP5018_MAX_LED_STRINGS 6
+#define LP5024_MAX_LED_STRINGS 8
+#define LP5030_MAX_LED_STRINGS 10
+#define LP5036_MAX_LED_STRINGS 12
+
+enum lp50xx_model {
+ LP5018,
+ LP5024,
+ LP5030,
+ LP5036,
+};
+
+struct lp50xx_led {
+ u32 led_strings[LP5036_MAX_LED_STRINGS];
+ char label[LED_MAX_NAME_SIZE];
+ struct led_classdev led_dev;
+ struct lp50xx *priv;
+ int led_number;
+ u8 ctrl_bank_enabled;
+};
+
+/**
+ * struct lp50xx -
+ * @enable_gpio: Hardware enable gpio
+ * @regulator: LED supply regulator pointer
+ * @client: Pointer to the I2C client
+ * @regmap: Devices register map
+ * @dev: Pointer to the devices device struct
+ * @lock: Lock for reading/writing the device
+ * @model_id: ID of the device
+ * @leds: Array of LED strings
+ */
+struct lp50xx {
+ struct gpio_desc *enable_gpio;
+ struct regulator *regulator;
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct device *dev;
+ struct mutex lock;
+ enum lp50xx_model model_id;
+ int max_leds;
+ int num_of_leds;
+
+ u8 led_brightness0_reg;
+ u8 mix_out0_reg;
+ u8 bank_brt_reg;
+ u8 bank_mix_reg;
+ u8 reset_reg;
+
+ /* This needs to be at the end of the struct */
+ struct lp50xx_led leds[];
+};
+
+static const struct reg_default lp5024_reg_defs[] = {
+ {LP50XX_DEV_CFG0, 0x0},
+ {LP50XX_DEV_CFG1, 0x3c},
+ {LP50XX_LED_CFG0, 0x0},
+ {LP5024_BNK_BRT, 0xff},
+ {LP5024_BNKA_CLR, 0x0f},
+ {LP5024_BNKB_CLR, 0x0f},
+ {LP5024_BNKC_CLR, 0x0f},
+ {LP5024_LED0_BRT, 0x0f},
+ {LP5024_LED1_BRT, 0xff},
+ {LP5024_LED2_BRT, 0xff},
+ {LP5024_LED3_BRT, 0xff},
+ {LP5024_LED4_BRT, 0xff},
+ {LP5024_LED5_BRT, 0xff},
+ {LP5024_LED6_BRT, 0xff},
+ {LP5024_LED7_BRT, 0xff},
+ {LP5024_OUT0_CLR, 0x0f},
+ {LP5024_OUT1_CLR, 0x00},
+ {LP5024_OUT2_CLR, 0x00},
+ {LP5024_OUT3_CLR, 0x00},
+ {LP5024_OUT4_CLR, 0x00},
+ {LP5024_OUT5_CLR, 0x00},
+ {LP5024_OUT6_CLR, 0x00},
+ {LP5024_OUT7_CLR, 0x00},
+ {LP5024_OUT8_CLR, 0x00},
+ {LP5024_OUT9_CLR, 0x00},
+ {LP5024_OUT10_CLR, 0x00},
+ {LP5024_OUT11_CLR, 0x00},
+ {LP5024_OUT12_CLR, 0x00},
+ {LP5024_OUT13_CLR, 0x00},
+ {LP5024_OUT14_CLR, 0x00},
+ {LP5024_OUT15_CLR, 0x00},
+ {LP5024_OUT16_CLR, 0x00},
+ {LP5024_OUT17_CLR, 0x00},
+ {LP5024_OUT18_CLR, 0x00},
+ {LP5024_OUT19_CLR, 0x00},
+ {LP5024_OUT20_CLR, 0x00},
+ {LP5024_OUT21_CLR, 0x00},
+ {LP5024_OUT22_CLR, 0x00},
+ {LP5024_OUT23_CLR, 0x00},
+ {LP5024_RESET, 0x00}
+};
+
+static const struct reg_default lp5036_reg_defs[] = {
+ {LP50XX_DEV_CFG0, 0x0},
+ {LP50XX_DEV_CFG1, 0x3c},
+ {LP50XX_LED_CFG0, 0x0},
+ {LP5036_LED_CFG1, 0x0},
+ {LP5036_BNK_BRT, 0xff},
+ {LP5036_BNKA_CLR, 0x0f},
+ {LP5036_BNKB_CLR, 0x0f},
+ {LP5036_BNKC_CLR, 0x0f},
+ {LP5036_LED0_BRT, 0x0f},
+ {LP5036_LED1_BRT, 0xff},
+ {LP5036_LED2_BRT, 0xff},
+ {LP5036_LED3_BRT, 0xff},
+ {LP5036_LED4_BRT, 0xff},
+ {LP5036_LED5_BRT, 0xff},
+ {LP5036_LED6_BRT, 0xff},
+ {LP5036_LED7_BRT, 0xff},
+ {LP5036_OUT0_CLR, 0x0f},
+ {LP5036_OUT1_CLR, 0x00},
+ {LP5036_OUT2_CLR, 0x00},
+ {LP5036_OUT3_CLR, 0x00},
+ {LP5036_OUT4_CLR, 0x00},
+ {LP5036_OUT5_CLR, 0x00},
+ {LP5036_OUT6_CLR, 0x00},
+ {LP5036_OUT7_CLR, 0x00},
+ {LP5036_OUT8_CLR, 0x00},
+ {LP5036_OUT9_CLR, 0x00},
+ {LP5036_OUT10_CLR, 0x00},
+ {LP5036_OUT11_CLR, 0x00},
+ {LP5036_OUT12_CLR, 0x00},
+ {LP5036_OUT13_CLR, 0x00},
+ {LP5036_OUT14_CLR, 0x00},
+ {LP5036_OUT15_CLR, 0x00},
+ {LP5036_OUT16_CLR, 0x00},
+ {LP5036_OUT17_CLR, 0x00},
+ {LP5036_OUT18_CLR, 0x00},
+ {LP5036_OUT19_CLR, 0x00},
+ {LP5036_OUT20_CLR, 0x00},
+ {LP5036_OUT21_CLR, 0x00},
+ {LP5036_OUT22_CLR, 0x00},
+ {LP5036_OUT23_CLR, 0x00},
+ {LP5036_OUT24_CLR, 0x00},
+ {LP5036_OUT25_CLR, 0x00},
+ {LP5036_OUT26_CLR, 0x00},
+ {LP5036_OUT27_CLR, 0x00},
+ {LP5036_OUT28_CLR, 0x00},
+ {LP5036_OUT29_CLR, 0x00},
+ {LP5036_OUT30_CLR, 0x00},
+ {LP5036_OUT31_CLR, 0x00},
+ {LP5036_OUT32_CLR, 0x00},
+ {LP5036_OUT33_CLR, 0x00},
+ {LP5036_OUT34_CLR, 0x00},
+ {LP5036_OUT35_CLR, 0x00},
+ {LP5036_RESET, 0x00}
+};
+
+static const struct regmap_config lp5024_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = LP5024_RESET,
+ .reg_defaults = lp5024_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(lp5024_reg_defs),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_config lp5036_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = LP5036_RESET,
+ .reg_defaults = lp5036_reg_defs,
+ .num_reg_defaults = ARRAY_SIZE(lp5036_reg_defs),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static ssize_t color_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
+ led_dev);
+ struct lp50xx *priv = led->priv;
+ unsigned int red_val, green_val, blue_val;
+ u8 red_reg, green_reg, blue_reg;
+ u32 mix_value = 0;
+ u8 led_offset;
+ int ret;
+
+ if (led->ctrl_bank_enabled) {
+ red_reg = priv->bank_mix_reg;
+ green_reg = priv->bank_mix_reg + 1;
+ blue_reg = priv->bank_mix_reg + 2;
+ } else {
+ led_offset = (led->led_number * 3);
+ red_reg = priv->mix_out0_reg + led_offset;
+ green_reg = priv->mix_out0_reg + led_offset + 1;
+ blue_reg = priv->mix_out0_reg + led_offset + 2;
+ }
+
+ ret = regmap_read(priv->regmap, red_reg, &red_val);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot read LED value\n");
+ goto out;
+ }
+
+ ret = regmap_read(priv->regmap, green_reg, &green_val);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot read LED value\n");
+ goto out;
+ }
+
+ ret = regmap_read(priv->regmap, blue_reg, &blue_val);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot read LED value\n");
+ goto out;
+ }
+
+ mix_value = (red_val << 16 | green_val << 8 | blue_val);
+
+out:
+ return scnprintf(buf, PAGE_SIZE, "0x%X\n", mix_value);
+}
+
+static ssize_t color_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
+ led_dev);
+ struct lp50xx *priv = led->priv;
+ u8 led_offset;
+ unsigned long mix_value;
+ u8 red_reg, green_reg, blue_reg;
+ u8 red_val, green_val, blue_val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &mix_value);
+ if (ret)
+ return ret;
+
+ if (led->ctrl_bank_enabled) {
+ red_reg = priv->bank_mix_reg;
+ green_reg = priv->bank_mix_reg + 1;
+ blue_reg = priv->bank_mix_reg + 2;
+ } else {
+ led_offset = (led->led_number * 3);
+ red_reg = priv->mix_out0_reg + led_offset;
+ green_reg = priv->mix_out0_reg + led_offset + 1;
+ blue_reg = priv->mix_out0_reg + led_offset + 2;
+ }
+
+ red_val = (mix_value & 0xff0000) >> 16;
+ green_val = (mix_value & 0xff00) >> 8;
+ blue_val = (mix_value & 0xff);
+
+ ret = regmap_write(priv->regmap, red_reg, red_val);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot write LED value\n");
+ goto out;
+ }
+
+ ret = regmap_write(priv->regmap, green_reg, green_val);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot write LED value\n");
+ goto out;
+ }
+
+ ret = regmap_write(priv->regmap, blue_reg, blue_val);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot write LED value\n");
+ goto out;
+ }
+out:
+ return size;
+}
+
+static DEVICE_ATTR_RW(color);
+
+static struct attribute *lp50xx_led_color_attrs[] = {
+ &dev_attr_color.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(lp50xx_led_color);
+
+static int lp50xx_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brt_val)
+{
+ struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
+ led_dev);
+ int ret = 0;
+ u8 reg_val;
+
+ mutex_lock(&led->priv->lock);
+
+ if (led->ctrl_bank_enabled)
+ reg_val = led->priv->bank_brt_reg;
+ else
+ reg_val = led->priv->led_brightness0_reg + led->led_number;
+
+ ret = regmap_write(led->priv->regmap, reg_val, brt_val);
+
+ mutex_unlock(&led->priv->lock);
+
+ return ret;
+}
+
+static enum led_brightness lp50xx_brightness_get(struct led_classdev *led_cdev)
+{
+ struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
+ led_dev);
+ unsigned int brt_val;
+ u8 reg_val;
+ int ret;
+
+ mutex_lock(&led->priv->lock);
+
+ if (led->ctrl_bank_enabled)
+ reg_val = led->priv->bank_brt_reg;
+ else
+ reg_val = led->priv->led_brightness0_reg + led->led_number;
+
+ ret = regmap_read(led->priv->regmap, reg_val, &brt_val);
+
+ mutex_unlock(&led->priv->lock);
+
+ return brt_val;
+}
+
+static void lp50xx_set_led_values(struct lp50xx *priv)
+{
+ if (priv->model_id == LP5018 || priv->model_id == LP5024) {
+ priv->led_brightness0_reg = LP5024_LED0_BRT;
+ priv->mix_out0_reg = LP5024_OUT0_CLR;
+ priv->bank_brt_reg = LP5024_BNK_BRT;
+ priv->bank_mix_reg = LP5024_BNKA_CLR;
+ priv->reset_reg = LP5024_RESET;
+ } else {
+ priv->led_brightness0_reg = LP5036_LED0_BRT;
+ priv->mix_out0_reg = LP5036_OUT0_CLR;
+ priv->bank_brt_reg = LP5036_BNK_BRT;
+ priv->bank_mix_reg = LP5036_BNKA_CLR;
+ priv->reset_reg = LP5036_RESET;
+ }
+}
+
+static int lp50xx_set_banks(struct lp50xx *priv)
+{
+ struct lp50xx_led *led;
+ u8 led_ctrl_enable = 0;
+ u8 led1_ctrl_enable = 0;
+ u8 ctrl_ext = 0;
+ int i, j;
+ int ret;
+
+ for (i = 0; i <= priv->num_of_leds; i++) {
+ led = &priv->leds[i];
+ if (!led->ctrl_bank_enabled)
+ continue;
+
+ for (j = 0; j <= priv->max_leds - 1; j++) {
+ if (led->led_strings[j] > (LP5024_MAX_LED_STRINGS - 1)) {
+ ctrl_ext = led->led_strings[j] - LP5024_MAX_LED_STRINGS;
+ led1_ctrl_enable |= (1 << ctrl_ext);
+ } else {
+ led_ctrl_enable |= (1 << led->led_strings[j]);
+ }
+ }
+ }
+
+ ret = regmap_write(priv->regmap, LP50XX_LED_CFG0, led_ctrl_enable);
+
+ if (led1_ctrl_enable)
+ ret = regmap_write(priv->regmap, LP5036_LED_CFG1,
+ led1_ctrl_enable);
+
+ return ret;
+}
+
+static int lp50xx_init(struct lp50xx *priv)
+{
+ int ret;
+
+ lp50xx_set_led_values(priv);
+
+ if (priv->enable_gpio) {
+ gpiod_direction_output(priv->enable_gpio, 1);
+ } else {
+ ret = regmap_write(priv->regmap, priv->reset_reg,
+ LP50XX_SW_RESET);
+ if (ret) {
+ dev_err(&priv->client->dev,
+ "Cannot reset the device\n");
+ goto out;
+ }
+ }
+
+ ret = lp50xx_set_banks(priv);
+ if (ret) {
+ dev_err(&priv->client->dev, "Cannot set the banks\n");
+ goto out;
+ }
+
+ ret = regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
+ if (ret)
+ dev_err(&priv->client->dev, "Cannot write ctrl enable\n");
+
+out:
+ return ret;
+}
+
+static int lp50xx_probe_dt(struct lp50xx *priv)
+{
+ struct fwnode_handle *child = NULL;
+ struct lp50xx_led *led;
+ int control_bank_defined = 0;
+ const char *name;
+ int led_number;
+ size_t i = 0;
+ int ret;
+
+ priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
+ "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(priv->enable_gpio)) {
+ ret = PTR_ERR(priv->enable_gpio);
+ dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
+ ret);
+ return ret;
+ }
+
+ priv->regulator = devm_regulator_get(&priv->client->dev, "vled");
+ if (IS_ERR(priv->regulator))
+ priv->regulator = NULL;
+
+ if (priv->model_id == LP5018)
+ priv->max_leds = LP5018_MAX_LED_STRINGS;
+ else if (priv->model_id == LP5024)
+ priv->max_leds = LP5024_MAX_LED_STRINGS;
+ else if (priv->model_id == LP5030)
+ priv->max_leds = LP5030_MAX_LED_STRINGS;
+ else
+ priv->max_leds = LP5036_MAX_LED_STRINGS;
+
+ device_for_each_child_node(&priv->client->dev, child) {
+ led = &priv->leds[i];
+
+ if (fwnode_property_present(child, "ti,led-bank")) {
+ led->ctrl_bank_enabled = 1;
+ if (!control_bank_defined)
+ control_bank_defined = 1;
+ else {
+ dev_err(&priv->client->dev,
+ "ti,led-bank defined twice\n");
+ fwnode_handle_put(child);
+ goto child_out;
+ }
+ } else {
+ led->ctrl_bank_enabled = 0;
+ }
+
+ if (led->ctrl_bank_enabled) {
+ ret = fwnode_property_read_u32_array(child,
+ "ti,led-bank",
+ NULL, 0);
+ ret = fwnode_property_read_u32_array(child,
+ "ti,led-bank",
+ led->led_strings,
+ ret);
+
+ led->led_number = led->led_strings[0];
+
+ } else {
+ ret = fwnode_property_read_u32(child, "ti,led-module",
+ &led_number);
+
+ led->led_number = led_number;
+ }
+ if (ret) {
+ dev_err(&priv->client->dev,
+ "led sourcing property missing\n");
+ fwnode_handle_put(child);
+ goto child_out;
+ }
+
+ if (led_number > priv->max_leds) {
+ dev_err(&priv->client->dev,
+ "led-sources property is invalid\n");
+ ret = -EINVAL;
+ fwnode_handle_put(child);
+ goto child_out;
+ }
+
+ ret = fwnode_property_read_string(child, "label", &name);
+ if (ret)
+ snprintf(led->label, sizeof(led->label),
+ "%s::", priv->client->name);
+ else
+ snprintf(led->label, sizeof(led->label),
+ "%s:%s", priv->client->name, name);
+
+ fwnode_property_read_string(child, "linux,default-trigger",
+ &led->led_dev.default_trigger);
+
+ led->priv = priv;
+ led->led_dev.name = led->label;
+ led->led_dev.brightness_set_blocking = lp50xx_brightness_set;
+ led->led_dev.brightness_get = lp50xx_brightness_get;
+ led->led_dev.groups = lp50xx_led_color_groups;
+
+ ret = devm_led_classdev_register(&priv->client->dev,
+ &led->led_dev);
+ if (ret) {
+ dev_err(&priv->client->dev, "led register err: %d\n",
+ ret);
+ fwnode_handle_put(child);
+ goto child_out;
+ }
+ i++;
+ }
+ priv->num_of_leds = i;
+
+child_out:
+ return ret;
+}
+
+static int lp50xx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lp50xx *led;
+ int count;
+ int ret;
+
+ count = device_get_child_node_count(&client->dev);
+ if (!count) {
+ dev_err(&client->dev, "LEDs are not defined in device tree!");
+ return -ENODEV;
+ }
+
+ led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
+ GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+
+ mutex_init(&led->lock);
+ led->client = client;
+ led->dev = &client->dev;
+ led->model_id = id->driver_data;
+ i2c_set_clientdata(client, led);
+
+ if (led->model_id == LP5018 || led->model_id == LP5024)
+ led->regmap = devm_regmap_init_i2c(client,
+ &lp5024_regmap_config);
+ else
+ led->regmap = devm_regmap_init_i2c(client,
+ &lp5036_regmap_config);
+
+ if (IS_ERR(led->regmap)) {
+ ret = PTR_ERR(led->regmap);
+ dev_err(&client->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = lp50xx_probe_dt(led);
+ if (ret)
+ return ret;
+
+ ret = lp50xx_init(led);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lp50xx_remove(struct i2c_client *client)
+{
+ struct lp50xx *led = i2c_get_clientdata(client);
+ int ret;
+
+ ret = regmap_update_bits(led->regmap, LP50XX_DEV_CFG0,
+ LP50XX_CHIP_EN, 0);
+ if (ret) {
+ dev_err(&led->client->dev, "Failed to disable regulator\n");
+ return ret;
+ }
+
+ if (led->enable_gpio)
+ gpiod_direction_output(led->enable_gpio, 0);
+
+ if (led->regulator) {
+ ret = regulator_disable(led->regulator);
+ if (ret)
+ dev_err(&led->client->dev,
+ "Failed to disable regulator\n");
+ }
+
+ mutex_destroy(&led->lock);
+
+ return 0;
+}
+
+static const struct i2c_device_id lp50xx_id[] = {
+ { "lp5018", LP5018 },
+ { "lp5024", LP5024 },
+ { "lp5030", LP5030 },
+ { "lp5036", LP5036 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, lp50xx_id);
+
+static const struct of_device_id of_lp50xx_leds_match[] = {
+ { .compatible = "ti,lp5018", },
+ { .compatible = "ti,lp5024", },
+ { .compatible = "ti,lp5030", },
+ { .compatible = "ti,lp5036", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_lp50xx_leds_match);
+
+static struct i2c_driver lp50xx_driver = {
+ .driver = {
+ .name = "lp50xx",
+ .of_match_table = of_lp50xx_leds_match,
+ },
+ .probe = lp50xx_probe,
+ .remove = lp50xx_remove,
+ .id_table = lp50xx_id,
+};
+module_i2c_driver(lp50xx_driver);
+
+MODULE_DESCRIPTION("Texas Instruments LP5024 LED driver");
+MODULE_AUTHOR("Dan Murphy <[email protected]>");
+MODULE_LICENSE("GPL v2");
--
2.20.1.98.gecbdaf0899
Hi Dan,
Thank you for the patch.
Seeing the mess with regs and led-modules I think
it will be better to abide by the regs alone.
Please see below how I would structure that.
On 1/14/19 10:17 PM, Dan Murphy wrote:
> Introduce the bindings for the Texas Instruments LP5036, LP5030, LP5024 and the LP5018
> RGB LED device driver. The LP5036/3024/18 can control RGB LEDs individually
> or as part of a control bank group. These devices have the ability
> to adjust the mixing control for the RGB LEDs to obtain different colors
> independent of the overall brightness of the LED grouping.
>
> Datasheet:
> http://www.ti.com/lit/ds/symlink/lp5024.pdf
> http://www.ti.com/lit/ds/symlink/lp5036.pdf
>
> Signed-off-by: Dan Murphy <[email protected]>
> ---
>
> v2 - Added the LP5030/36 devices, defined the modules vs banked properties
> renamed the file from lp5024 to lp50xx. - https://lore.kernel.org/patchwork/patch/1026514/
>
> .../devicetree/bindings/leds/leds-lp50xx.txt | 143 ++++++++++++++++++
> 1 file changed, 143 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/leds/leds-lp50xx.txt
>
> diff --git a/Documentation/devicetree/bindings/leds/leds-lp50xx.txt b/Documentation/devicetree/bindings/leds/leds-lp50xx.txt
> new file mode 100644
> index 000000000000..7bc6843ddba4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/leds-lp50xx.txt
> @@ -0,0 +1,143 @@
> +* Texas Instruments - LP5018/24/30/36 RGB LED driver
> +
> +The LP50XX is multi-channel, I2C RGB LED Drivers that can group RGB LEDs into
> +a LED group or control them individually.
> +
> +The difference in these RGB LED drivers is the number of supported RGB strings.
Maybe it would be better to replace "strings" with "modules"?
Strings usually mean LEDs connected in a row, which is specific
to backlights.
> +Required properties:
> + - compatible:
> + "ti,lp5018"
> + "ti,lp5024"
> + "ti,lp5030"
> + "ti,lp5036"
> + - reg : I2C slave address
> + lp5018/24 - 0x28
> + lp5030/36 - 0x30
> + - #address-cells : 1
> + - #size-cells : 0
> +
> +Optional properties:
> + - enable-gpios : gpio pin to enable/disable the device.
> + - vled-supply : LED supply
> +
> +Required child properties:
> + - reg : Is the child node iteration.
Let's change it to:
- reg : RGB LED module number. For the node describing RGB cluster bank
it should match first element of ti,led-bank array.
> +
> +Required Child properties but only one should be defined per child:
> +Either one of these two properties are required for each node. The
> +property ti,led-bank takes precedence over the ti,led-module within the same
> +node.
> +
> + - ti,led-module : This property denotes the single LED module number
> + that will be controlled in the LED class instance.
It will be not needed then.
> + - ti,led-bank : This property denotes the LED module numbers that will
> + be controlled as a single RGB cluster. Each LED module
> + number will be controlled by a single LED class instance.
> + There can only be one instance of the ti,led-bank
> + property for each device node.
> +
> +The LED outpus associated with the LED modules are defined in Table 1 of the
> +corresponding data sheets.
> +
> +LP5018 - 6 Total RGB cluster LED outputs 0-5
> +LP5024 - 8 Total RGB cluster LED outputs 0-7
> +LP5030 - 10 Total RGB cluster LED outputs 0-9
> +LP5036 - 12 Total RGB cluster LED outputs 0-11
> +
> +Optional child properties:
> + - label : see Documentation/devicetree/bindings/leds/common.txt
> + - linux,default-trigger :
> + see Documentation/devicetree/bindings/leds/common.txt
> +
> +Examples:
> +LP5018 and LP5024 example:
> +led-controller@29 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "ti,lp5024";
> + reg = <0x29>;
> + enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
> + vled-supply = <&vmmcsd_fixed>;
> +
> + led@0 {
> + reg = <0>;
> + label = "led1_mod";
> + ti,led-module = <1>;
> + };
> +
> + led@1 {
> + reg = <1>;
> + label = "banked_leds";
> + ti,led-bank = <0 2 5 3 >;
> + };
> +
> + led@2 {
> + reg = <2>;
> + label = "led4_mod";
> + ti,led-module = <4>;
> + };
> +
> + led@3 {
> + reg = <3>;
> + label = "led7_mod";
> + ti,led-module = <7>;
> + };
> +
> + led@4 {
> + reg = <4>;
> + label = "led6_mod";
> + ti,led-module = <6>;
> + };
Without ti,led-module it will look like below:
led@0 {
reg = <0>;
label = "banked_leds";
ti,led-bank = <0 2 5 3 >;
};
led@1 {
reg = <1>;
label = "led1_mod";
};
led@4 {
reg = <4>;
label = "led4_mod";
};
led@6 {
reg = <6>;
label = "led6_mod";
};
led@7 {
reg = <7>;
label = "led7_mod";
};
> +};
> +
> +LP5030 and LP5036 example:
> +led-controller@30 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "ti,lp5036";
> + reg = <0x30>;
> + enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
> + vled-supply = <&vmmcsd_fixed>;
> +
> + led@0 {
> + reg = <0>;
> + label = "led1_mod";
> + ti,led-module = <1>;
> + };
> +
> + led@1 {
> + reg = <1>;
> + label = "led_banked";
> + ti,led-bank = <0 2 5 3 9 10 >;
> + };
> +
> + led@2 {
> + reg = <2>;
> + label = "led4_mod";
> + ti,led-module = <4>;
> + };
> +
> + led@3 {
> + reg = <3>;
> + label = "led7_mod";
> + ti,led-module = <7>;
> + };
> +
> + led@4 {
> + reg = <4>;
> + label = "led6_mod";
> + ti,led-module = <6>;
> + };
> +
> + led@5 {
> + reg = <5>;
> + label = "led8_mod";
> + ti,led-module = <8>;
> + };
> +};
> +
> +
> +For more product information please see the link below:
> +http://www.ti.com/lit/ds/symlink/lp5024.pdf
> +http://www.ti.com/lit/ds/symlink/lp5036.pdf
>
--
Best regards,
Jacek Anaszewski
Hi Da,
Thank you for the v2.
I have some remarks below.
On 1/14/19 10:17 PM, Dan Murphy wrote:
> Introduce the LP5036/30/24/18 RGB LED driver.
> The difference in these parts are the number of
> LED outputs where the:
>
> LP5036 can control 36 LEDs
> LP5030 can control 30 LEDs
> LP5024 can control 24 LEDs
> LP5018 can control 18 LEDs
>
> The device has the ability to group LED output into control banks
> so that multiple LED banks can be controlled with the same mixing and
> brightness. Inversely the LEDs can also be controlled independently.
>
> Signed-off-by: Dan Murphy <[email protected]>
> ---
>
> v2 - Changed the mix and module files to a single "color" file, added the LP5030
> and LP5036 register mapping, added ABI documentation, updated the parsing of
> DT and led sources to match DT, renamed driver to leds-lp50xx.c - https://lore.kernel.org/patchwork/patch/1026515/
>
> Documentation/leds/leds-lp50xx.txt | 36 ++
> drivers/leds/Kconfig | 7 +
> drivers/leds/Makefile | 1 +
> drivers/leds/leds-lp50xx.c | 754 +++++++++++++++++++++++++++++
> 4 files changed, 798 insertions(+)
> create mode 100644 Documentation/leds/leds-lp50xx.txt
> create mode 100644 drivers/leds/leds-lp50xx.c
>
> diff --git a/Documentation/leds/leds-lp50xx.txt b/Documentation/leds/leds-lp50xx.txt
Please move it to
Documentation/ABI/testing/sysfs-class-led-driver-lp50xx
and use standard ABI documentation format.
> new file mode 100644
> index 000000000000..8b1b01dfdd22
> --- /dev/null
> +++ b/Documentation/leds/leds-lp50xx.txt
> @@ -0,0 +1,36 @@
> +LP5018/LP5024/LP5030/LP5036 Common Driver
> +=================================================
> +
> +Authors: Dan Murphy <[email protected]>
> +
> +Description
> +-----------
> +The LP50XX RGB LED drivers have the ability to group multiple RGB cluster
> +LEDs into a single group for simultaneous control or expose single RGB cluster
> +for control. This device exposes different register interfaces to control
> +the cluster brightness as well as the individual RGB LEDs color intensity.
> +
> +RGB Cluster Color Control
> +-------------------------
> +The LP50xx driver will expose a file called "color" for each LED class instance
> +defined. This file will accept a 24-bit RGB value in which the the color of the
> +RGB LEDs will be set.
> +
> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
> +XX - Do not care ignored by the driver
> +RR - is the 8 bit Red LED value
> +GG - is the 8 bit Green LED value
> +BB - is the 8 bit Blue LED value
> +
> +Example:
> +LED module output 4 of the LP5024 will be a yellow color:
> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
> +
> +LED module output 4 of the LP5024 will be dimmed 50%:
> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
> +
> +LED banked RGBs of the LP5036 will be a white color:
> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
This part with example cans remain in Documentation/leds if you like.
> +
> +LED banked RGBs of the LP50364 will be dimmed 50%:
> +echo 0x80 > /sys/class/leds/lp5036\:led_banked/brightness
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index a72f97fca57b..5f413445a667 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -326,6 +326,13 @@ config LEDS_LP3952
> To compile this driver as a module, choose M here: the
> module will be called leds-lp3952.
>
> +config LEDS_LP50XX
> + tristate "LED Support for TI LP5036/30/24/18 LED driver chip"
> + depends on LEDS_CLASS && REGMAP_I2C
> + help
> + If you say yes here you get support for the Texas Instruments
> + LP5036, LP5030, LP5024 and LP5018 LED driver.
> +
> config LEDS_LP55XX_COMMON
> tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
> depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index 4c1b0054f379..852eff0b773f 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
> obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
> obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
> obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o
> +obj-$(CONFIG_LEDS_LP50XX) += leds-lp50xx.o
> obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o
> obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
> obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
> diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
> new file mode 100644
> index 000000000000..41bb2e0129c8
> --- /dev/null
> +++ b/drivers/leds/leds-lp50xx.c
> @@ -0,0 +1,754 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* TI LP50XX LED chip family driver
> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
> + */
Let's use uniform "//" comment style here.
> +#include <linux/gpio/consumer.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +#include <uapi/linux/uleds.h>
> +
> +#define LP50XX_DEV_CFG0 0x00
> +#define LP50XX_DEV_CFG1 0x01
> +#define LP50XX_LED_CFG0 0x02
> +
> +/* LP5018 and LP5024 registers */
> +#define LP5024_BNK_BRT 0x03
> +#define LP5024_BNKA_CLR 0x04
> +#define LP5024_BNKB_CLR 0x05
> +#define LP5024_BNKC_CLR 0x06
> +#define LP5024_LED0_BRT 0x07
> +#define LP5024_LED1_BRT 0x08
> +#define LP5024_LED2_BRT 0x09
> +#define LP5024_LED3_BRT 0x0a
> +#define LP5024_LED4_BRT 0x0b
> +#define LP5024_LED5_BRT 0x0c
> +#define LP5024_LED6_BRT 0x0d
> +#define LP5024_LED7_BRT 0x0e
> +
> +#define LP5024_OUT0_CLR 0x0f
> +#define LP5024_OUT1_CLR 0x10
> +#define LP5024_OUT2_CLR 0x11
> +#define LP5024_OUT3_CLR 0x12
> +#define LP5024_OUT4_CLR 0x13
> +#define LP5024_OUT5_CLR 0x14
> +#define LP5024_OUT6_CLR 0x15
> +#define LP5024_OUT7_CLR 0x16
> +#define LP5024_OUT8_CLR 0x17
> +#define LP5024_OUT9_CLR 0x18
> +#define LP5024_OUT10_CLR 0x19
> +#define LP5024_OUT11_CLR 0x1a
> +#define LP5024_OUT12_CLR 0x1b
> +#define LP5024_OUT13_CLR 0x1c
> +#define LP5024_OUT14_CLR 0x1d
> +#define LP5024_OUT15_CLR 0x1e
> +#define LP5024_OUT16_CLR 0x1f
> +#define LP5024_OUT17_CLR 0x20
> +#define LP5024_OUT18_CLR 0x21
> +#define LP5024_OUT19_CLR 0x22
> +#define LP5024_OUT20_CLR 0x23
> +#define LP5024_OUT21_CLR 0x24
> +#define LP5024_OUT22_CLR 0x25
> +#define LP5024_OUT23_CLR 0x26
> +#define LP5024_RESET 0x27
> +
> +/* LP5030 and LP5036 registers */
> +#define LP5036_LED_CFG1 0x03
> +#define LP5036_BNK_BRT 0x04
> +#define LP5036_BNKA_CLR 0x05
> +#define LP5036_BNKB_CLR 0x06
> +#define LP5036_BNKC_CLR 0x07
> +#define LP5036_LED0_BRT 0x08
> +#define LP5036_LED1_BRT 0x09
> +#define LP5036_LED2_BRT 0x0a
> +#define LP5036_LED3_BRT 0x0b
> +#define LP5036_LED4_BRT 0x0c
> +#define LP5036_LED5_BRT 0x0d
> +#define LP5036_LED6_BRT 0x0e
> +#define LP5036_LED7_BRT 0x0f
> +#define LP5036_LED8_BRT 0x10
> +#define LP5036_LED9_BRT 0x11
> +#define LP5036_LED10_BRT 0x12
> +#define LP5036_LED11_BRT 0x13
> +
> +#define LP5036_OUT0_CLR 0x14
> +#define LP5036_OUT1_CLR 0x15
> +#define LP5036_OUT2_CLR 0x16
> +#define LP5036_OUT3_CLR 0x17
> +#define LP5036_OUT4_CLR 0x18
> +#define LP5036_OUT5_CLR 0x19
> +#define LP5036_OUT6_CLR 0x1a
> +#define LP5036_OUT7_CLR 0x1b
> +#define LP5036_OUT8_CLR 0x1c
> +#define LP5036_OUT9_CLR 0x1d
> +#define LP5036_OUT10_CLR 0x1e
> +#define LP5036_OUT11_CLR 0x1f
> +#define LP5036_OUT12_CLR 0x20
> +#define LP5036_OUT13_CLR 0x21
> +#define LP5036_OUT14_CLR 0x22
> +#define LP5036_OUT15_CLR 0x23
> +#define LP5036_OUT16_CLR 0x24
> +#define LP5036_OUT17_CLR 0x25
> +#define LP5036_OUT18_CLR 0x26
> +#define LP5036_OUT19_CLR 0x27
> +#define LP5036_OUT20_CLR 0x28
> +#define LP5036_OUT21_CLR 0x29
> +#define LP5036_OUT22_CLR 0x2a
> +#define LP5036_OUT23_CLR 0x2b
> +#define LP5036_OUT24_CLR 0x2c
> +#define LP5036_OUT25_CLR 0x2d
> +#define LP5036_OUT26_CLR 0x2e
> +#define LP5036_OUT27_CLR 0x2f
> +#define LP5036_OUT28_CLR 0x30
> +#define LP5036_OUT29_CLR 0x31
> +#define LP5036_OUT30_CLR 0x32
> +#define LP5036_OUT31_CLR 0x33
> +#define LP5036_OUT32_CLR 0x34
> +#define LP5036_OUT33_CLR 0x35
> +#define LP5036_OUT34_CLR 0x36
> +#define LP5036_OUT35_CLR 0x37
> +#define LP5036_RESET 0x38
> +
> +#define LP50XX_SW_RESET 0xff
> +
> +#define LP50XX_CHIP_EN BIT(6)
> +
> +#define LP5018_MAX_LED_STRINGS 6
> +#define LP5024_MAX_LED_STRINGS 8
> +#define LP5030_MAX_LED_STRINGS 10
> +#define LP5036_MAX_LED_STRINGS 12
> +
> +enum lp50xx_model {
> + LP5018,
> + LP5024,
> + LP5030,
> + LP5036,
> +};
> +
> +struct lp50xx_led {
> + u32 led_strings[LP5036_MAX_LED_STRINGS];
It is possible to have only one bank, so this can be a property
of struct lp50xx. Moreover, it doesn't need to be an array,
but should be:
unsigned long bank_modules;
Then you will be able to use bitops on it, where bit position will
refer to the id of RGB LED module assigned to the bank.
> + char label[LED_MAX_NAME_SIZE];
> + struct led_classdev led_dev;
> + struct lp50xx *priv;
> + int led_number;
> + u8 ctrl_bank_enabled;
> +};
> +
> +/**
> + * struct lp50xx -
> + * @enable_gpio: Hardware enable gpio
> + * @regulator: LED supply regulator pointer
> + * @client: Pointer to the I2C client
> + * @regmap: Devices register map
> + * @dev: Pointer to the devices device struct
> + * @lock: Lock for reading/writing the device
> + * @model_id: ID of the device
> + * @leds: Array of LED strings
Please don't use capital letters for property description.
Still, some of the properties below remain undocumented.
> + */
> +struct lp50xx {
> + struct gpio_desc *enable_gpio;
> + struct regulator *regulator;
> + struct i2c_client *client;
> + struct regmap *regmap;
> + struct device *dev;
> + struct mutex lock;
> + enum lp50xx_model model_id;
> + int max_leds;
> + int num_of_leds;
> +
> + u8 led_brightness0_reg;
> + u8 mix_out0_reg;
> + u8 bank_brt_reg;
> + u8 bank_mix_reg;
> + u8 reset_reg;
> +
> + /* This needs to be at the end of the struct */
> + struct lp50xx_led leds[];
> +};
> +
> +static const struct reg_default lp5024_reg_defs[] = {
> + {LP50XX_DEV_CFG0, 0x0},
> + {LP50XX_DEV_CFG1, 0x3c},
> + {LP50XX_LED_CFG0, 0x0},
> + {LP5024_BNK_BRT, 0xff},
> + {LP5024_BNKA_CLR, 0x0f},
> + {LP5024_BNKB_CLR, 0x0f},
> + {LP5024_BNKC_CLR, 0x0f},
> + {LP5024_LED0_BRT, 0x0f},
> + {LP5024_LED1_BRT, 0xff},
> + {LP5024_LED2_BRT, 0xff},
> + {LP5024_LED3_BRT, 0xff},
> + {LP5024_LED4_BRT, 0xff},
> + {LP5024_LED5_BRT, 0xff},
> + {LP5024_LED6_BRT, 0xff},
> + {LP5024_LED7_BRT, 0xff},
> + {LP5024_OUT0_CLR, 0x0f},
> + {LP5024_OUT1_CLR, 0x00},
> + {LP5024_OUT2_CLR, 0x00},
> + {LP5024_OUT3_CLR, 0x00},
> + {LP5024_OUT4_CLR, 0x00},
> + {LP5024_OUT5_CLR, 0x00},
> + {LP5024_OUT6_CLR, 0x00},
> + {LP5024_OUT7_CLR, 0x00},
> + {LP5024_OUT8_CLR, 0x00},
> + {LP5024_OUT9_CLR, 0x00},
> + {LP5024_OUT10_CLR, 0x00},
> + {LP5024_OUT11_CLR, 0x00},
> + {LP5024_OUT12_CLR, 0x00},
> + {LP5024_OUT13_CLR, 0x00},
> + {LP5024_OUT14_CLR, 0x00},
> + {LP5024_OUT15_CLR, 0x00},
> + {LP5024_OUT16_CLR, 0x00},
> + {LP5024_OUT17_CLR, 0x00},
> + {LP5024_OUT18_CLR, 0x00},
> + {LP5024_OUT19_CLR, 0x00},
> + {LP5024_OUT20_CLR, 0x00},
> + {LP5024_OUT21_CLR, 0x00},
> + {LP5024_OUT22_CLR, 0x00},
> + {LP5024_OUT23_CLR, 0x00},
> + {LP5024_RESET, 0x00}
> +};
> +
> +static const struct reg_default lp5036_reg_defs[] = {
> + {LP50XX_DEV_CFG0, 0x0},
> + {LP50XX_DEV_CFG1, 0x3c},
> + {LP50XX_LED_CFG0, 0x0},
> + {LP5036_LED_CFG1, 0x0},
> + {LP5036_BNK_BRT, 0xff},
> + {LP5036_BNKA_CLR, 0x0f},
> + {LP5036_BNKB_CLR, 0x0f},
> + {LP5036_BNKC_CLR, 0x0f},
> + {LP5036_LED0_BRT, 0x0f},
> + {LP5036_LED1_BRT, 0xff},
> + {LP5036_LED2_BRT, 0xff},
> + {LP5036_LED3_BRT, 0xff},
> + {LP5036_LED4_BRT, 0xff},
> + {LP5036_LED5_BRT, 0xff},
> + {LP5036_LED6_BRT, 0xff},
> + {LP5036_LED7_BRT, 0xff},
> + {LP5036_OUT0_CLR, 0x0f},
> + {LP5036_OUT1_CLR, 0x00},
> + {LP5036_OUT2_CLR, 0x00},
> + {LP5036_OUT3_CLR, 0x00},
> + {LP5036_OUT4_CLR, 0x00},
> + {LP5036_OUT5_CLR, 0x00},
> + {LP5036_OUT6_CLR, 0x00},
> + {LP5036_OUT7_CLR, 0x00},
> + {LP5036_OUT8_CLR, 0x00},
> + {LP5036_OUT9_CLR, 0x00},
> + {LP5036_OUT10_CLR, 0x00},
> + {LP5036_OUT11_CLR, 0x00},
> + {LP5036_OUT12_CLR, 0x00},
> + {LP5036_OUT13_CLR, 0x00},
> + {LP5036_OUT14_CLR, 0x00},
> + {LP5036_OUT15_CLR, 0x00},
> + {LP5036_OUT16_CLR, 0x00},
> + {LP5036_OUT17_CLR, 0x00},
> + {LP5036_OUT18_CLR, 0x00},
> + {LP5036_OUT19_CLR, 0x00},
> + {LP5036_OUT20_CLR, 0x00},
> + {LP5036_OUT21_CLR, 0x00},
> + {LP5036_OUT22_CLR, 0x00},
> + {LP5036_OUT23_CLR, 0x00},
> + {LP5036_OUT24_CLR, 0x00},
> + {LP5036_OUT25_CLR, 0x00},
> + {LP5036_OUT26_CLR, 0x00},
> + {LP5036_OUT27_CLR, 0x00},
> + {LP5036_OUT28_CLR, 0x00},
> + {LP5036_OUT29_CLR, 0x00},
> + {LP5036_OUT30_CLR, 0x00},
> + {LP5036_OUT31_CLR, 0x00},
> + {LP5036_OUT32_CLR, 0x00},
> + {LP5036_OUT33_CLR, 0x00},
> + {LP5036_OUT34_CLR, 0x00},
> + {LP5036_OUT35_CLR, 0x00},
> + {LP5036_RESET, 0x00}
> +};
> +
> +static const struct regmap_config lp5024_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .max_register = LP5024_RESET,
> + .reg_defaults = lp5024_reg_defs,
> + .num_reg_defaults = ARRAY_SIZE(lp5024_reg_defs),
> + .cache_type = REGCACHE_RBTREE,
> +};
> +
> +static const struct regmap_config lp5036_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +
> + .max_register = LP5036_RESET,
> + .reg_defaults = lp5036_reg_defs,
> + .num_reg_defaults = ARRAY_SIZE(lp5036_reg_defs),
> + .cache_type = REGCACHE_RBTREE,
> +};
> +
> +static ssize_t color_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
> + led_dev);
> + struct lp50xx *priv = led->priv;
> + unsigned int red_val, green_val, blue_val;
> + u8 red_reg, green_reg, blue_reg;
> + u32 mix_value = 0;
> + u8 led_offset;
> + int ret;
> +
> + if (led->ctrl_bank_enabled) {
> + red_reg = priv->bank_mix_reg;
> + green_reg = priv->bank_mix_reg + 1;
> + blue_reg = priv->bank_mix_reg + 2;
> + } else {
> + led_offset = (led->led_number * 3);
> + red_reg = priv->mix_out0_reg + led_offset;
> + green_reg = priv->mix_out0_reg + led_offset + 1;
> + blue_reg = priv->mix_out0_reg + led_offset + 2;
> + }
> +
> + ret = regmap_read(priv->regmap, red_reg, &red_val);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot read LED value\n");
> + goto out;
> + }
> +
> + ret = regmap_read(priv->regmap, green_reg, &green_val);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot read LED value\n");
> + goto out;
> + }
> +
> + ret = regmap_read(priv->regmap, blue_reg, &blue_val);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot read LED value\n");
> + goto out;
> + }
> +
> + mix_value = (red_val << 16 | green_val << 8 | blue_val);
> +
> +out:
> + return scnprintf(buf, PAGE_SIZE, "0x%X\n", mix_value);
> +}
> +
> +static ssize_t color_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t size)
> +{
> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
> + led_dev);
> + struct lp50xx *priv = led->priv;
> + u8 led_offset;
> + unsigned long mix_value;
> + u8 red_reg, green_reg, blue_reg;
> + u8 red_val, green_val, blue_val;
> + int ret;
> +
> + ret = kstrtoul(buf, 0, &mix_value);
> + if (ret)
> + return ret;
> +
> + if (led->ctrl_bank_enabled) {
> + red_reg = priv->bank_mix_reg;
> + green_reg = priv->bank_mix_reg + 1;
> + blue_reg = priv->bank_mix_reg + 2;
> + } else {
> + led_offset = (led->led_number * 3);
> + red_reg = priv->mix_out0_reg + led_offset;
> + green_reg = priv->mix_out0_reg + led_offset + 1;
> + blue_reg = priv->mix_out0_reg + led_offset + 2;
> + }
> +
> + red_val = (mix_value & 0xff0000) >> 16;
> + green_val = (mix_value & 0xff00) >> 8;
> + blue_val = (mix_value & 0xff);
I've been rather thinking about space separated list of decimal
"red green blue" values, but maybe this way it will be less
controversial. Let's if there will be other opinions.
> +
> + ret = regmap_write(priv->regmap, red_reg, red_val);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot write LED value\n");
> + goto out;
> + }
> +
> + ret = regmap_write(priv->regmap, green_reg, green_val);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot write LED value\n");
> + goto out;
> + }
> +
> + ret = regmap_write(priv->regmap, blue_reg, blue_val);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot write LED value\n");
> + goto out;
> + }
> +out:
> + return size;
> +}
> +
> +static DEVICE_ATTR_RW(color);
> +
> +static struct attribute *lp50xx_led_color_attrs[] = {
> + &dev_attr_color.attr,
> + NULL
> +};
> +ATTRIBUTE_GROUPS(lp50xx_led_color);
> +
> +static int lp50xx_brightness_set(struct led_classdev *led_cdev,
> + enum led_brightness brt_val)
> +{
> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
> + led_dev);
> + int ret = 0;
> + u8 reg_val;
> +
> + mutex_lock(&led->priv->lock);
> +
> + if (led->ctrl_bank_enabled)
> + reg_val = led->priv->bank_brt_reg;
> + else
> + reg_val = led->priv->led_brightness0_reg + led->led_number;
> +
> + ret = regmap_write(led->priv->regmap, reg_val, brt_val);
> +
> + mutex_unlock(&led->priv->lock);
> +
> + return ret;
> +}
> +
> +static enum led_brightness lp50xx_brightness_get(struct led_classdev *led_cdev)
> +{
> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
> + led_dev);
> + unsigned int brt_val;
> + u8 reg_val;
> + int ret;
> +
> + mutex_lock(&led->priv->lock);
> +
> + if (led->ctrl_bank_enabled)
> + reg_val = led->priv->bank_brt_reg;
> + else
> + reg_val = led->priv->led_brightness0_reg + led->led_number;
> +
> + ret = regmap_read(led->priv->regmap, reg_val, &brt_val);
> +
> + mutex_unlock(&led->priv->lock);
> +
> + return brt_val;
> +}
> +
> +static void lp50xx_set_led_values(struct lp50xx *priv)
> +{
> + if (priv->model_id == LP5018 || priv->model_id == LP5024) {
> + priv->led_brightness0_reg = LP5024_LED0_BRT;
> + priv->mix_out0_reg = LP5024_OUT0_CLR;
> + priv->bank_brt_reg = LP5024_BNK_BRT;
> + priv->bank_mix_reg = LP5024_BNKA_CLR;
> + priv->reset_reg = LP5024_RESET;
> + } else {
> + priv->led_brightness0_reg = LP5036_LED0_BRT;
> + priv->mix_out0_reg = LP5036_OUT0_CLR;
> + priv->bank_brt_reg = LP5036_BNK_BRT;
> + priv->bank_mix_reg = LP5036_BNKA_CLR;
> + priv->reset_reg = LP5036_RESET;
> + }
> +}
> +
> +static int lp50xx_set_banks(struct lp50xx *priv)
> +{
> + struct lp50xx_led *led;
> + u8 led_ctrl_enable = 0;
> + u8 led1_ctrl_enable = 0;
> + u8 ctrl_ext = 0;
> + int i, j;
> + int ret;
> +
> + for (i = 0; i <= priv->num_of_leds; i++) {
> + led = &priv->leds[i];
> + if (!led->ctrl_bank_enabled)
> + continue;
> +
> + for (j = 0; j <= priv->max_leds - 1; j++) {
> + if (led->led_strings[j] > (LP5024_MAX_LED_STRINGS - 1)) {
> + ctrl_ext = led->led_strings[j] - LP5024_MAX_LED_STRINGS;
> + led1_ctrl_enable |= (1 << ctrl_ext);
> + } else {
> + led_ctrl_enable |= (1 << led->led_strings[j]);
> + }
> + }
> + }
With centralized bank_modules flags it should look simpler.
> +
> + ret = regmap_write(priv->regmap, LP50XX_LED_CFG0, led_ctrl_enable);
> +
> + if (led1_ctrl_enable)
> + ret = regmap_write(priv->regmap, LP5036_LED_CFG1,
> + led1_ctrl_enable);
> +
> + return ret;
> +}
> +
> +static int lp50xx_init(struct lp50xx *priv)
> +{
> + int ret;
> +
> + lp50xx_set_led_values(priv);
> +
> + if (priv->enable_gpio) {
> + gpiod_direction_output(priv->enable_gpio, 1);
> + } else {
> + ret = regmap_write(priv->regmap, priv->reset_reg,
> + LP50XX_SW_RESET);
> + if (ret) {
> + dev_err(&priv->client->dev,
> + "Cannot reset the device\n");
> + goto out;
> + }
> + }
> +
> + ret = lp50xx_set_banks(priv);
> + if (ret) {
> + dev_err(&priv->client->dev, "Cannot set the banks\n");
> + goto out;
> + }
> +
> + ret = regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
> + if (ret)
> + dev_err(&priv->client->dev, "Cannot write ctrl enable\n");
> +
> +out:
> + return ret;
> +}
> +
> +static int lp50xx_probe_dt(struct lp50xx *priv)
> +{
> + struct fwnode_handle *child = NULL;
> + struct lp50xx_led *led;
> + int control_bank_defined = 0;
> + const char *name;
> + int led_number;
> + size_t i = 0;
> + int ret;
> +
> + priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
> + "enable", GPIOD_OUT_LOW);
> + if (IS_ERR(priv->enable_gpio)) {
> + ret = PTR_ERR(priv->enable_gpio);
> + dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
> + ret);
> + return ret;
> + }
> +
> + priv->regulator = devm_regulator_get(&priv->client->dev, "vled");
> + if (IS_ERR(priv->regulator))
> + priv->regulator = NULL;
> +
> + if (priv->model_id == LP5018)
> + priv->max_leds = LP5018_MAX_LED_STRINGS;
> + else if (priv->model_id == LP5024)
> + priv->max_leds = LP5024_MAX_LED_STRINGS;
> + else if (priv->model_id == LP5030)
> + priv->max_leds = LP5030_MAX_LED_STRINGS;
> + else
> + priv->max_leds = LP5036_MAX_LED_STRINGS;
Let's change STRINGS to MODULEs.
> +
> + device_for_each_child_node(&priv->client->dev, child) {
> + led = &priv->leds[i];
> +
> + if (fwnode_property_present(child, "ti,led-bank")) {
> + led->ctrl_bank_enabled = 1;
> + if (!control_bank_defined)
> + control_bank_defined = 1;
> + else {
> + dev_err(&priv->client->dev,
> + "ti,led-bank defined twice\n");
> + fwnode_handle_put(child);
> + goto child_out;
> + }
> + } else {
> + led->ctrl_bank_enabled = 0;
> + }
Any bit set in bank_modules will signify that bank is defined
and enabled.
> + if (led->ctrl_bank_enabled) {
> + ret = fwnode_property_read_u32_array(child,
> + "ti,led-bank",
> + NULL, 0);
> + ret = fwnode_property_read_u32_array(child,
> + "ti,led-bank",
> + led->led_strings,
> + ret);
> +
> + led->led_number = led->led_strings[0];
> +
> + } else {
> + ret = fwnode_property_read_u32(child, "ti,led-module",
> + &led_number);
> +
> + led->led_number = led_number;
> + }
> + if (ret) {
> + dev_err(&priv->client->dev,
> + "led sourcing property missing\n");
> + fwnode_handle_put(child);
> + goto child_out;
> + }
> +
> + if (led_number > priv->max_leds) {
> + dev_err(&priv->client->dev,
> + "led-sources property is invalid\n");
> + ret = -EINVAL;
> + fwnode_handle_put(child);
> + goto child_out;
> + }
> +
> + ret = fwnode_property_read_string(child, "label", &name);
> + if (ret)
> + snprintf(led->label, sizeof(led->label),
> + "%s::", priv->client->name);
> + else
> + snprintf(led->label, sizeof(led->label),
> + "%s:%s", priv->client->name, name);
> +
> + fwnode_property_read_string(child, "linux,default-trigger",
> + &led->led_dev.default_trigger);
> +
> + led->priv = priv;
> + led->led_dev.name = led->label;
> + led->led_dev.brightness_set_blocking = lp50xx_brightness_set;
> + led->led_dev.brightness_get = lp50xx_brightness_get;
> + led->led_dev.groups = lp50xx_led_color_groups;
> +
> + ret = devm_led_classdev_register(&priv->client->dev,
> + &led->led_dev);
> + if (ret) {
> + dev_err(&priv->client->dev, "led register err: %d\n",
> + ret);
> + fwnode_handle_put(child);
> + goto child_out;
> + }
> + i++;
> + }
> + priv->num_of_leds = i;
> +
> +child_out:
> + return ret;
> +}
> +
> +static int lp50xx_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct lp50xx *led;
> + int count;
> + int ret;
> +
> + count = device_get_child_node_count(&client->dev);
> + if (!count) {
> + dev_err(&client->dev, "LEDs are not defined in device tree!");
> + return -ENODEV;
> + }
> +
> + led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
> + GFP_KERNEL);
> + if (!led)
> + return -ENOMEM;
> +
> + mutex_init(&led->lock);
> + led->client = client;
> + led->dev = &client->dev;
> + led->model_id = id->driver_data;
> + i2c_set_clientdata(client, led);
> +
> + if (led->model_id == LP5018 || led->model_id == LP5024)
> + led->regmap = devm_regmap_init_i2c(client,
> + &lp5024_regmap_config);
> + else
> + led->regmap = devm_regmap_init_i2c(client,
> + &lp5036_regmap_config);
> +
> + if (IS_ERR(led->regmap)) {
> + ret = PTR_ERR(led->regmap);
> + dev_err(&client->dev, "Failed to allocate register map: %d\n",
> + ret);
> + return ret;
> + }
> +
> + ret = lp50xx_probe_dt(led);
> + if (ret)
> + return ret;
> +
> + ret = lp50xx_init(led);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int lp50xx_remove(struct i2c_client *client)
> +{
> + struct lp50xx *led = i2c_get_clientdata(client);
> + int ret;
> +
> + ret = regmap_update_bits(led->regmap, LP50XX_DEV_CFG0,
> + LP50XX_CHIP_EN, 0);
> + if (ret) {
> + dev_err(&led->client->dev, "Failed to disable regulator\n");
> + return ret;
> + }
> +
> + if (led->enable_gpio)
> + gpiod_direction_output(led->enable_gpio, 0);
> +
> + if (led->regulator) {
> + ret = regulator_disable(led->regulator);
> + if (ret)
> + dev_err(&led->client->dev,
> + "Failed to disable regulator\n");
> + }
> +
> + mutex_destroy(&led->lock);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id lp50xx_id[] = {
> + { "lp5018", LP5018 },
> + { "lp5024", LP5024 },
> + { "lp5030", LP5030 },
> + { "lp5036", LP5036 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, lp50xx_id);
> +
> +static const struct of_device_id of_lp50xx_leds_match[] = {
> + { .compatible = "ti,lp5018", },
> + { .compatible = "ti,lp5024", },
> + { .compatible = "ti,lp5030", },
> + { .compatible = "ti,lp5036", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, of_lp50xx_leds_match);
> +
> +static struct i2c_driver lp50xx_driver = {
> + .driver = {
> + .name = "lp50xx",
> + .of_match_table = of_lp50xx_leds_match,
> + },
> + .probe = lp50xx_probe,
> + .remove = lp50xx_remove,
> + .id_table = lp50xx_id,
> +};
> +module_i2c_driver(lp50xx_driver);
> +
> +MODULE_DESCRIPTION("Texas Instruments LP5024 LED driver");
> +MODULE_AUTHOR("Dan Murphy <[email protected]>");
> +MODULE_LICENSE("GPL v2");
>
--
Best regards,
Jacek Anaszewski
Hi!
> >+The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
> >+XX - Do not care ignored by the driver
> >+RR - is the 8 bit Red LED value
> >+GG - is the 8 bit Green LED value
> >+BB - is the 8 bit Blue LED value
> >+
> >+Example:
> >+LED module output 4 of the LP5024 will be a yellow color:
> >+echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
> >+
> >+LED module output 4 of the LP5024 will be dimmed 50%:
> >+echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
> >+
> >+LED banked RGBs of the LP5036 will be a white color:
> >+echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>
> This part with example cans remain in Documentation/leds if you
> >like.
Does it actually work like that on hardware?
Is it supposed to support "normal" RGB colors as seen on monitors?
Because 100% PWM on all channels does not result in white on hardware
I have.
> >+ } else {
> >+ led_offset = (led->led_number * 3);
> >+ red_reg = priv->mix_out0_reg + led_offset;
> >+ green_reg = priv->mix_out0_reg + led_offset + 1;
> >+ blue_reg = priv->mix_out0_reg + led_offset + 2;
> >+ }
> >+
> >+ red_val = (mix_value & 0xff0000) >> 16;
> >+ green_val = (mix_value & 0xff00) >> 8;
> >+ blue_val = (mix_value & 0xff);
>
> I've been rather thinking about space separated list of decimal
> "red green blue" values, but maybe this way it will be less
> controversial. Let's if there will be other opinions.
We support maximum brightness > 255, so space separated is certainly
better option than this.
But...
I believe we should have a reasonable design before we do something
like this. There's no guarantee someone will not use lp50xx with just
the white LEDs for example. How will this work? Plus existing hardware
already uses three separate LEDs for RGB LED. Why not provide same
interface?
(Oh and don't try to say "sysfs is slow", without numbers).
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hello
Pavel Thanks for the review it is always good to have your comments.
On 1/15/19 4:22 PM, Pavel Machek wrote:
> Hi!
>
>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>> +XX - Do not care ignored by the driver
>>> +RR - is the 8 bit Red LED value
>>> +GG - is the 8 bit Green LED value
>>> +BB - is the 8 bit Blue LED value
>>> +
>>> +Example:
>>> +LED module output 4 of the LP5024 will be a yellow color:
>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>> +
>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>> +
>>> +LED banked RGBs of the LP5036 will be a white color:
>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>
>> This part with example cans remain in Documentation/leds if you
>>> like.
>
> Does it actually work like that on hardware?
What?
>
> Is it supposed to support "normal" RGB colors as seen on monitors?
Monitors are not an application for this part.
Data sheet indicates these are the target applications
LED Lighting, Indicator Lights, and Fun Lights for:
Smart Speaker
Smart Home Appliances
Video Doorbell
Electric Smart Lock
Smoke Detector
Set-Top Box
Smart Router
Handheld Devices
ie Echo, Ring
>
> Because 100% PWM on all channels does not result in white on hardware
> I have.
>
I don't know I am usually blinded by the light and have no diffuser over
the LEDs to disperse the light so when I look I see all 3 colors.
>>> + } else {
>>> + led_offset = (led->led_number * 3);
>>> + red_reg = priv->mix_out0_reg + led_offset;
>>> + green_reg = priv->mix_out0_reg + led_offset + 1;
>>> + blue_reg = priv->mix_out0_reg + led_offset + 2;
>>> + }
>>> +
>>> + red_val = (mix_value & 0xff0000) >> 16;
>>> + green_val = (mix_value & 0xff00) >> 8;
>>> + blue_val = (mix_value & 0xff);
>>
>> I've been rather thinking about space separated list of decimal
>> "red green blue" values, but maybe this way it will be less
>> controversial. Let's if there will be other opinions.
>
> We support maximum brightness > 255, so space separated is certainly
> better option than this.
>
I was using the HSL picker URL that Jacek sent to me that gave me that idea
And there were comments about presenting a single file to control the color.
But that was probably lost in the noise of the email chain.
https://lore.kernel.org/patchwork/patch/1026514/
"Apart of that, I've been also mulling over if we shouldn't go for single
"color" sysfs file for setting r,g,b components at one go."
http://hslpicker.com/#e6e200
> But...
>
> I believe we should have a reasonable design before we do something
> like this. There's no guarantee someone will not use lp50xx with just
> the white LEDs for example. How will this work? Plus existing hardware
> already uses three separate LEDs for RGB LED. Why not provide same
> interface?
>
Which existing hardware? Are they using this part?
<rant>
Why are we delaying getting the RGB framework or HSV in?
I would rather design against something you want instead of having
everyone complain about every implementation I post.
</rant>
It is not a normal RGB driver. The device collates the individual RGB
clusters into a single brightness register and you can modify the intensity of the individual
LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
set in the individual registers.
And the RGB clusters can be banked into a single RGB cluster group to
present a single register to control numerous RGB LED clusters.
> (Oh and don't try to say "sysfs is slow", without numbers).
Never said sysfs was slow.
Dan
>
> Thanks,
> Pavel
>
--
------------------
Dan Murphy
Hi!
> On 1/15/19 4:22 PM, Pavel Machek wrote:
> > Hi!
> >
> >>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
> >>> +XX - Do not care ignored by the driver
> >>> +RR - is the 8 bit Red LED value
> >>> +GG - is the 8 bit Green LED value
> >>> +BB - is the 8 bit Blue LED value
> >>> +
> >>> +Example:
> >>> +LED module output 4 of the LP5024 will be a yellow color:
> >>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
> >>> +
> >>> +LED module output 4 of the LP5024 will be dimmed 50%:
> >>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
> >>> +
> >>> +LED banked RGBs of the LP5036 will be a white color:
> >>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
> >>
> >> This part with example cans remain in Documentation/leds if you
> >>> like.
> >
> > Does it actually work like that on hardware?
>
> What?
If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
does it actually produce white? With all the different RGB modules
manufacturers can use with lp5024P?
If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
it actually produce yellow, with all the different RGB modules
manufacturers can use with lp5024P?
> > Is it supposed to support "normal" RGB colors as seen on monitors?
>
> Monitors are not an application for this part.
You did not answer the question. When you talk about yellow, is it
same yellow the rest of world talks about?
> > Because 100% PWM on all channels does not result in white on hardware
> > I have.
>
> I don't know I am usually blinded by the light and have no diffuser over
> the LEDs to disperse the light so when I look I see all 3 colors.
How can we have useful discussion about colors when you don't see the
colors?
Place a piece of paper over the LEDs....
> > But...
> >
> > I believe we should have a reasonable design before we do something
> > like this. There's no guarantee someone will not use lp50xx with just
> > the white LEDs for example. How will this work? Plus existing hardware
> > already uses three separate LEDs for RGB LED. Why not provide same
> > interface?
>
> Which existing hardware? Are they using this part?
Nokia N900. They are not using this part, but any interface we invent
should work there, too.
> <rant>
> Why are we delaying getting the RGB framework or HSV in?
> I would rather design against something you want instead of having
> everyone complain about every implementation I post.
> </rant>
Because you insist on creating new kernel interfaces, when existing
interfaces work, and are doing that badly.
Because your patches are of lower quality than is acceptable for linux
kernel.
Because you don't seem to be reading the emails.
I sent list of requirements for RGB led support. This does not meet
them.
> It is not a normal RGB driver. The device collates the individual RGB
> clusters into a single brightness register and you can modify the intensity of the individual
> LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
> set in the individual registers.
I understand that. So just set cluster brightness to 255 and you have
normal RGB driver you can control with existing interfaces. You don't
have to use every feature your hardware has.
You did not answer the "what if someone uses this with all white LEDs"
question.
You know what? First, submit driver with similar functionality to
existing RGB drivers, using same interface existing drivers are
using. When that is accepted, we can talk about extending
kernel<->user interfaces.
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hello
On 1/16/19 4:55 AM, Pavel Machek wrote:
> Hi!
>
>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>> Hi!
>>>
>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>> +XX - Do not care ignored by the driver
>>>>> +RR - is the 8 bit Red LED value
>>>>> +GG - is the 8 bit Green LED value
>>>>> +BB - is the 8 bit Blue LED value
>>>>> +
>>>>> +Example:
>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>> +
>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>> +
>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>
>>>> This part with example cans remain in Documentation/leds if you
>>>>> like.
>>>
>>> Does it actually work like that on hardware?
>>
>> What?
>
> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
> does it actually produce white? With all the different RGB modules
> manufacturers can use with lp5024P?
>
> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
> it actually produce yellow, with all the different RGB modules
> manufacturers can use with lp5024P?
>
I believe the answer to the general questions is no for any RGB cluster and driver out there.
Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
But everyone interprets colors differently.
If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
Most probably not.
As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
scales down to the hand helds and smart home applications.
If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
coefficients.
I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
As you indicated in the requirements there is more involved here then just the LED and the values written.
The colors should be close but may not be identical.
A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
light pipe and LED driver technology.
The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
a hardware aspect to the calculation.
>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>
>> Monitors are not an application for this part.
>
> You did not answer the question. When you talk about yellow, is it
> same yellow the rest of world talks about?
>
See above. It is close to what was on my monitor displayed.
>>> Because 100% PWM on all channels does not result in white on hardware
>>> I have.
>>
>> I don't know I am usually blinded by the light and have no diffuser over
>> the LEDs to disperse the light so when I look I see all 3 colors.
>
> How can we have useful discussion about colors when you don't see the
> colors?
>
> Place a piece of paper over the LEDs....
>
Good suggestion for a rough test.
>>> But...
>>>
>>> I believe we should have a reasonable design before we do something
>>> like this. There's no guarantee someone will not use lp50xx with just
>>> the white LEDs for example. How will this work? Plus existing hardware
>>> already uses three separate LEDs for RGB LED. Why not provide same
>>> interface?
>>
>> Which existing hardware? Are they using this part?
>
> Nokia N900. They are not using this part, but any interface we invent
> should work there, too.
>
Yes a common interface would be nice with some sort of hardware tuning coefficient.
>> <rant>
>> Why are we delaying getting the RGB framework or HSV in?
>> I would rather design against something you want instead of having
>> everyone complain about every implementation I post.
>> </rant>
>
> Because you insist on creating new kernel interfaces, when existing
> interfaces work, and are doing that badly.
>
> Because your patches are of lower quality than is acceptable for linux
> kernel.
>
> Because you don't seem to be reading the emails.
>
> I sent list of requirements for RGB led support. This does not meet
> them.
>
Sigh. You did not answer my question.
Your requirements seem to be centered around monitors but that is only one application of the current
RGB LED landscape.
I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
maybe color capabilities but not specific colors.
It was agreed to continue forward with this particular implementation.
At least thats what the email (I apparently did not read) stated.
I need to fix the code to use the space separated value as pointed out and shown by Vesa.
This will map nicely into this device with the color file as what I implemented is in theory
they same code except for the space separated values.
>> It is not a normal RGB driver. The device collates the individual RGB
>> clusters into a single brightness register and you can modify the intensity of the individual
>> LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
>> set in the individual registers.
>
> I understand that. So just set cluster brightness to 255 and you have
> normal RGB driver you can control with existing interfaces. You don't
> have to use every feature your hardware has.
>
The brightness file is available and adjusts the brightness of the RGB cluster.
I am not attempting to implement every feature the device has. But I am attempting to use
the basic features that are available and useful.
> You did not answer the "what if someone uses this with all white LEDs"
> question.
>
Are you asking what if someone places a white LED instead of a RGB on the hardware?
Well then they need to go back and have a review of the data sheet and what they are trying to
achieve. That would be a misapplication of the LED driver itself and something software cannot fix.
But if they do determine they want to control these white LEDs with this device
then they can ignore the "color" file and control the cluster via the brightness file like we
do today. The color file will only change the intensity of the single output (assuming LED module mode)
or the banked output.
If a user wants to place a RGB cluster down on the hardware and have white as the consistent color
well then that is fine as the RGB outputs are all set to 0xff and the intensity of the cluster is
controlled by the brightness file. If they cannot achieve the "white" with the default settings then
on init they can set the color file once to obtain the "white" color and continue to use the brightness
file to control the overall brightness of the cluster.
It was determined in the email chain not to expose a brightness file per output as this device
does not lend itself to that convention.
> You know what? First, submit driver with similar functionality to
> existing RGB drivers, using same interface existing drivers are
> using. When that is accepted, we can talk about extending
> kernel<->user interfaces.
>
I could do that but then there is no way for users to have any other color but "white" with this driver.
That defeats the purpose of the device itself.
This is why I would rather align the interfaces with what is being proposed so the interfaces won't change only
the engine underneath will.
I am not sure if you are aware of this or care but I found this recent blog on this effort:
https://www.phoronix.com/scan.php?page=news_item&px=Linux-RGB-LED-Interface
See some of the comments.
Dan
> Thanks,
> Pavel
>
--
------------------
Dan Murphy
Hi!
..snip. Let me read it and reply when I have a time.
> > You know what? First, submit driver with similar functionality to
> > existing RGB drivers, using same interface existing drivers are
> > using. When that is accepted, we can talk about extending
> > kernel<->user interfaces.
> >
>
> I could do that but then there is no way for users to have any other color but "white" with this driver.
> That defeats the purpose of the device itself.
No, that is not what I meant.
We do have RGB drivers in tree, they just present three separate LEDs
-- red, green and blue. I ask you to do the same for initial
submission.
You'll still be able to set brightness independently on the
red/green/blue LEDs...
> I am not sure if you are aware of this or care but I found this recent blog on this effort:
> https://www.phoronix.com/scan.php?page=news_item&px=Linux-RGB-LED-Interface
> See some of the comments.
I went through the comments quickly, but see nothing really
interesting.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hello
On 1/16/19 4:04 PM, Pavel Machek wrote:
> Hi!
>
> ..snip. Let me read it and reply when I have a time.
>
>>> You know what? First, submit driver with similar functionality to
>>> existing RGB drivers, using same interface existing drivers are
>>> using. When that is accepted, we can talk about extending
>>> kernel<->user interfaces.
>>>
>>
>> I could do that but then there is no way for users to have any other color but "white" with this driver.
>> That defeats the purpose of the device itself.
>
> No, that is not what I meant.
>
> We do have RGB drivers in tree, they just present three separate LEDs
> -- red, green and blue. I ask you to do the same for initial
> submission.
>
For clarification you are asking me to register a LED class per output pin?
If that is not you mean can you point me to an example because looking through the code I see the
lp5562, bd2802 and lp3944 of which none are equivalent to the LP50xx devices. Each one
of those devices have a dedicated register per LED output which makes perfect sense to do what
you are asking.
If it is what you are asking then this was already explained and it was agreed in the email chain to provide
a Class with a "brightness" file that maps to the Master brightness register and
the "color" file that would map to the respective color control register.
These registrations would be per LED Module output and Banked output and not per LED output.
RED LED Color Control Register------| |------| RED LED OUTPUT
Green LED Color Control Register----|--- LED Master Brightness register--|------| Green LED OUTPUT
Blue LED Color Control Register-----| |------| Blue LED OUTPUT
As explained before the Master brightness register has absolute control over the output current
to the LED outputs regardless of the color control setting.
> You'll still be able to set brightness independently on the
> red/green/blue LEDs...
>
But which one would control the overall brightness of the cluster?
Dan
>> I am not sure if you are aware of this or care but I found this recent blog on this effort:
>> https://www.phoronix.com/scan.php?page=news_item&px=Linux-RGB-LED-Interface
>> See some of the comments.
>
> I went through the comments quickly, but see nothing really
> interesting.
>
> Best regards,
>
> Pavel
>
--
------------------
Dan Murphy
Hi!
> >>> You know what? First, submit driver with similar functionality to
> >>> existing RGB drivers, using same interface existing drivers are
> >>> using. When that is accepted, we can talk about extending
> >>> kernel<->user interfaces.
> >>>
> >>
> >> I could do that but then there is no way for users to have any other color but "white" with this driver.
> >> That defeats the purpose of the device itself.
> >
> > No, that is not what I meant.
> >
> > We do have RGB drivers in tree, they just present three separate LEDs
> > -- red, green and blue. I ask you to do the same for initial
> > submission.
> >
>
> For clarification you are asking me to register a LED class per
> output pin?
Yes.
> As explained before the Master brightness register has absolute control over the output current
> to the LED outputs regardless of the color control setting.
>
Yes, just set master brightness to 255 and you can ignore it.
> > You'll still be able to set brightness independently on the
> > red/green/blue LEDs...
> >
>
> But which one would control the overall brightness of the cluster?
You would not have that control in initial version of the patch.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hello
On 1/17/19 4:06 AM, Pavel Machek wrote:
> Hi!
>
>>>>> You know what? First, submit driver with similar functionality to
>>>>> existing RGB drivers, using same interface existing drivers are
>>>>> using. When that is accepted, we can talk about extending
>>>>> kernel<->user interfaces.
>>>>>
>>>>
>>>> I could do that but then there is no way for users to have any other color but "white" with this driver.
>>>> That defeats the purpose of the device itself.
>>>
>>> No, that is not what I meant.
>>>
>>> We do have RGB drivers in tree, they just present three separate LEDs
>>> -- red, green and blue. I ask you to do the same for initial
>>> submission.
>>>
>>
>> For clarification you are asking me to register a LED class per
>> output pin?
>
> Yes.
>
OK I can do that but I would like to get Jacek to align with this as he
suggested creating the code as I submitted based on the review of the
devices data sheet.
LED class registration per LED module or for the single Banked output.
>> As explained before the Master brightness register has absolute control over the output current
>> to the LED outputs regardless of the color control setting.
>>
>
> Yes, just set master brightness to 255 and you can ignore it.
OK Sounds fine. Will just need to do an init that sets the color
register to 0 and brightness to 0 so we don't have a flash.
>
>>> You'll still be able to set brightness independently on the
>>> red/green/blue LEDs...
>>>
>>
>> But which one would control the overall brightness of the cluster?
>
> You would not have that control in initial version of the patch.
>
See above on alignment
Dan
> Pavel
>
--
------------------
Dan Murphy
Hi Dan,
On 1/16/19 7:41 PM, Dan Murphy wrote:
> Hello
>
> On 1/16/19 4:55 AM, Pavel Machek wrote:
>> Hi!
>>
>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>> Hi!
>>>>
>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>> +XX - Do not care ignored by the driver
>>>>>> +RR - is the 8 bit Red LED value
>>>>>> +GG - is the 8 bit Green LED value
>>>>>> +BB - is the 8 bit Blue LED value
>>>>>> +
>>>>>> +Example:
>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>> +
>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>> +
>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>
>>>>> This part with example cans remain in Documentation/leds if you
>>>>>> like.
>>>>
>>>> Does it actually work like that on hardware?
>>>
>>> What?
>>
>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>> does it actually produce white? With all the different RGB modules
>> manufacturers can use with lp5024P?
>>
>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>> it actually produce yellow, with all the different RGB modules
>> manufacturers can use with lp5024P?
>>
>
> I believe the answer to the general questions is no for any RGB cluster and driver out there.
> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
> But everyone interprets colors differently.
>
> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
> Most probably not.
>
> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>
> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
> scales down to the hand helds and smart home applications.
>
> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>
> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
> coefficients.
>
> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
> As you indicated in the requirements there is more involved here then just the LED and the values written.
> The colors should be close but may not be identical.
>
> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
> light pipe and LED driver technology.
> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>
> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
> a hardware aspect to the calculation.
>
>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>
>>> Monitors are not an application for this part.
>>
>> You did not answer the question. When you talk about yellow, is it
>> same yellow the rest of world talks about?
>>
>
> See above. It is close to what was on my monitor displayed.
>
>>>> Because 100% PWM on all channels does not result in white on hardware
>>>> I have.
>>>
>>> I don't know I am usually blinded by the light and have no diffuser over
>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>
>> How can we have useful discussion about colors when you don't see the
>> colors?
>>
>> Place a piece of paper over the LEDs....
>>
>
> Good suggestion for a rough test.
>
>>>> But...
>>>>
>>>> I believe we should have a reasonable design before we do something
>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>> interface?
>>>
>>> Which existing hardware? Are they using this part?
>>
>> Nokia N900. They are not using this part, but any interface we invent
>> should work there, too.
>>
>
> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>
>>> <rant>
>>> Why are we delaying getting the RGB framework or HSV in?
>>> I would rather design against something you want instead of having
>>> everyone complain about every implementation I post.
>>> </rant>
>>
>> Because you insist on creating new kernel interfaces, when existing
>> interfaces work, and are doing that badly.
>>
>> Because your patches are of lower quality than is acceptable for linux
>> kernel.
>>
>> Because you don't seem to be reading the emails.
>>
>> I sent list of requirements for RGB led support. This does not meet
>> them.
>>
>
> Sigh. You did not answer my question.
>
> Your requirements seem to be centered around monitors but that is only one application of the current
> RGB LED landscape.
>
> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
> maybe color capabilities but not specific colors.
Dan, if you have a bandwidth for LED RGB class implementation
then please go ahead. It would be good to compare colors produced
by software HSV->RGB algorithm to what can be achieved with
LEDn_BRIGHTNESS feature.
The requirements for LED RGB class as I would see it:
sysfs interface:
brightness-model: space separated list of available options:
- rgb (default):
- creates color file with "red green blue" decimal values
- creates brightness file
a) for devices with hardware support for adjusting color
intensity it maps to corresponding register
b) for the rest writing any value greater than 0 will result
in setting all color registers to max
- hsv:
- creates color file with "h s v" values - it shall
use software HSV->RGB algorithm for setting color registers
- any other custom color ranges defined in DT, but it can be covered
later
- other options?
Best regards,
Jacek Anaszewski
> It was agreed to continue forward with this particular implementation.
> At least thats what the email (I apparently did not read) stated.
>
> I need to fix the code to use the space separated value as pointed out and shown by Vesa.
> This will map nicely into this device with the color file as what I implemented is in theory
> they same code except for the space separated values.
>
>>> It is not a normal RGB driver. The device collates the individual RGB
>>> clusters into a single brightness register and you can modify the intensity of the individual
>>> LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
>>> set in the individual registers.
>>
>> I understand that. So just set cluster brightness to 255 and you have
>> normal RGB driver you can control with existing interfaces. You don't
>> have to use every feature your hardware has.
>>
>
> The brightness file is available and adjusts the brightness of the RGB cluster.
> I am not attempting to implement every feature the device has. But I am attempting to use
> the basic features that are available and useful.
>
>> You did not answer the "what if someone uses this with all white LEDs"
>> question.
>>
>
> Are you asking what if someone places a white LED instead of a RGB on the hardware?
> Well then they need to go back and have a review of the data sheet and what they are trying to
> achieve. That would be a misapplication of the LED driver itself and something software cannot fix.
>
> But if they do determine they want to control these white LEDs with this device
> then they can ignore the "color" file and control the cluster via the brightness file like we
> do today. The color file will only change the intensity of the single output (assuming LED module mode)
> or the banked output.
>
> If a user wants to place a RGB cluster down on the hardware and have white as the consistent color
> well then that is fine as the RGB outputs are all set to 0xff and the intensity of the cluster is
> controlled by the brightness file. If they cannot achieve the "white" with the default settings then
> on init they can set the color file once to obtain the "white" color and continue to use the brightness
> file to control the overall brightness of the cluster.
>
> It was determined in the email chain not to expose a brightness file per output as this device
> does not lend itself to that convention.
>
>> You know what? First, submit driver with similar functionality to
>> existing RGB drivers, using same interface existing drivers are
>> using. When that is accepted, we can talk about extending
>> kernel<->user interfaces.
>>
>
> I could do that but then there is no way for users to have any other color but "white" with this driver.
> That defeats the purpose of the device itself.
>
> This is why I would rather align the interfaces with what is being proposed so the interfaces won't change only
> the engine underneath will.
>
> I am not sure if you are aware of this or care but I found this recent blog on this effort:
> https://www.phoronix.com/scan.php?page=news_item&px=Linux-RGB-LED-Interface
> See some of the comments.
>
> Dan
>
>> Thanks,
>> Pavel
>>
>
>
On 1/16/19 11:55 AM, Pavel Machek wrote:
> Hi!
>
>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>> Hi!
>>>
>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>> +XX - Do not care ignored by the driver
>>>>> +RR - is the 8 bit Red LED value
>>>>> +GG - is the 8 bit Green LED value
>>>>> +BB - is the 8 bit Blue LED value
>>>>> +
>>>>> +Example:
>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>> +
>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>> +
>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>
>>>> This part with example cans remain in Documentation/leds if you
>>>>> like.
>>>
>>> Does it actually work like that on hardware?
>>
>> What?
>
> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
> does it actually produce white? With all the different RGB modules
> manufacturers can use with lp5024P?
>
> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
> it actually produce yellow, with all the different RGB modules
> manufacturers can use with lp5024P?
Vesa proposed using icc-profiles to make the colors looking similar
on various LEDs. It was in reply to your message with requirements
for RGB LED class.
For this device we can however do without it. Videos showing the
performance of this particular device with a reference design using
RGB LEDs prove it works nice.
>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>
>> Monitors are not an application for this part.
>
> You did not answer the question. When you talk about yellow, is it
> same yellow the rest of world talks about?
>
>>> Because 100% PWM on all channels does not result in white on hardware
>>> I have.
>>
>> I don't know I am usually blinded by the light and have no diffuser over
>> the LEDs to disperse the light so when I look I see all 3 colors.
>
> How can we have useful discussion about colors when you don't see the
> colors?
>
> Place a piece of paper over the LEDs....
>
>>> But...
>>>
>>> I believe we should have a reasonable design before we do something
>>> like this. There's no guarantee someone will not use lp50xx with just
>>> the white LEDs for example. How will this work? Plus existing hardware
>>> already uses three separate LEDs for RGB LED. Why not provide same
>>> interface?
>>
>> Which existing hardware? Are they using this part?
>
> Nokia N900. They are not using this part, but any interface we invent
> should work there, too.
>
>> <rant>
>> Why are we delaying getting the RGB framework or HSV in?
>> I would rather design against something you want instead of having
>> everyone complain about every implementation I post.
>> </rant>
>
> Because you insist on creating new kernel interfaces, when existing
> interfaces work, and are doing that badly.
>
> Because your patches are of lower quality than is acceptable for linux
> kernel.
Lets keep things civil please.
This sentence should look familiar to you - it's not the first time
you resort to this type of narration.
> Because you don't seem to be reading the emails.
>
> I sent list of requirements for RGB led support. This does not meet
> them.
And you didn't respond to the comments from Vesa. The requirements
has not been acclaimed.
>> It is not a normal RGB driver. The device collates the individual RGB
>> clusters into a single brightness register and you can modify the intensity of the individual
>> LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
>> set in the individual registers.
>
> I understand that. So just set cluster brightness to 255 and you have
> normal RGB driver you can control with existing interfaces. You don't
> have to use every feature your hardware has.
This feature is one of the core advantages of this device.
> You did not answer the "what if someone uses this with all white LEDs"
> question.
>
> You know what? First, submit driver with similar functionality to
> existing RGB drivers, using same interface existing drivers are
> using. When that is accepted, we can talk about extending
> kernel<->user interfaces.
This stands in contradiction with my request.
Provided there will be no other NAKs, I am eager to accept the
interface with color and brightness files.
Moreover, I think that RGB LED class with configurable
brightness-model, and with possible color range adjustments via
icc-profiles or something similar, is the best solution that has been
proposed so far. It is just flexible.
I'd like to capitalize on the ideas shared in this thread and have
finally LED RGB class materialized.
--
Best regards,
Jacek Anaszewski
Hi!
> >I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
> >Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
> > maybe color capabilities but not specific colors.
>
> Dan, if you have a bandwidth for LED RGB class implementation
> then please go ahead. It would be good to compare colors produced
> by software HSV->RGB algorithm to what can be achieved with
> LEDn_BRIGHTNESS feature.
Don't get me wrong, I'd like to see LED RGB class implementation. But
it will delay merge of this driver.
If we want to do that, we should first discuss the requirements, and
then come up with interface.. and only then we can talk about the
driver code.
That's why I believe preferable way would be to merge the driver using
the existing interface.
Of course, first designing RGB LED class and then merging the
driver.. is okay with me. But lets not rush the class because there's
driver waiting for it.
> The requirements for LED RGB class as I would see it:
>
> sysfs interface:
>
> brightness-model: space separated list of available options:
> - rgb (default):
> - creates color file with "red green blue" decimal values
> - creates brightness file
> a) for devices with hardware support for adjusting color
> intensity it maps to corresponding register
> b) for the rest writing any value greater than 0 will result
> in setting all color registers to max
> - hsv:
> - creates color file with "h s v" values - it shall
> use software HSV->RGB algorithm for setting color registers
>
> - any other custom color ranges defined in DT, but it can be covered
> later
> - other options?
First, I think we want to decide if RGB LED should be presented as
3 LEDs or as 1 LED... and what to do with existing RGB leds being
presented as 3 LEDs.
I don't think we want to support both RGB and HSV in the kernel. It is
math, and not a nice one.
Yes, both have advantages and disadvantages, but having _both_ in
kernel has disadvantages of both.
One way I could imagine the interface:
RGB LED presented as one LED.
brightness -- controls brightness of whole RGB module.
pwm_channels -- "1000 240 300" -- "red part should be full on, green
should be pwm controlled to 240/1000, blue should be 300/1000"
pwm_white -- "1000 500 400" -- tells userspace what to write to PWM
channels to get approximately white color.
This would assume that RGB LEDs are always pwm controlled. That
seems to be true for hardware I seen.
+ no complex math in kernel
+ userspace knows enough to display arbitrary colors
+ userspace can use full range of available PWM intensities
+ existing triggers will work nicely
- userland needs to do non-trivial math to get colors it wants
- not sure how to migrate existing devices
Thoughts? Other possible interfaces?
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Jacek
On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
> Hi Dan,
>
> On 1/16/19 7:41 PM, Dan Murphy wrote:
>> Hello
>>
>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>> Hi!
>>>
>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>> Hi!
>>>>>
>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>> +XX - Do not care ignored by the driver
>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>> +
>>>>>>> +Example:
>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>> +
>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>> +
>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>
>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>> like.
>>>>>
>>>>> Does it actually work like that on hardware?
>>>>
>>>> What?
>>>
>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>> does it actually produce white? With all the different RGB modules
>>> manufacturers can use with lp5024P?
>>>
>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>> it actually produce yellow, with all the different RGB modules
>>> manufacturers can use with lp5024P?
>>>
>>
>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>> But everyone interprets colors differently.
>>
>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>> Most probably not.
>>
>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>
>> But we need to take into account the light pipe.? Pools nowadays have RGB LED spot lights in them.? It can
>> be set to white.? On my pool right off the lens the color has a purplish hue to it.? As the light is diffracted into
>> the pool the color becomes white.? The pool is clear.? When I add chemicals to the pool and make it cloudy
>> and turn on the lights the color off the lens is now white.? This is an example on a large scale but the issue
>> scales down to the hand helds and smart home applications.
>>
>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>
>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>> coefficients.
>>
>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>> a "rest of the world" absolute color.? Maybe it can produce something similar but not identical.
>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>> The colors should be close but may not be identical.
>>
>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>> light pipe and LED driver technology.
>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>
>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>> a hardware aspect to the calculation.
>>
>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>
>>>> Monitors are not an application for this part.
>>>
>>> You did not answer the question. When you talk about yellow, is it
>>> same yellow the rest of world talks about?
>>>
>>
>> See above.? It is close to what was on my monitor displayed.
>>
>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>> I have.
>>>>
>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>
>>> How can we have useful discussion about colors when you don't see the
>>> colors?
>>>
>>> Place a piece of paper over the LEDs....
>>>
>>
>> Good suggestion for a rough test.
>>
>>>>> But...
>>>>>
>>>>> I believe we should have a reasonable design before we do something
>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>> interface?
>>>>
>>>> Which existing hardware?? Are they using this part?
>>>
>>> Nokia N900. They are not using this part, but any interface we invent
>>> should work there, too.
>>>
>>
>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>
>>>> <rant>
>>>> Why are we delaying getting the RGB framework or HSV in?
>>>> I would rather design against something you want instead of having
>>>> everyone complain about every implementation I post.
>>>> </rant>
>>>
>>> Because you insist on creating new kernel interfaces, when existing
>>> interfaces work, and are doing that badly.
>>>
>>> Because your patches are of lower quality than is acceptable for linux
>>> kernel.
>>>
>>> Because you don't seem to be reading the emails.
>>>
>>> I sent list of requirements for RGB led support. This does not meet
>>> them.
>>>
>>
>> Sigh.? You did not answer my question.
>>
>> Your requirements seem to be centered around monitors but that is only one application of the current
>> RGB LED landscape.
>>
>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>> Or any RGB framework for that matter.? I still don't agree with the kernel needing to declare colors
>> ? maybe color capabilities but not specific colors.
>
> Dan, if you have a bandwidth for LED RGB class implementation
> then please go ahead. It would be good to compare colors produced
> by software HSV->RGB algorithm to what can be achieved with
> LEDn_BRIGHTNESS feature.
>
> The requirements for LED RGB class as I would see it:
>
> sysfs interface:
>
> brightness-model: space separated list of available options:
> - rgb (default):
> ? - creates color file with "red green blue" decimal values
What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
Should the LED color come from the DT?
How to validate that the color is real?
Or do we present a list of possible colors and validate that the color is appropriate?
I believe this could leverage the work you are doing on the LED label for color.
> ? - creates brightness file
> ????a) for devices with hardware support for adjusting color
> ?????????? intensity it maps to corresponding register
If we group LEDs as proposed we will have independent devices that give each LED a separate brightness control register.
We would need to write to each brightness register here.
> ??????? b) for the rest writing any value greater than 0 will result
> ?????????? in setting all color registers to max
> - hsv:
> ? - creates color file with "h s v" values - it shall
> ??? use software HSV->RGB algorithm for setting color registers
>
> - any other custom color ranges defined in DT, but it can be covered
> ? later
> - other options?
>
> Best regards,
> Jacek Anaszewski
>
>
>> It was agreed to continue forward with this particular implementation.
>> At least thats what the email (I apparently did not read) stated.
>>
>> I need to fix the code to use the space separated value as pointed out and shown by Vesa.
>> This will map nicely into this device with the color file as what I implemented is in theory
>> they same code except for the space separated values.
>>
>>>> It is not a normal RGB driver.? The device collates the individual RGB
>>>> clusters into a single brightness register and you can modify the intensity of the individual
>>>> LEDs via other registers.? If brightness is 0 then the cluster is OFF regardless of the color
>>>> set in the individual registers.
>>>
>>> I understand that. So just set cluster brightness to 255 and you have
>>> normal RGB driver you can control with existing interfaces. You don't
>>> have to use every feature your hardware has.
>>>
>>
>> The brightness file is available and adjusts the brightness of the RGB cluster.
>> I am not attempting to implement every feature the device has.? But I am attempting to use
>> the basic features that are available and useful.
>>
>>> You did not answer the "what if someone uses this with all white LEDs"
>>> question.
>>>
>>
>> Are you asking what if someone places a white LED instead of a RGB on the hardware?
>> Well then they need to go back and have a review of the data sheet and what they are trying to
>> achieve.? That would be a misapplication of the LED driver itself and something software cannot fix.
>>
>> But if they do determine they want to control these white LEDs with this device
>> then they can ignore the "color" file and control the cluster via the brightness file like we
>> do today.? The color file will only change the intensity of the single output (assuming LED module mode)
>> or the banked output.
>>
>> If a user wants to place a RGB cluster down on the hardware and have white as the consistent color
>> well then that is fine as the RGB outputs are all set to 0xff and the intensity of the cluster is
>> controlled by the brightness file.? If they cannot achieve the "white" with the default settings then
>> on init they can set the color file once to obtain the "white" color and continue to use the brightness
>> file to control the overall brightness of the cluster.
>>
>> It was determined in the email chain not to expose a brightness file per output as this device
>> does not lend itself to that convention.
>>
>>> You know what? First, submit driver with similar functionality to
>>> existing RGB drivers, using same interface existing drivers are
>>> using. When that is accepted, we can talk about extending
>>> kernel<->user interfaces.
>>>
>>
>> I could do that but then there is no way for users to have any other color but "white" with this driver.
>> That defeats the purpose of the device itself.
>>
>> This is why I would rather align the interfaces with what is being proposed so the interfaces won't change only
>> the engine underneath will.
>>
>> I am not sure if you are aware of this or care but I found this recent blog on this effort:
>> https://www.phoronix.com/scan.php?page=news_item&px=Linux-RGB-LED-Interface
>> See some of the comments.
>>
>> Dan
>>
>>> Thanks,
>>> ??????????????????????????????????? Pavel
>>>
>>
>>
>
>
--
------------------
Dan Murphy
Jacek
On 1/18/19 7:45 AM, Dan Murphy wrote:
> Jacek
>
> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>> Hi Dan,
>>
>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>> Hello
>>>
>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>> Hi!
>>>>
>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>> Hi!
>>>>>>
>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>> +
>>>>>>>> +Example:
>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>> +
>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>> +
>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>
>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>> like.
>>>>>>
>>>>>> Does it actually work like that on hardware?
>>>>>
>>>>> What?
>>>>
>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>> does it actually produce white? With all the different RGB modules
>>>> manufacturers can use with lp5024P?
>>>>
>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>> it actually produce yellow, with all the different RGB modules
>>>> manufacturers can use with lp5024P?
>>>>
>>>
>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>> But everyone interprets colors differently.
>>>
>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>> Most probably not.
>>>
>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>
>>> But we need to take into account the light pipe.? Pools nowadays have RGB LED spot lights in them.? It can
>>> be set to white.? On my pool right off the lens the color has a purplish hue to it.? As the light is diffracted into
>>> the pool the color becomes white.? The pool is clear.? When I add chemicals to the pool and make it cloudy
>>> and turn on the lights the color off the lens is now white.? This is an example on a large scale but the issue
>>> scales down to the hand helds and smart home applications.
>>>
>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>
>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>> coefficients.
>>>
>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>> a "rest of the world" absolute color.? Maybe it can produce something similar but not identical.
>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>> The colors should be close but may not be identical.
>>>
>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>> light pipe and LED driver technology.
>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>
>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>> a hardware aspect to the calculation.
>>>
>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>
>>>>> Monitors are not an application for this part.
>>>>
>>>> You did not answer the question. When you talk about yellow, is it
>>>> same yellow the rest of world talks about?
>>>>
>>>
>>> See above.? It is close to what was on my monitor displayed.
>>>
>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>> I have.
>>>>>
>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>
>>>> How can we have useful discussion about colors when you don't see the
>>>> colors?
>>>>
>>>> Place a piece of paper over the LEDs....
>>>>
>>>
>>> Good suggestion for a rough test.
>>>
>>>>>> But...
>>>>>>
>>>>>> I believe we should have a reasonable design before we do something
>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>> interface?
>>>>>
>>>>> Which existing hardware?? Are they using this part?
>>>>
>>>> Nokia N900. They are not using this part, but any interface we invent
>>>> should work there, too.
>>>>
>>>
>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>
>>>>> <rant>
>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>> I would rather design against something you want instead of having
>>>>> everyone complain about every implementation I post.
>>>>> </rant>
>>>>
>>>> Because you insist on creating new kernel interfaces, when existing
>>>> interfaces work, and are doing that badly.
>>>>
>>>> Because your patches are of lower quality than is acceptable for linux
>>>> kernel.
>>>>
>>>> Because you don't seem to be reading the emails.
>>>>
>>>> I sent list of requirements for RGB led support. This does not meet
>>>> them.
>>>>
>>>
>>> Sigh.? You did not answer my question.
>>>
>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>> RGB LED landscape.
>>>
>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>> Or any RGB framework for that matter.? I still don't agree with the kernel needing to declare colors
>>> ? maybe color capabilities but not specific colors.
>>
>> Dan, if you have a bandwidth for LED RGB class implementation
>> then please go ahead. It would be good to compare colors produced
>> by software HSV->RGB algorithm to what can be achieved with
>> LEDn_BRIGHTNESS feature.
>>
>> The requirements for LED RGB class as I would see it:
>>
>> sysfs interface:
>>
>> brightness-model: space separated list of available options:
>> - rgb (default):
>> ? - creates color file with "red green blue" decimal values
>
> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
> Should the LED color come from the DT?
>
I thought about this, other non-RGB LEDs would not use the RGB framework.
But should they have the same interfaces as RGB?
Should PWM control be a global interface?
Dan
<snip>
--
------------------
Dan Murphy
Hello
On 1/17/19 6:02 PM, Pavel Machek wrote:
> Hi!
>
>
>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>> maybe color capabilities but not specific colors.
>>
>> Dan, if you have a bandwidth for LED RGB class implementation
>> then please go ahead. It would be good to compare colors produced
>> by software HSV->RGB algorithm to what can be achieved with
>> LEDn_BRIGHTNESS feature.
>
> Don't get me wrong, I'd like to see LED RGB class implementation. But
> it will delay merge of this driver.
>
> If we want to do that, we should first discuss the requirements, and
> then come up with interface.. and only then we can talk about the
> driver code.
>
> That's why I believe preferable way would be to merge the driver using
> the existing interface.
>
> Of course, first designing RGB LED class and then merging the
> driver.. is okay with me. But lets not rush the class because there's
> driver waiting for it.
>
We have been able to provide users a preliminary driver they can use to test
their hardware. It is not the ideal driver but it helps them develop their
product.
The important thing here is that the driver is available to all from the Linux mainline
and not from a product repo.
>> The requirements for LED RGB class as I would see it:
>>
>> sysfs interface:
>>
>> brightness-model: space separated list of available options:
>> - rgb (default):
>> - creates color file with "red green blue" decimal values
>> - creates brightness file
>> a) for devices with hardware support for adjusting color
>> intensity it maps to corresponding register
>> b) for the rest writing any value greater than 0 will result
>> in setting all color registers to max
>> - hsv:
>> - creates color file with "h s v" values - it shall
>> use software HSV->RGB algorithm for setting color registers
>>
>> - any other custom color ranges defined in DT, but it can be covered
>> later
>> - other options?
>
> First, I think we want to decide if RGB LED should be presented as
> 3 LEDs or as 1 LED... and what to do with existing RGB leds being
> presented as 3 LEDs.
What do we do with RGBW drivers? Like the LP5562. RGB can be grouped as a single
LED but does the white LED get grouped too or should it register as a new LED?
I am assuming the answer is that it would register as a new LED.
>
> I don't think we want to support both RGB and HSV in the kernel. It is
> math, and not a nice one.
>
> Yes, both have advantages and disadvantages, but having _both_ in
> kernel has disadvantages of both.
>
I agree. Beyond the math I think giving developers a choice may bring about
driver discussion of why the developer is using RGB over HSV or vice versa.
> One way I could imagine the interface:
>
> RGB LED presented as one LED.
>
We would have to figure out a cluster schema that would group these LEDs.
Difficulty would come if you have different drivers driving different LEDs.
I personally have not seen this but the possibility is there.
We don't have to put that in the initial design and if a developer needs this
level of functionality they can submit a patch.
> brightness -- controls brightness of whole RGB module.
>
This would be nice assuming the product groups them. They should also be
individual LEDs like we have today.
> pwm_channels -- "1000 240 300" -- "red part should be full on, green
> should be pwm controlled to 240/1000, blue should be 300/1000"
>
Why 1000? Why not based on a duty cycle percentage and let the LED driver figure out
what that means to the device?
pwm_channels -- "100 24 30" -- red part is full on 100%, green is 24% duty cycle and
blue is 30% duty cycle.
> pwm_white -- "1000 500 400" -- tells userspace what to write to PWM
> channels to get approximately white color.
>
Same as above on the duty cycle.
But I still am in disagreement with the kernel detailing what is white or how to
achieve white.
Based on my earlier email about light pipes and the LED vendors and aging I think product
developers will need to fine tune what is "white" on their product from user space or even a DT node.
Not sure that the driver needs to have that level of intelligence because it has no idea
what vendor or what shade of the LED it is driving or even if the LED it is driving is the
color defined. All be it that the LP50xx data sheet does suggest that the LEDs be connected to
particular outputs but that does not mean they will.
Wondering if it would be better to set a DT node property like rgb-white that defines the values
the driver would need for the hardware to produce a white color. Then the driver would register a
set_color_white call back and the driver would take the hardware property and set the color values as defined.
Then the user space can set either "color" to 0xff 0xff 0xff or pwm_channels to 100 100 100 and the framework
would call the set_color_white call back as opposed to the set_color call back.
If rbg-white does not exist in the dt node then no call back is set and the the set_color call back is only called.
rgb-white can be an optional child property. And this eliminates the need for a user ABI
Thoughts?
> This would assume that RGB LEDs are always pwm controlled. That
> seems to be true for hardware I seen.
>
GPIO LEDs can be binary or use PWM depending on what is needed.
> + no complex math in kernel
We can eliminate the math if we use the "color" file that was proposed and pass in absolute
hex/decimal numbers for color.
>
> + userspace knows enough to display arbitrary colors
>
> + userspace can use full range of available PWM intensities
>
Do we need a pwm_max file to indicate to the user space what the max values of the pwm
is for each color?
> + existing triggers will work nicely
>
> - userland needs to do non-trivial math to get colors it wants
>
Could this be done via a DT node that exposes an attenuation constant for each LED?
Then user space can query and apply the attenuation to the associated LED.
Or userland may not care and this can be done in the driver.
It would be optional child property. And this eliminates the need for a user ABI
> - not sure how to migrate existing devices
>
> Thoughts? Other possible interfaces?
Userland would need to know what RGBs are available. The product could use a green and blue
or red and green or whatever combo. So userland can know that not all colors are available.
Dan
>
> Best regards,
> Pavel
>
--
------------------
Dan Murphy
Hi Pavel,
On 1/18/19 1:02 AM, Pavel Machek wrote:
> Hi!
>
>
>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>> maybe color capabilities but not specific colors.
>>
>> Dan, if you have a bandwidth for LED RGB class implementation
>> then please go ahead. It would be good to compare colors produced
>> by software HSV->RGB algorithm to what can be achieved with
>> LEDn_BRIGHTNESS feature.
>
> Don't get me wrong, I'd like to see LED RGB class implementation. But
> it will delay merge of this driver.
>
> If we want to do that, we should first discuss the requirements, and
> then come up with interface.. and only then we can talk about the
> driver code.
>
> That's why I believe preferable way would be to merge the driver using
> the existing interface.
>
> Of course, first designing RGB LED class and then merging the
> driver.. is okay with me. But lets not rush the class because there's
> driver waiting for it.
>
>> The requirements for LED RGB class as I would see it:
>>
>> sysfs interface:
>>
>> brightness-model: space separated list of available options:
>> - rgb (default):
>> - creates color file with "red green blue" decimal values
>> - creates brightness file
>> a) for devices with hardware support for adjusting color
>> intensity it maps to corresponding register
>> b) for the rest writing any value greater than 0 will result
>> in setting all color registers to max
>> - hsv:
>> - creates color file with "h s v" values - it shall
>> use software HSV->RGB algorithm for setting color registers
>>
>> - any other custom color ranges defined in DT, but it can be covered
>> later
>> - other options?
>
> First, I think we want to decide if RGB LED should be presented as
> 3 LEDs or as 1 LED... and what to do with existing RGB leds being
> presented as 3 LEDs.
>
> I don't think we want to support both RGB and HSV in the kernel. It is
> math, and not a nice one.
>
> Yes, both have advantages and disadvantages, but having _both_ in
> kernel has disadvantages of both.
>
> One way I could imagine the interface:
>
> RGB LED presented as one LED.
>
> brightness -- controls brightness of whole RGB module.
What algorithm would be used for mapping brightness levels to RGB values
in case of devices without hardware support for that?
> pwm_channels -- "1000 240 300" -- "red part should be full on, green
> should be pwm controlled to 240/1000, blue should be 300/1000"
>
> pwm_white -- "1000 500 400" -- tells userspace what to write to PWM
> channels to get approximately white color.
>
> This would assume that RGB LEDs are always pwm controlled. That
> seems to be true for hardware I seen.
Why pwm in the file names? I don't see any gain and only possible
problems. Many LED controllers use current level and not PWM
for driving LEDs.
Even mainline RGB LED driver: drivers/leds/leds-lp3952.c [0].
s/pwm/color/
Besides white also other color presets could be defined in DT.
> + no complex math in kernel
>
> + userspace knows enough to display arbitrary colors
>
> + userspace can use full range of available PWM intensities
>
> + existing triggers will work nicely
>
> - userland needs to do non-trivial math to get colors it wants
>
> - not sure how to migrate existing devices
>
> Thoughts? Other possible interfaces?
[0] https://www.mouser.com/ds/2/348/bd2802gu-e-210449.pdf
--
Best regards,
Jacek Anaszewski
Hi Jacek et al,
On 17/01/2019 23.08, Jacek Anaszewski wrote:
> On 1/16/19 11:55 AM, Pavel Machek wrote:
>> Hi!
>>
>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>> Hi!
>>>>
>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>> +XX - Do not care ignored by the driver
>>>>>> +RR - is the 8 bit Red LED value
>>>>>> +GG - is the 8 bit Green LED value
>>>>>> +BB - is the 8 bit Blue LED value
>>>>>> +
>>>>>> +Example:
>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>> +
>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>> +
>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>
>>>>> This part with example cans remain in Documentation/leds if you
>>>>>> like.
>>>>
>>>> Does it actually work like that on hardware?
>>>
>>> What?
>>
>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>> does it actually produce white? With all the different RGB modules
>> manufacturers can use with lp5024P?
>>
>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>> it actually produce yellow, with all the different RGB modules
>> manufacturers can use with lp5024P?
>
> Vesa proposed using icc-profiles to make the colors looking similar
> on various LEDs. It was in reply to your message with requirements
> for RGB LED class.
>
> For this device we can however do without it. Videos showing the
> performance of this particular device with a reference design using
> RGB LEDs prove it works nice.
>
>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>
>>> Monitors are not an application for this part.
>>
>> You did not answer the question. When you talk about yellow, is it
>> same yellow the rest of world talks about?
>>
>>>> Because 100% PWM on all channels does not result in white on hardware
>>>> I have.
>>>
>>> I don't know I am usually blinded by the light and have no diffuser over
>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>
>> How can we have useful discussion about colors when you don't see the
>> colors?
>>
>> Place a piece of paper over the LEDs....
>>
>>>> But...
>>>>
>>>> I believe we should have a reasonable design before we do something
>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>> interface?
>>>
>>> Which existing hardware? Are they using this part?
>>
>> Nokia N900. They are not using this part, but any interface we invent
>> should work there, too.
>>
>>> <rant>
>>> Why are we delaying getting the RGB framework or HSV in?
>>> I would rather design against something you want instead of having
>>> everyone complain about every implementation I post.
>>> </rant>
>>
>> Because you insist on creating new kernel interfaces, when existing
>> interfaces work, and are doing that badly.
>>
>> Because your patches are of lower quality than is acceptable for linux
>> kernel.
>
> Lets keep things civil please.
>
> This sentence should look familiar to you - it's not the first time
> you resort to this type of narration.
>
>> Because you don't seem to be reading the emails.
>>
>> I sent list of requirements for RGB led support. This does not meet
>> them.
>
> And you didn't respond to the comments from Vesa. The requirements
> has not been acclaimed.
>
>>> It is not a normal RGB driver. The device collates the individual RGB
>>> clusters into a single brightness register and you can modify the
>>> intensity of the individual
>>> LEDs via other registers. If brightness is 0 then the cluster is OFF
>>> regardless of the color
>>> set in the individual registers.
>>
>> I understand that. So just set cluster brightness to 255 and you have
>> normal RGB driver you can control with existing interfaces. You don't
>> have to use every feature your hardware has.
>
> This feature is one of the core advantages of this device.
>
>> You did not answer the "what if someone uses this with all white LEDs"
>> question.
>>
>> You know what? First, submit driver with similar functionality to
>> existing RGB drivers, using same interface existing drivers are
>> using. When that is accepted, we can talk about extending
>> kernel<->user interfaces.
>
> This stands in contradiction with my request.
>
> Provided there will be no other NAKs, I am eager to accept the
> interface with color and brightness files.
>
> Moreover, I think that RGB LED class with configurable
> brightness-model, and with possible color range adjustments via
> icc-profiles or something similar, is the best solution that has been
> proposed so far. It is just flexible.
>
> I'd like to capitalize on the ideas shared in this thread and have
> finally LED RGB class materialized.
>
I have now updated my github code with my understanding of the discussion:
https://github.com/vesajaaskelainen/linux/tree/wip-multi-color-led
Commits:
- dt-bindings: leds: Introduce linux,default-brightness-model for all leds
https://github.com/vesajaaskelainen/linux/commit/4ffb21d644056686096226bbede7c8c78b0254c2
- drivers: leds: Add core support for multi color element LEDs
https://github.com/vesajaaskelainen/linux/commit/627f38bb78cebc694b8e6d735fb088c87925435d
- dt-bindings: leds: leds-pwm: Introduce multi color element leds support
https://github.com/vesajaaskelainen/linux/commit/ef6c5730d621e79ea0b02470caa83bc39439536a
- WIP: drivers: leds: leds-pwm: Add multi color element LED support.
https://github.com/vesajaaskelainen/linux/commit/0430a27823d9162926424b32c23be1c53eb9cbe2
First two commits are common and could be taken before I am happy with
the pwm led driver changes. This new conditional feature flag makes it a
bit harder. Of course one option would be to require it to be enabled.
Current set of concepts:
- brightness-model: hardware, onoff, linear
- could be extended in future with other modes like hsv if wanted
- led_common_setup_of: helper for setting up common parts of led class
device from devicetree.
- led_color_element_setup_of: helper for setting up color element parts
of led class device from devicetree.
- led_scale_color_elements: single point helper for handling
brightness-model.
- From user space point-of-view atomic changes for color elements and
brightness.
Sysfs interfaces:
- brightness_model: Change of brightness model on the fly. Similar if as
trigger selection.
- color: configuring all color element values as array of values with
support for optional brightness entry as last value.
- color_names: information for user space about color element values in
'color' array.
- max_color: information for user space about maximum values for entries
in 'color' array.
Example usage:
$ cd /sys/class/leds/status
$ ls
brightness brightness_model color color_names
device max_brightness max_color power
subsystem trigger uevent
$ cat brightness_model
hardware [onoff] linear
$ cat color_names
red green blue
$ cat max_color
255 255 255
$ cat brightness
0
# Setting up color to not so bright purple with brightness set to 255
$ echo "32 0 32 255" > color
# Setting up color to a bit brighter purple with brightness
$ echo "128 0 128 255" > color
# Activate heartbeat blinking
$ echo "heartbeat" > trigger
# Now led is blinking with purple color
# Change color to green
$ echo "0 255 0" > color
# Now led is blinking with green color
And in devicetree I had now:
multi-color-leds {
compatible = "pwm-leds";
status-led {
label = "status";
linux,default-brightness-model = "onoff";
element-red {
pwms = <&ehrpwm0 0 100000 0>;
};
element-green {
pwms = <&ehrpwm1 0 100000 0>;
};
element-blue {
pwms = <&ehrpwm1 1 100000 0>;
};
};
};
What do you think is this something we agree and could go forward?
If it is it would be a good idea to get feedback from Dan on how easy it
is to use and other possible issues if he takes common commits and tries
it out with his lp50xx driver.
Thanks,
Vesa Jääskeläinen
Hi!
> >First, I think we want to decide if RGB LED should be presented as
> >3 LEDs or as 1 LED... and what to do with existing RGB leds being
> >presented as 3 LEDs.
> >
> >I don't think we want to support both RGB and HSV in the kernel. It is
> >math, and not a nice one.
> >
> >Yes, both have advantages and disadvantages, but having _both_ in
> >kernel has disadvantages of both.
> >
> >One way I could imagine the interface:
> >
> > RGB LED presented as one LED.
> >
> > brightness -- controls brightness of whole RGB module.
>
> What algorithm would be used for mapping brightness levels to RGB values
> in case of devices without hardware support for that?
Output power = brightness / max_brightness * pwm_channel[x].
> > pwm_channels -- "1000 240 300" -- "red part should be full on, green
> > should be pwm controlled to 240/1000, blue should be 300/1000"
> >
> > pwm_white -- "1000 500 400" -- tells userspace what to write to PWM
> > channels to get approximately white color.
> >
> > This would assume that RGB LEDs are always pwm controlled. That
> > seems to be true for hardware I seen.
>
> Why pwm in the file names? I don't see any gain and only possible
> problems. Many LED controllers use current level and not PWM
> for driving LEDs.
I want to make sure userspace understands this has linear relation to
output power. I'd like to avoid mentioning color because there power
output is not linear with "RGB"
> s/pwm/color/
s/pwm/power/ would work for me.
> Besides white also other color presets could be defined in DT.
They should not be neccessary. When userspace knows what is white and
that power is linear with values in power_channels, it should be able
to do colorspace conversion itself.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
> >Moreover, I think that RGB LED class with configurable
> >brightness-model, and with possible color range adjustments via
> >icc-profiles or something similar, is the best solution that has been
> >proposed so far. It is just flexible.
> >
> >I'd like to capitalize on the ideas shared in this thread and have
> >finally LED RGB class materialized.
> >
>
> I have now updated my github code with my understanding of the discussion:
> https://github.com/vesajaaskelainen/linux/tree/wip-multi-color-led
>
> Commits:
> - dt-bindings: leds: Introduce linux,default-brightness-model for all leds
> https://github.com/vesajaaskelainen/linux/commit/4ffb21d644056686096226bbede7c8c78b0254c2
> - drivers: leds: Add core support for multi color element LEDs
> https://github.com/vesajaaskelainen/linux/commit/627f38bb78cebc694b8e6d735fb088c87925435d
> - dt-bindings: leds: leds-pwm: Introduce multi color element leds support
> https://github.com/vesajaaskelainen/linux/commit/ef6c5730d621e79ea0b02470caa83bc39439536a
> - WIP: drivers: leds: leds-pwm: Add multi color element LED support.
> https://github.com/vesajaaskelainen/linux/commit/0430a27823d9162926424b32c23be1c53eb9cbe2
>
> First two commits are common and could be taken before I am happy with the
> pwm led driver changes. This new conditional feature flag makes it a bit
> harder. Of course one option would be to require it to be enabled.
>
> Current set of concepts:
> - brightness-model: hardware, onoff, linear
> - could be extended in future with other modes like hsv if wanted
Would it be enough to tell userspace what is relation between values
it writes and output power?
Onoff is subset of linear, I guess. We already have max_brightness in
the API.
> # Setting up color to not so bright purple with brightness set to 255
> $ echo "32 0 32 255" > color
> # Setting up color to a bit brighter purple with brightness
> $ echo "128 0 128 255" > color
This would require colorspace conversion in kernel. I have:
scales = (1., 0.39, 0.11) # for n900
val = map(lambda x: int((x**2.2)*255), val)
(r, g, b) = val
(r_, g_, b_) = m.scales
red = r*r_
...
x**2.2 is simplified, real expression is more complex. But it is
floating point math...
Do we want to do that?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi Pavel,
On 19/01/2019 23.46, Pavel Machek wrote:
> Hi!
>
>>> Moreover, I think that RGB LED class with configurable
>>> brightness-model, and with possible color range adjustments via
>>> icc-profiles or something similar, is the best solution that has been
>>> proposed so far. It is just flexible.
>>>
>>> I'd like to capitalize on the ideas shared in this thread and have
>>> finally LED RGB class materialized.
>>>
>>
>> I have now updated my github code with my understanding of the discussion:
>> https://github.com/vesajaaskelainen/linux/tree/wip-multi-color-led
>>
>> Commits:
>> - dt-bindings: leds: Introduce linux,default-brightness-model for all leds
>> https://github.com/vesajaaskelainen/linux/commit/4ffb21d644056686096226bbede7c8c78b0254c2
>> - drivers: leds: Add core support for multi color element LEDs
>> https://github.com/vesajaaskelainen/linux/commit/627f38bb78cebc694b8e6d735fb088c87925435d
>> - dt-bindings: leds: leds-pwm: Introduce multi color element leds support
>> https://github.com/vesajaaskelainen/linux/commit/ef6c5730d621e79ea0b02470caa83bc39439536a
>> - WIP: drivers: leds: leds-pwm: Add multi color element LED support.
>> https://github.com/vesajaaskelainen/linux/commit/0430a27823d9162926424b32c23be1c53eb9cbe2
>>
>> First two commits are common and could be taken before I am happy with the
>> pwm led driver changes. This new conditional feature flag makes it a bit
>> harder. Of course one option would be to require it to be enabled.
>>
>> Current set of concepts:
>> - brightness-model: hardware, onoff, linear
>> - could be extended in future with other modes like hsv if wanted
>
> Would it be enough to tell userspace what is relation between values
> it writes and output power?
>
> Onoff is subset of linear, I guess. We already have max_brightness in
> the API.
>
>> # Setting up color to not so bright purple with brightness set to 255
>> $ echo "32 0 32 255" > color
>
>> # Setting up color to a bit brighter purple with brightness
>> $ echo "128 0 128 255" > color
>
> This would require colorspace conversion in kernel. I have:
>
> scales = (1., 0.39, 0.11) # for n900
> val = map(lambda x: int((x**2.2)*255), val)
> (r, g, b) = val
>
> (r_, g_, b_) = m.scales
> red = r*r_
> ...
>
> x**2.2 is simplified, real expression is more complex. But it is
> floating point math...
>
> Do we want to do that?
If we would have range in user space let say 0..255 for components and
then in devicetree we could define ramp for each of the element like
what is done for backlight pwm [1] [2].
I believe this would generate same result and user space interface would
be a bit easier than writing direct pwm/power values.
You could then tune this ramp based on properties of your led. And if
you ran your software in another device it could behave similarly only
requiring tuning in devicetree.
For some of our lcd backlights we had generate non-linear ramp
definition in devicetree to have linearly looking response when user
configures brightness values from 0-100.
Definition could be something like this in devicetree:
element-red {
pwms = <&ehrpwm0 0 100000 0>;
brightness-levels = <0 128 256 1024 2048 4096 8192 16384 65535>;
num-interpolated-steps = <32>;
};
Don't know if better name would actually be in this case "ramp-levels"
or such. Used pwm-backlights terminology in this example.
[1]
https://www.kernel.org/doc/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
[2]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/video/backlight/pwm_bl.c?h=v5.0-rc2#n253
Thanks,
Vesa Jääskeläinen
Hi Dan,
On 18/01/2019 15.58, Dan Murphy wrote:
> Jacek
>
> On 1/18/19 7:45 AM, Dan Murphy wrote:
>> Jacek
>>
>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>> Hi Dan,
>>>
>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>> Hello
>>>>
>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>> Hi!
>>>>>
>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>> Hi!
>>>>>>>
>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>> +
>>>>>>>>> +Example:
>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>> +
>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>> +
>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>
>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>> like.
>>>>>>>
>>>>>>> Does it actually work like that on hardware?
>>>>>>
>>>>>> What?
>>>>>
>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>> does it actually produce white? With all the different RGB modules
>>>>> manufacturers can use with lp5024P?
>>>>>
>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>> it actually produce yellow, with all the different RGB modules
>>>>> manufacturers can use with lp5024P?
>>>>>
>>>>
>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>> But everyone interprets colors differently.
>>>>
>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>> Most probably not.
>>>>
>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>
>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>> scales down to the hand helds and smart home applications.
>>>>
>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>
>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>> coefficients.
>>>>
>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>> The colors should be close but may not be identical.
>>>>
>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>> light pipe and LED driver technology.
>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>
>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>> a hardware aspect to the calculation.
>>>>
>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>
>>>>>> Monitors are not an application for this part.
>>>>>
>>>>> You did not answer the question. When you talk about yellow, is it
>>>>> same yellow the rest of world talks about?
>>>>>
>>>>
>>>> See above. It is close to what was on my monitor displayed.
>>>>
>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>> I have.
>>>>>>
>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>
>>>>> How can we have useful discussion about colors when you don't see the
>>>>> colors?
>>>>>
>>>>> Place a piece of paper over the LEDs....
>>>>>
>>>>
>>>> Good suggestion for a rough test.
>>>>
>>>>>>> But...
>>>>>>>
>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>> interface?
>>>>>>
>>>>>> Which existing hardware? Are they using this part?
>>>>>
>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>> should work there, too.
>>>>>
>>>>
>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>
>>>>>> <rant>
>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>> I would rather design against something you want instead of having
>>>>>> everyone complain about every implementation I post.
>>>>>> </rant>
>>>>>
>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>> interfaces work, and are doing that badly.
>>>>>
>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>> kernel.
>>>>>
>>>>> Because you don't seem to be reading the emails.
>>>>>
>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>> them.
>>>>>
>>>>
>>>> Sigh. You did not answer my question.
>>>>
>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>> RGB LED landscape.
>>>>
>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>> maybe color capabilities but not specific colors.
>>>
>>> Dan, if you have a bandwidth for LED RGB class implementation
>>> then please go ahead. It would be good to compare colors produced
>>> by software HSV->RGB algorithm to what can be achieved with
>>> LEDn_BRIGHTNESS feature.
>>>
>>> The requirements for LED RGB class as I would see it:
>>>
>>> sysfs interface:
>>>
>>> brightness-model: space separated list of available options:
>>> - rgb (default):
>>> - creates color file with "red green blue" decimal values
>>
>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>> Should the LED color come from the DT?
>>
>
> I thought about this, other non-RGB LEDs would not use the RGB framework.
> But should they have the same interfaces as RGB?
>
> Should PWM control be a global interface?
In order to being able to set multi color element led at one go I would
recommend using then model:
color_names: "red green blue white"
echo "32 43 0 128" > color
This way all elements would be set at same time from user space point of
view.
This of course requires that it is part of the physical/logical led that
is being controlled. If it is a separate thing then it would logically
be differently controlled mono color led.
If you look what kinds of leds are available lets say from digikey you
get all kinds of combos:
- red, green, blue
- red, green, blue, amber
- red, green, blue, white
- red, green, blue, white - cool
- red, green, blue, white - neutral
- red, green, blue, white - warm
- red, orange
- purple, ultraviolet
- amber, blue
- amber, blue, cyan, green, red, violet, white - cool
- amber, blue, green
- amber, green, blue
- and then lots of single special colors
Better models even list some properties about how different color
elements behave.
I would expect red, green, blue to be the most common case. So
automating for that for chip like what you are working now is reasonable.
For simple case where we can expect red, green, blue mapping we can
auto-configure the multi color element led with "red", "green" and
"blue" color elements.
But TI also have other kind of driver chips that could be used in "more
freely" enabling use all of those combos.
If user would have "amber", "green" and "blue" then we would need to add
this definition in devicetree in order for user space to be able to
recognize that now we have different config.
Or if user would have most complex of those then in devicetree you would
configure 7 color element led like "amber", "blue", "cyan", "green",
"red", "violet", "white" as color elements.
Then you could set them in one go:
echo "32 76 43 2 43 76 54" > color
Now in this special case if we would have hsl brightness model and lets
say it only knows red, green and blue. Then it would pick red, green and
blue color element names and only adjust those others would be linear
should there be non-zero value.
In this case however you might be better doing it in user space as it
might be preferable to control all values let say in sRGB space and then
let the software transform result to all color elements and then setup
entries to kernel. In here the ICC color profile might be the way to go
to model your let and let user space software do the fancier math.
As this latest example is the fanciest I would like to remind that the
red, green, blue is the most common. I would make their life easier and
then when you go to more advanced setups then you are are already
mentally ready to do more complex things :)
As an example in our case we can do with "red", "green", and "red",
"green", "blue" combos fill all our current requirements we have.
Perhaps white could be added as one thing in future (white is currently
used only in lcd module's background).
Latest proposal I have for the interface now lets you do all of those
things so it should be easy enough for most cases and still flexes to
more complex cases while keeping kernel space simple.
Thanks,
Vesa Jääskeläinen
Hi Pavel,
On 19/01/2019 23.46, Pavel Machek wrote:
> Hi!
>
>>> Moreover, I think that RGB LED class with configurable
>>> brightness-model, and with possible color range adjustments via
>>> icc-profiles or something similar, is the best solution that has been
>>> proposed so far. It is just flexible.
>>>
>>> I'd like to capitalize on the ideas shared in this thread and have
>>> finally LED RGB class materialized.
>>>
>>
>> I have now updated my github code with my understanding of the discussion:
>> https://github.com/vesajaaskelainen/linux/tree/wip-multi-color-led
>>
>> Commits:
>> - dt-bindings: leds: Introduce linux,default-brightness-model for all leds
>> https://github.com/vesajaaskelainen/linux/commit/4ffb21d644056686096226bbede7c8c78b0254c2
>> - drivers: leds: Add core support for multi color element LEDs
>> https://github.com/vesajaaskelainen/linux/commit/627f38bb78cebc694b8e6d735fb088c87925435d
>> - dt-bindings: leds: leds-pwm: Introduce multi color element leds support
>> https://github.com/vesajaaskelainen/linux/commit/ef6c5730d621e79ea0b02470caa83bc39439536a
>> - WIP: drivers: leds: leds-pwm: Add multi color element LED support.
>> https://github.com/vesajaaskelainen/linux/commit/0430a27823d9162926424b32c23be1c53eb9cbe2
>>
>> First two commits are common and could be taken before I am happy with the
>> pwm led driver changes. This new conditional feature flag makes it a bit
>> harder. Of course one option would be to require it to be enabled.
>>
>> Current set of concepts:
>> - brightness-model: hardware, onoff, linear
>> - could be extended in future with other modes like hsv if wanted
>
> Would it be enough to tell userspace what is relation between values
> it writes and output power?
>
> Onoff is subset of linear, I guess. We already have max_brightness in
> the API.
Btw. there is slight problem with led trigger framework which is kinda
visible with "onoff" vs "linear" settings.
If you configure color like:
echo onoff > brightness_model
echo 32 0 32 255 > color
You get not so bright pink color. And if you then enable blinking:
echo heartbeat > trigger
Then it blinks with not so bright pink color as expected.
However if you do it:
echo linear > brightness_model
echo 255 0 255 32 > color
You once again you get not so bright pink color. However when you enable
blinking:
echo heartbeat > trigger
Then it blinks with very bright pink color.
Reason I believe is because trigger uses either values 0 or 255 for
brightness when controlling. To fix the issue I believe trigger
mechanism should be adjusted to allowing one to control ON brightness level.
I would recommend fixing this trigger problem with future patches for it.
Thanks,
Vesa Jääskeläinen
On 1/19/19 10:36 PM, Pavel Machek wrote:
> Hi!
>
>>> First, I think we want to decide if RGB LED should be presented as
>>> 3 LEDs or as 1 LED... and what to do with existing RGB leds being
>>> presented as 3 LEDs.
>>>
>>> I don't think we want to support both RGB and HSV in the kernel. It is
>>> math, and not a nice one.
>>>
>>> Yes, both have advantages and disadvantages, but having _both_ in
>>> kernel has disadvantages of both.
>>>
>>> One way I could imagine the interface:
>>>
>>> RGB LED presented as one LED.
>>>
>>> brightness -- controls brightness of whole RGB module.
>>
>> What algorithm would be used for mapping brightness levels to RGB values
>> in case of devices without hardware support for that?
>
> Output power = brightness / max_brightness * pwm_channel[x].
IIUC you mean it as a formula for calculating r,g,b, values?
I.e., on brightness setting we would have to do this calculation for
each of three channels?
Then, it will result in changing hue as well. That's why we're
discussing HSV.
>>> pwm_channels -- "1000 240 300" -- "red part should be full on, green
>>> should be pwm controlled to 240/1000, blue should be 300/1000"
>>>
>>> pwm_white -- "1000 500 400" -- tells userspace what to write to PWM
>>> channels to get approximately white color.
>>>
>>> This would assume that RGB LEDs are always pwm controlled. That
>>> seems to be true for hardware I seen.
>>
>> Why pwm in the file names? I don't see any gain and only possible
>> problems. Many LED controllers use current level and not PWM
>> for driving LEDs.
>
> I want to make sure userspace understands this has linear relation to
> output power. I'd like to avoid mentioning color because there power
> output is not linear with "RGB"
>
>> s/pwm/color/
>
> s/pwm/power/ would work for me.
Power implies physical units. I'd prefer "intensity".
>> Besides white also other color presets could be defined in DT.
>
> They should not be neccessary. When userspace knows what is white and
> that power is linear with values in power_channels, it should be able
> to do colorspace conversion itself.
Have you verified it in practice? Would it allow to convert RGB values
of the color displayed on the monitor to LED RGB class intensities,
allowing to achieve similar color on the LED?
--
Best regards,
Jacek Anaszewski
Dan,
On 1/18/19 2:45 PM, Dan Murphy wrote:
> Jacek
>
> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>> Hi Dan,
>>
>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>> Hello
>>>
>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>> Hi!
>>>>
>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>> Hi!
>>>>>>
>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>> +
>>>>>>>> +Example:
>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>> +
>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>> +
>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>
>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>> like.
>>>>>>
>>>>>> Does it actually work like that on hardware?
>>>>>
>>>>> What?
>>>>
>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>> does it actually produce white? With all the different RGB modules
>>>> manufacturers can use with lp5024P?
>>>>
>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>> it actually produce yellow, with all the different RGB modules
>>>> manufacturers can use with lp5024P?
>>>>
>>>
>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>> But everyone interprets colors differently.
>>>
>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>> Most probably not.
>>>
>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>
>>> But we need to take into account the light pipe.? Pools nowadays have RGB LED spot lights in them.? It can
>>> be set to white.? On my pool right off the lens the color has a purplish hue to it.? As the light is diffracted into
>>> the pool the color becomes white.? The pool is clear.? When I add chemicals to the pool and make it cloudy
>>> and turn on the lights the color off the lens is now white.? This is an example on a large scale but the issue
>>> scales down to the hand helds and smart home applications.
>>>
>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>
>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>> coefficients.
>>>
>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>> a "rest of the world" absolute color.? Maybe it can produce something similar but not identical.
>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>> The colors should be close but may not be identical.
>>>
>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>> light pipe and LED driver technology.
>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>
>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>> a hardware aspect to the calculation.
>>>
>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>
>>>>> Monitors are not an application for this part.
>>>>
>>>> You did not answer the question. When you talk about yellow, is it
>>>> same yellow the rest of world talks about?
>>>>
>>>
>>> See above.? It is close to what was on my monitor displayed.
>>>
>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>> I have.
>>>>>
>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>
>>>> How can we have useful discussion about colors when you don't see the
>>>> colors?
>>>>
>>>> Place a piece of paper over the LEDs....
>>>>
>>>
>>> Good suggestion for a rough test.
>>>
>>>>>> But...
>>>>>>
>>>>>> I believe we should have a reasonable design before we do something
>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>> interface?
>>>>>
>>>>> Which existing hardware?? Are they using this part?
>>>>
>>>> Nokia N900. They are not using this part, but any interface we invent
>>>> should work there, too.
>>>>
>>>
>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>
>>>>> <rant>
>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>> I would rather design against something you want instead of having
>>>>> everyone complain about every implementation I post.
>>>>> </rant>
>>>>
>>>> Because you insist on creating new kernel interfaces, when existing
>>>> interfaces work, and are doing that badly.
>>>>
>>>> Because your patches are of lower quality than is acceptable for linux
>>>> kernel.
>>>>
>>>> Because you don't seem to be reading the emails.
>>>>
>>>> I sent list of requirements for RGB led support. This does not meet
>>>> them.
>>>>
>>>
>>> Sigh.? You did not answer my question.
>>>
>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>> RGB LED landscape.
>>>
>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>> Or any RGB framework for that matter.? I still don't agree with the kernel needing to declare colors
>>> ? maybe color capabilities but not specific colors.
>>
>> Dan, if you have a bandwidth for LED RGB class implementation
>> then please go ahead. It would be good to compare colors produced
>> by software HSV->RGB algorithm to what can be achieved with
>> LEDn_BRIGHTNESS feature.
>>
>> The requirements for LED RGB class as I would see it:
>>
>> sysfs interface:
>>
>> brightness-model: space separated list of available options:
>> - rgb (default):
>> ? - creates color file with "red green blue" decimal values
>
> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
> Should the LED color come from the DT?
This is out of this discussion scope. Here we're discussing RGB LEDs.
I believe LEDn_BRIGHTNESS of lp50xx would also not work as intended with
colors other than RGB.
Best regards,
Jacek Anaszewski
> How to validate that the color is real?
> Or do we present a list of possible colors and validate that the color is appropriate?
>
> I believe this could leverage the work you are doing on the LED label for color.
>
>> ? - creates brightness file
>> ????a) for devices with hardware support for adjusting color
>> ?????????? intensity it maps to corresponding register
>
> If we group LEDs as proposed we will have independent devices that give each LED a separate brightness control register.
> We would need to write to each brightness register here.
>
>> ??????? b) for the rest writing any value greater than 0 will result
>> ?????????? in setting all color registers to max
>> - hsv:
>> ? - creates color file with "h s v" values - it shall
>> ??? use software HSV->RGB algorithm for setting color registers
>>
>> - any other custom color ranges defined in DT, but it can be covered
>> ? later
>> - other options?
>>
>> Best regards,
>> Jacek Anaszewski
>>
>>
>>> It was agreed to continue forward with this particular implementation.
>>> At least thats what the email (I apparently did not read) stated.
>>>
>>> I need to fix the code to use the space separated value as pointed out and shown by Vesa.
>>> This will map nicely into this device with the color file as what I implemented is in theory
>>> they same code except for the space separated values.
>>>
>>>>> It is not a normal RGB driver.? The device collates the individual RGB
>>>>> clusters into a single brightness register and you can modify the intensity of the individual
>>>>> LEDs via other registers.? If brightness is 0 then the cluster is OFF regardless of the color
>>>>> set in the individual registers.
>>>>
>>>> I understand that. So just set cluster brightness to 255 and you have
>>>> normal RGB driver you can control with existing interfaces. You don't
>>>> have to use every feature your hardware has.
>>>>
>>>
>>> The brightness file is available and adjusts the brightness of the RGB cluster.
>>> I am not attempting to implement every feature the device has.? But I am attempting to use
>>> the basic features that are available and useful.
>>>
>>>> You did not answer the "what if someone uses this with all white LEDs"
>>>> question.
>>>>
>>>
>>> Are you asking what if someone places a white LED instead of a RGB on the hardware?
>>> Well then they need to go back and have a review of the data sheet and what they are trying to
>>> achieve.? That would be a misapplication of the LED driver itself and something software cannot fix.
>>>
>>> But if they do determine they want to control these white LEDs with this device
>>> then they can ignore the "color" file and control the cluster via the brightness file like we
>>> do today.? The color file will only change the intensity of the single output (assuming LED module mode)
>>> or the banked output.
>>>
>>> If a user wants to place a RGB cluster down on the hardware and have white as the consistent color
>>> well then that is fine as the RGB outputs are all set to 0xff and the intensity of the cluster is
>>> controlled by the brightness file.? If they cannot achieve the "white" with the default settings then
>>> on init they can set the color file once to obtain the "white" color and continue to use the brightness
>>> file to control the overall brightness of the cluster.
>>>
>>> It was determined in the email chain not to expose a brightness file per output as this device
>>> does not lend itself to that convention.
>>>
>>>> You know what? First, submit driver with similar functionality to
>>>> existing RGB drivers, using same interface existing drivers are
>>>> using. When that is accepted, we can talk about extending
>>>> kernel<->user interfaces.
>>>>
>>>
>>> I could do that but then there is no way for users to have any other color but "white" with this driver.
>>> That defeats the purpose of the device itself.
>>>
>>> This is why I would rather align the interfaces with what is being proposed so the interfaces won't change only
>>> the engine underneath will.
>>>
>>> I am not sure if you are aware of this or care but I found this recent blog on this effort:
>>> https://www.phoronix.com/scan.php?page=news_item&px=Linux-RGB-LED-Interface
>>> See some of the comments.
>>>
>>> Dan
>>>
>>>> Thanks,
>>>> ??????????????????????????????????? Pavel
>>>>
>>>
>>>
>>
>>
>
>
Vesa
On 1/19/19 1:11 PM, Vesa Jääskeläinen wrote:
> Hi Jacek et al,
>
> On 17/01/2019 23.08, Jacek Anaszewski wrote:
>> On 1/16/19 11:55 AM, Pavel Machek wrote:
>>> Hi!
>>>
>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>> Hi!
>>>>>
>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>> +XX - Do not care ignored by the driver
>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>> +
>>>>>>> +Example:
>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>> +
>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>> +
>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>
>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>> like.
>>>>>
>>>>> Does it actually work like that on hardware?
>>>>
>>>> What?
>>>
>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>> does it actually produce white? With all the different RGB modules
>>> manufacturers can use with lp5024P?
>>>
>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>> it actually produce yellow, with all the different RGB modules
>>> manufacturers can use with lp5024P?
>>
>> Vesa proposed using icc-profiles to make the colors looking similar
>> on various LEDs. It was in reply to your message with requirements
>> for RGB LED class.
>>
>> For this device we can however do without it. Videos showing the
>> performance of this particular device with a reference design using
>> RGB LEDs prove it works nice.
>>
>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>
>>>> Monitors are not an application for this part.
>>>
>>> You did not answer the question. When you talk about yellow, is it
>>> same yellow the rest of world talks about?
>>>
>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>> I have.
>>>>
>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>
>>> How can we have useful discussion about colors when you don't see the
>>> colors?
>>>
>>> Place a piece of paper over the LEDs....
>>>
>>>>> But...
>>>>>
>>>>> I believe we should have a reasonable design before we do something
>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>> interface?
>>>>
>>>> Which existing hardware? Are they using this part?
>>>
>>> Nokia N900. They are not using this part, but any interface we invent
>>> should work there, too.
>>>
>>>> <rant>
>>>> Why are we delaying getting the RGB framework or HSV in?
>>>> I would rather design against something you want instead of having
>>>> everyone complain about every implementation I post.
>>>> </rant>
>>>
>>> Because you insist on creating new kernel interfaces, when existing
>>> interfaces work, and are doing that badly.
>>>
>>> Because your patches are of lower quality than is acceptable for linux
>>> kernel.
>>
>> Lets keep things civil please.
>>
>> This sentence should look familiar to you - it's not the first time
>> you resort to this type of narration.
>>
>>> Because you don't seem to be reading the emails.
>>>
>>> I sent list of requirements for RGB led support. This does not meet
>>> them.
>>
>> And you didn't respond to the comments from Vesa. The requirements
>> has not been acclaimed.
>>
>>>> It is not a normal RGB driver. The device collates the individual RGB
>>>> clusters into a single brightness register and you can modify the intensity of the individual
>>>> LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
>>>> set in the individual registers.
>>>
>>> I understand that. So just set cluster brightness to 255 and you have
>>> normal RGB driver you can control with existing interfaces. You don't
>>> have to use every feature your hardware has.
>>
>> This feature is one of the core advantages of this device.
>>
>>> You did not answer the "what if someone uses this with all white LEDs"
>>> question.
>>>
>>> You know what? First, submit driver with similar functionality to
>>> existing RGB drivers, using same interface existing drivers are
>>> using. When that is accepted, we can talk about extending
>>> kernel<->user interfaces.
>>
>> This stands in contradiction with my request.
>>
>> Provided there will be no other NAKs, I am eager to accept the
>> interface with color and brightness files.
>>
>> Moreover, I think that RGB LED class with configurable
>> brightness-model, and with possible color range adjustments via
>> icc-profiles or something similar, is the best solution that has been proposed so far. It is just flexible.
>>
>> I'd like to capitalize on the ideas shared in this thread and have
>> finally LED RGB class materialized.
>>
>
> I have now updated my github code with my understanding of the discussion:
> https://github.com/vesajaaskelainen/linux/tree/wip-multi-color-led
>
Maybe I did not see it but a RFC to the list would be good for discussion points.
> Commits:
> - dt-bindings: leds: Introduce linux,default-brightness-model for all leds
> https://github.com/vesajaaskelainen/linux/commit/4ffb21d644056686096226bbede7c8c78b0254c2
> - drivers: leds: Add core support for multi color element LEDs
> https://github.com/vesajaaskelainen/linux/commit/627f38bb78cebc694b8e6d735fb088c87925435d
> - dt-bindings: leds: leds-pwm: Introduce multi color element leds support
> https://github.com/vesajaaskelainen/linux/commit/ef6c5730d621e79ea0b02470caa83bc39439536a
> - WIP: drivers: leds: leds-pwm: Add multi color element LED support.
> https://github.com/vesajaaskelainen/linux/commit/0430a27823d9162926424b32c23be1c53eb9cbe2
>
> First two commits are common and could be taken before I am happy with the pwm led driver changes. This new conditional feature flag makes it a bit harder. Of course one option would be to require it to be enabled.
>
> Current set of concepts:
> - brightness-model: hardware, onoff, linear
Seem to be missing logarithmic
> - could be extended in future with other modes like hsv if wanted
> - led_common_setup_of: helper for setting up common parts of led class device from devicetree.
> - led_color_element_setup_of: helper for setting up color element parts of led class device from devicetree.
> - led_scale_color_elements: single point helper for handling brightness-model.
> - From user space point-of-view atomic changes for color elements and brightness.
>
> Sysfs interfaces:
> - brightness_model: Change of brightness model on the fly. Similar if as trigger selection.
> - color: configuring all color element values as array of values with support for optional brightness entry as last value.
> - color_names: information for user space about color element values in 'color' array.
> - max_color: information for user space about maximum values for entries in 'color' array.
>
> Example usage:
>
> $ cd /sys/class/leds/status
>
> $ ls
> brightness brightness_model color color_names device max_brightness max_color power subsystem trigger uevent
>
> $ cat brightness_model
> hardware [onoff] linear
> $ cat color_names
> red green blue
> $ cat max_color
> 255 255 255
> $ cat brightness
> 0
>
What happens if brightness is set? Is that ignored?
What is the driver supposed to do?
The LP50xx can set brightness independent of color but other devices cannot do that.
> # Setting up color to not so bright purple with brightness set to 255
> $ echo "32 0 32 255" > color
>
> # Setting up color to a bit brighter purple with brightness
> $ echo "128 0 128 255" > color
>
> # Activate heartbeat blinking
> $ echo "heartbeat" > trigger
>
> # Now led is blinking with purple color
>
> # Change color to green
> $ echo "0 255 0" > color
>
> # Now led is blinking with green color
>
> And in devicetree I had now:
>
> multi-color-leds {
> compatible = "pwm-leds";
>
> status-led {
> label = "status";
> linux,default-brightness-model = "onoff";
>
> element-red {
> pwms = <&ehrpwm0 0 100000 0>;
> };
> element-green {
> pwms = <&ehrpwm1 0 100000 0>;
> };
> element-blue {
> pwms = <&ehrpwm1 1 100000 0>;
> };
> };
> };
>
> What do you think is this something we agree and could go forward?
>
> If it is it would be a good idea to get feedback from Dan on how easy it is to use and other possible issues if he takes common commits and tries it out with his lp50xx driver.
>
The LP50xx pwm is not standard.
It defines a PWM dithering mode which phase shifts the LED outputs and does not really control the PWM width of the LEDs.
I can try to stitch this together for testing. I will need to go through this code and docs a bit more.
Dan
> Thanks,
> Vesa Jääskeläinen
--
------------------
Dan Murphy
Hi Dan,
On 21/01/2019 15.27, Dan Murphy wrote:
> Vesa
>
> On 1/19/19 1:11 PM, Vesa Jääskeläinen wrote:
>> Hi Jacek et al,
>>
>> On 17/01/2019 23.08, Jacek Anaszewski wrote:
>>> On 1/16/19 11:55 AM, Pavel Machek wrote:
>>>> Hi!
>>>>
>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>> Hi!
>>>>>>
>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>> +
>>>>>>>> +Example:
>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>> +
>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>> +
>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>
>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>> like.
>>>>>>
>>>>>> Does it actually work like that on hardware?
>>>>>
>>>>> What?
>>>>
>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>> does it actually produce white? With all the different RGB modules
>>>> manufacturers can use with lp5024P?
>>>>
>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>> it actually produce yellow, with all the different RGB modules
>>>> manufacturers can use with lp5024P?
>>>
>>> Vesa proposed using icc-profiles to make the colors looking similar
>>> on various LEDs. It was in reply to your message with requirements
>>> for RGB LED class.
>>>
>>> For this device we can however do without it. Videos showing the
>>> performance of this particular device with a reference design using
>>> RGB LEDs prove it works nice.
>>>
>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>
>>>>> Monitors are not an application for this part.
>>>>
>>>> You did not answer the question. When you talk about yellow, is it
>>>> same yellow the rest of world talks about?
>>>>
>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>> I have.
>>>>>
>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>
>>>> How can we have useful discussion about colors when you don't see the
>>>> colors?
>>>>
>>>> Place a piece of paper over the LEDs....
>>>>
>>>>>> But...
>>>>>>
>>>>>> I believe we should have a reasonable design before we do something
>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>> interface?
>>>>>
>>>>> Which existing hardware? Are they using this part?
>>>>
>>>> Nokia N900. They are not using this part, but any interface we invent
>>>> should work there, too.
>>>>
>>>>> <rant>
>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>> I would rather design against something you want instead of having
>>>>> everyone complain about every implementation I post.
>>>>> </rant>
>>>>
>>>> Because you insist on creating new kernel interfaces, when existing
>>>> interfaces work, and are doing that badly.
>>>>
>>>> Because your patches are of lower quality than is acceptable for linux
>>>> kernel.
>>>
>>> Lets keep things civil please.
>>>
>>> This sentence should look familiar to you - it's not the first time
>>> you resort to this type of narration.
>>>
>>>> Because you don't seem to be reading the emails.
>>>>
>>>> I sent list of requirements for RGB led support. This does not meet
>>>> them.
>>>
>>> And you didn't respond to the comments from Vesa. The requirements
>>> has not been acclaimed.
>>>
>>>>> It is not a normal RGB driver. The device collates the individual RGB
>>>>> clusters into a single brightness register and you can modify the intensity of the individual
>>>>> LEDs via other registers. If brightness is 0 then the cluster is OFF regardless of the color
>>>>> set in the individual registers.
>>>>
>>>> I understand that. So just set cluster brightness to 255 and you have
>>>> normal RGB driver you can control with existing interfaces. You don't
>>>> have to use every feature your hardware has.
>>>
>>> This feature is one of the core advantages of this device.
>>>
>>>> You did not answer the "what if someone uses this with all white LEDs"
>>>> question.
>>>>
>>>> You know what? First, submit driver with similar functionality to
>>>> existing RGB drivers, using same interface existing drivers are
>>>> using. When that is accepted, we can talk about extending
>>>> kernel<->user interfaces.
>>>
>>> This stands in contradiction with my request.
>>>
>>> Provided there will be no other NAKs, I am eager to accept the
>>> interface with color and brightness files.
>>>
>>> Moreover, I think that RGB LED class with configurable
>>> brightness-model, and with possible color range adjustments via
>>> icc-profiles or something similar, is the best solution that has been proposed so far. It is just flexible.
>>>
>>> I'd like to capitalize on the ideas shared in this thread and have
>>> finally LED RGB class materialized.
>>>
>>
>> I have now updated my github code with my understanding of the discussion:
>> https://github.com/vesajaaskelainen/linux/tree/wip-multi-color-led
>>
>
> Maybe I did not see it but a RFC to the list would be good for discussion points.
Ok. I can try to do that soonish. I want to clean PWM driver a bit first.
>> Commits:
>> - dt-bindings: leds: Introduce linux,default-brightness-model for all leds
>> https://github.com/vesajaaskelainen/linux/commit/4ffb21d644056686096226bbede7c8c78b0254c2
>> - drivers: leds: Add core support for multi color element LEDs
>> https://github.com/vesajaaskelainen/linux/commit/627f38bb78cebc694b8e6d735fb088c87925435d
>> - dt-bindings: leds: leds-pwm: Introduce multi color element leds support
>> https://github.com/vesajaaskelainen/linux/commit/ef6c5730d621e79ea0b02470caa83bc39439536a
>> - WIP: drivers: leds: leds-pwm: Add multi color element LED support.
>> https://github.com/vesajaaskelainen/linux/commit/0430a27823d9162926424b32c23be1c53eb9cbe2
>>
>> First two commits are common and could be taken before I am happy with the pwm led driver changes. This new conditional feature flag makes it a bit harder. Of course one option would be to require it to be enabled.
>>
>> Current set of concepts:
>> - brightness-model: hardware, onoff, linear
>
> Seem to be missing logarithmic
How would you model that? As a ramp curve and then use linear?
Do you think devicetree would be enough to define the ramp curve?
>> - could be extended in future with other modes like hsv if wanted
>> - led_common_setup_of: helper for setting up common parts of led class device from devicetree.
>> - led_color_element_setup_of: helper for setting up color element parts of led class device from devicetree.
>> - led_scale_color_elements: single point helper for handling brightness-model.
>> - From user space point-of-view atomic changes for color elements and brightness.
>>
>> Sysfs interfaces:
>> - brightness_model: Change of brightness model on the fly. Similar if as trigger selection.
>> - color: configuring all color element values as array of values with support for optional brightness entry as last value.
>> - color_names: information for user space about color element values in 'color' array.
>> - max_color: information for user space about maximum values for entries in 'color' array.
>>
>> Example usage:
>>
>> $ cd /sys/class/leds/status
>>
>> $ ls
>> brightness brightness_model color color_names device max_brightness max_color power subsystem trigger uevent
>>
>> $ cat brightness_model
>> hardware [onoff] linear
>> $ cat color_names
>> red green blue
>> $ cat max_color
>> 255 255 255
>> $ cat brightness
>> 0
>>
>
> What happens if brightness is set? Is that ignored?
> What is the driver supposed to do?
> The LP50xx can set brightness independent of color but other devices cannot do that.
What happens is a call from led framework class to execute brightness
set operation to the driver (cdev::brightness_set_blocking which in pwm
driver is led_pwm_set).
Driver can then (optionally) call for led_scale_color_elements() which
would then calculate brightness model operation from set logical value
to raw value.
If mode is hardware then led_scale_color_elements() just copies the
logical value to raw value.
Then it is up to driver to decide what to do with those input information.
Eg. in hardware brightness model case probably following:
Iterate raw color element values and set registers based on those.
Take brightness value from the call and set it to register.
If brightness model is something else then it might be better to set
brightness to 0 or 255.
>> # Setting up color to not so bright purple with brightness set to 255
>> $ echo "32 0 32 255" > color
>>
>> # Setting up color to a bit brighter purple with brightness
>> $ echo "128 0 128 255" > color
>>
>> # Activate heartbeat blinking
>> $ echo "heartbeat" > trigger
>>
>> # Now led is blinking with purple color
>>
>> # Change color to green
>> $ echo "0 255 0" > color
>>
>> # Now led is blinking with green color
>>
>> And in devicetree I had now:
>>
>> multi-color-leds {
>> compatible = "pwm-leds";
>>
>> status-led {
>> label = "status";
>> linux,default-brightness-model = "onoff";
>>
>> element-red {
>> pwms = <&ehrpwm0 0 100000 0>;
>> };
>> element-green {
>> pwms = <&ehrpwm1 0 100000 0>;
>> };
>> element-blue {
>> pwms = <&ehrpwm1 1 100000 0>;
>> };
>> };
>> };
>>
>> What do you think is this something we agree and could go forward?
>>
>> If it is it would be a good idea to get feedback from Dan on how easy it is to use and other possible issues if he takes common commits and tries it out with his lp50xx driver.
>>
>
> The LP50xx pwm is not standard.
> It defines a PWM dithering mode which phase shifts the LED outputs and does not really control the PWM width of the LEDs.
>
> I can try to stitch this together for testing. I will need to go through this code and docs a bit more.
Then it is even more important to test if the interface is suitable.
Thanks,
Vesa Jääskeläinen
On 1/20/19 4:30 PM, Jacek Anaszewski wrote:
> On 1/19/19 10:36 PM, Pavel Machek wrote:
>> Hi!
[...]
>> I want to make sure userspace understands this has linear relation to
>> output power. I'd like to avoid mentioning color because there power
>> output is not linear with "RGB"
>>
>>> s/pwm/color/
>>
>> s/pwm/power/ would work for me.
>
> Power implies physical units. I'd prefer "intensity".
Hmm, intensity_channels does not look too informative...
OK, so let's stick to power_channels, at least for time being.
Maybe some better ideas will have appeared before the final
solution is merged.
--
Best regards,
Jacek Anaszewski
Hi all,
On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
> Hi Dan,
>
> On 18/01/2019 15.58, Dan Murphy wrote:
>> Jacek
>>
>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>> Jacek
>>>
>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>> Hi Dan,
>>>>
>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>> Hello
>>>>>
>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>> Hi!
>>>>>>
>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>> Hi!
>>>>>>>>
>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>> +
>>>>>>>>>> +Example:
>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>> +
>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>> +
>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>
>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>> like.
>>>>>>>>
>>>>>>>> Does it actually work like that on hardware?
>>>>>>>
>>>>>>> What?
>>>>>>
>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>> does it actually produce white? With all the different RGB modules
>>>>>> manufacturers can use with lp5024P?
>>>>>>
>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color,
>>>>>> does
>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>> manufacturers can use with lp5024P?
>>>>>>
>>>>>
>>>>> I believe the answer to the general questions is no for any RGB
>>>>> cluster and driver out there.
>>>>> Because if you set the same values on each and every RGB device out
>>>>> there you will get varying shades of the color.
>>>>> But for this device yes the color does appear to be yellow to me
>>>>> versus what was displayed on my monitor by the HSL picker.
>>>>> But everyone interprets colors differently.
>>>>>
>>>>> If you write the same value for yellow or white on a droid 4 and
>>>>> the N900 do they produce the same color side by side?
>>>>> Most probably not.
>>>>>
>>>>> As you pointed out the PWM needs to be modified to obtain the
>>>>> correct white color to account for LED and other device constraints.
>>>>>
>>>>> But we need to take into account the light pipe. Pools nowadays
>>>>> have RGB LED spot lights in them. It can
>>>>> be set to white. On my pool right off the lens the color has a
>>>>> purplish hue to it. As the light is diffracted into
>>>>> the pool the color becomes white. The pool is clear. When I add
>>>>> chemicals to the pool and make it cloudy
>>>>> and turn on the lights the color off the lens is now white. This
>>>>> is an example on a large scale but the issue
>>>>> scales down to the hand helds and smart home applications.
>>>>>
>>>>> If the cluster is piped through a flexible optic 0xffffff may
>>>>> produce the "white" you want on its output.
>>>>>
>>>>> So an expectation of certain color without proper piping based on a
>>>>> single RGB value may be a little unreasonable.
>>>>> There may need to be a way to attenuate the values based on the
>>>>> hardware aspect of the equation ie light pipe (or lack thereof) and
>>>>> LED vendor.
>>>>> So if we write 0xffffff to the RGB driver the driver could adjust
>>>>> the intensity of the individual LEDs based on the diffraction
>>>>> coefficients.
>>>>>
>>>>> I also think that is an unreasonable expectation here that writing
>>>>> a single value to any LED RGB driver would produce
>>>>> a "rest of the world" absolute color. Maybe it can produce
>>>>> something similar but not identical.
>>>>> As you indicated in the requirements there is more involved here
>>>>> then just the LED and the values written.
>>>>> The colors should be close but may not be identical.
>>>>>
>>>>> A 10 year old N900 should not be considered the gold standard for
>>>>> color production due to advancements in LED,
>>>>> light pipe and LED driver technology.
>>>>> The single package RGB clusters on the board I am testing is about
>>>>> the size of a single RGB LED from 10 years ago.
>>>>>
>>>>> I agree that the interface developed should work on the device but
>>>>> the algorithm derived to obtain the color needs to have
>>>>> a hardware aspect to the calculation.
>>>>>
>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>
>>>>>>> Monitors are not an application for this part.
>>>>>>
>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>> same yellow the rest of world talks about?
>>>>>>
>>>>>
>>>>> See above. It is close to what was on my monitor displayed.
>>>>>
>>>>>>>> Because 100% PWM on all channels does not result in white on
>>>>>>>> hardware
>>>>>>>> I have.
>>>>>>>
>>>>>>> I don't know I am usually blinded by the light and have no
>>>>>>> diffuser over
>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>
>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>> colors?
>>>>>>
>>>>>> Place a piece of paper over the LEDs....
>>>>>>
>>>>>
>>>>> Good suggestion for a rough test.
>>>>>
>>>>>>>> But...
>>>>>>>>
>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>> like this. There's no guarantee someone will not use lp50xx with
>>>>>>>> just
>>>>>>>> the white LEDs for example. How will this work? Plus existing
>>>>>>>> hardware
>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>> interface?
>>>>>>>
>>>>>>> Which existing hardware? Are they using this part?
>>>>>>
>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>> should work there, too.
>>>>>>
>>>>>
>>>>> Yes a common interface would be nice with some sort of hardware
>>>>> tuning coefficient.
>>>>>
>>>>>>> <rant>
>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>> I would rather design against something you want instead of having
>>>>>>> everyone complain about every implementation I post.
>>>>>>> </rant>
>>>>>>
>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>> interfaces work, and are doing that badly.
>>>>>>
>>>>>> Because your patches are of lower quality than is acceptable for
>>>>>> linux
>>>>>> kernel.
>>>>>>
>>>>>> Because you don't seem to be reading the emails.
>>>>>>
>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>> them.
>>>>>>
>>>>>
>>>>> Sigh. You did not answer my question.
>>>>>
>>>>> Your requirements seem to be centered around monitors but that is
>>>>> only one application of the current
>>>>> RGB LED landscape.
>>>>>
>>>>> I am willing to work with you on the HSV and adapting the LP50xx
>>>>> part to this framework.
>>>>> Or any RGB framework for that matter. I still don't agree with the
>>>>> kernel needing to declare colors
>>>>> maybe color capabilities but not specific colors.
>>>>
>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>> then please go ahead. It would be good to compare colors produced
>>>> by software HSV->RGB algorithm to what can be achieved with
>>>> LEDn_BRIGHTNESS feature.
>>>>
>>>> The requirements for LED RGB class as I would see it:
>>>>
>>>> sysfs interface:
>>>>
>>>> brightness-model: space separated list of available options:
>>>> - rgb (default):
>>>> - creates color file with "red green blue" decimal values
>>>
>>> What about other colored LEDs? Presenting RGB for an Amber LED does
>>> not seem right.
>>> Should the LED color come from the DT?
>>>
>>
>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>> But should they have the same interfaces as RGB?
>>
>> Should PWM control be a global interface?
>
> In order to being able to set multi color element led at one go I would
> recommend using then model:
>
> color_names: "red green blue white"
>
> echo "32 43 0 128" > color
>
> This way all elements would be set at same time from user space point of
> view.
>
> This of course requires that it is part of the physical/logical led that
> is being controlled. If it is a separate thing then it would logically
> be differently controlled mono color led.
>
> If you look what kinds of leds are available lets say from digikey you
> get all kinds of combos:
>
> - red, green, blue
> - red, green, blue, amber
> - red, green, blue, white
> - red, green, blue, white - cool
> - red, green, blue, white - neutral
> - red, green, blue, white - warm
> - red, orange
> - purple, ultraviolet
> - amber, blue
> - amber, blue, cyan, green, red, violet, white - cool
> - amber, blue, green
> - amber, green, blue
> - and then lots of single special colors
It suggested me another solution. Instead of LED RGB class
we would have LED multi-color class.
Sysfs interface design:
-----------------------
colors: directory containing files that map to
the brightness of particular LEDs; there
would be predefined color names that LED class
driver should map iouts to, e.g.:
- red
- green
- blue
- white
- sync: accepts "write" and "read", which executes
write/readout to/from a device respectively.
brightness-model: defines brightness level to color configuration
mapping
- "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
- "rgb-<hue>": available only when all three red,green,blue colors
are present in the colors directory.
<hue> is a placeholder for given DT hue presets.
- "rgbw-<hue>": Same as above, but available only when white color
(any of amber or white-{cool|neutral|warm} can be
mapped to white) is also available. In this mode
max_brightness equals num-of-hue-presets + 1, and
max_brightness, when set, turns the "white" LED on
- "rgb-linear": I'm not sure if it should be available - it will
have unpredictable results
brightness: sets/reads brightness in the way specific to the
current brightness-model. When more colors are available
(e.g. amber, blue, cyan, green, red, violet, white), they
are not touched by write to brightness).
HSV->RGB conversion is left entirely to the userspace, which can set any
color with use of the proposed interface.
Let's agree on sysfs interface first, and only after that move
to the DT details.
Best regards,
Jacek Anaszewski
> Better models even list some properties about how different color
> elements behave.
>
> I would expect red, green, blue to be the most common case. So
> automating for that for chip like what you are working now is reasonable.
>
> For simple case where we can expect red, green, blue mapping we can
> auto-configure the multi color element led with "red", "green" and
> "blue" color elements.
>
> But TI also have other kind of driver chips that could be used in "more
> freely" enabling use all of those combos.
>
> If user would have "amber", "green" and "blue" then we would need to add
> this definition in devicetree in order for user space to be able to
> recognize that now we have different config.
>
> Or if user would have most complex of those then in devicetree you would
> configure 7 color element led like "amber", "blue", "cyan", "green",
> "red", "violet", "white" as color elements.
>
> Then you could set them in one go:
> echo "32 76 43 2 43 76 54" > color
>
> Now in this special case if we would have hsl brightness model and lets
> say it only knows red, green and blue. Then it would pick red, green and
> blue color element names and only adjust those others would be linear
> should there be non-zero value.
>
> In this case however you might be better doing it in user space as it
> might be preferable to control all values let say in sRGB space and then
> let the software transform result to all color elements and then setup
> entries to kernel. In here the ICC color profile might be the way to go
> to model your let and let user space software do the fancier math.
>
> As this latest example is the fanciest I would like to remind that the
> red, green, blue is the most common. I would make their life easier and
> then when you go to more advanced setups then you are are already
> mentally ready to do more complex things :)
>
> As an example in our case we can do with "red", "green", and "red",
> "green", "blue" combos fill all our current requirements we have.
> Perhaps white could be added as one thing in future (white is currently
> used only in lcd module's background).
>
> Latest proposal I have for the interface now lets you do all of those
> things so it should be easy enough for most cases and still flexes to
> more complex cases while keeping kernel space simple.
>
> Thanks,
> Vesa Jääskeläinen
>
Jacek
On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
> Hi all,
>
> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>> Hi Dan,
>>
>> On 18/01/2019 15.58, Dan Murphy wrote:
>>> Jacek
>>>
>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>> Jacek
>>>>
>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>> Hi Dan,
>>>>>
>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>> Hello
>>>>>>
>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>> Hi!
>>>>>>>
>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>> Hi!
>>>>>>>>>
>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>> +
>>>>>>>>>>> +Example:
>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>> +
>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>> +
>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>
>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>> like.
>>>>>>>>>
>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>
>>>>>>>> What?
>>>>>>>
>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>> manufacturers can use with lp5024P?
>>>>>>>
>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>> manufacturers can use with lp5024P?
>>>>>>>
>>>>>>
>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>> But everyone interprets colors differently.
>>>>>>
>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>> Most probably not.
>>>>>>
>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>
>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>> scales down to the hand helds and smart home applications.
>>>>>>
>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>
>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>> coefficients.
>>>>>>
>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>> The colors should be close but may not be identical.
>>>>>>
>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>> light pipe and LED driver technology.
>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>
>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>> a hardware aspect to the calculation.
>>>>>>
>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>
>>>>>>>> Monitors are not an application for this part.
>>>>>>>
>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>> same yellow the rest of world talks about?
>>>>>>>
>>>>>>
>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>
>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>> I have.
>>>>>>>>
>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>
>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>> colors?
>>>>>>>
>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>
>>>>>>
>>>>>> Good suggestion for a rough test.
>>>>>>
>>>>>>>>> But...
>>>>>>>>>
>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>> interface?
>>>>>>>>
>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>
>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>> should work there, too.
>>>>>>>
>>>>>>
>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>
>>>>>>>> <rant>
>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>> I would rather design against something you want instead of having
>>>>>>>> everyone complain about every implementation I post.
>>>>>>>> </rant>
>>>>>>>
>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>> interfaces work, and are doing that badly.
>>>>>>>
>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>> kernel.
>>>>>>>
>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>
>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>> them.
>>>>>>>
>>>>>>
>>>>>> Sigh. You did not answer my question.
>>>>>>
>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>> RGB LED landscape.
>>>>>>
>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>> maybe color capabilities but not specific colors.
>>>>>
>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>> then please go ahead. It would be good to compare colors produced
>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>> LEDn_BRIGHTNESS feature.
>>>>>
>>>>> The requirements for LED RGB class as I would see it:
>>>>>
>>>>> sysfs interface:
>>>>>
>>>>> brightness-model: space separated list of available options:
>>>>> - rgb (default):
>>>>> - creates color file with "red green blue" decimal values
>>>>
>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>> Should the LED color come from the DT?
>>>>
>>>
>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>> But should they have the same interfaces as RGB?
>>>
>>> Should PWM control be a global interface?
>>
>> In order to being able to set multi color element led at one go I would recommend using then model:
>>
>> color_names: "red green blue white"
>>
>> echo "32 43 0 128" > color
>>
>> This way all elements would be set at same time from user space point of view.
>>
>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>
>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>
>> - red, green, blue
>> - red, green, blue, amber
>> - red, green, blue, white
>> - red, green, blue, white - cool
>> - red, green, blue, white - neutral
>> - red, green, blue, white - warm
>> - red, orange
>> - purple, ultraviolet
>> - amber, blue
>> - amber, blue, cyan, green, red, violet, white - cool
>> - amber, blue, green
>> - amber, green, blue
>> - and then lots of single special colors
>
> It suggested me another solution. Instead of LED RGB class
> we would have LED multi-color class.
>
I was thinking the same thing this morning. But I was thinking that the RGB
class should be an additional class to stand on its own or can register to the
multi color class.
> Sysfs interface design:
> -----------------------
>
> colors: directory containing files that map to
> the brightness of particular LEDs; there
> would be predefined color names that LED class
> driver should map iouts to, e.g.:
Filling in the missing ideas with questions.
Is it a directory or a file? If it is a directory does that not break the current
directory label model?
so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
They are assigned to different triggers and have different directories. Both are GPIO controlled.
Or are you saying it would be something like (More then likely this is what you intended)
/sys/class/leds/input4::numlock/colors?
Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
knows that this is a multi color class and not a single LED color class.
What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
variants when RGB is only available? And this can also present a single write to the kernel with the new
color values.
I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
colors.
Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
if we start adding defines like white_warm, white_neutral and other variations to the color.
What about IR LEDs used for night vision products? Do these fall into the multi color class?
We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
flash class but it could be a multi color LED as well.
How would traversing through the full color palette work if you were to want to produce a multi
color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
Or in a product like the gaming keyboards that will change color or change backlight brightness?
Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
capable of doing this?
https://www.youtube.com/watch?v=pfKv3g2FeBE
or something like this
https://www.youtube.com/watch?v=PO3auX3f5C4
The LP5036 has this capability.
> - red
> - green
> - blue
> - white
> - sync: accepts "write" and "read", which executes
> write/readout to/from a device respectively.
>
What are these above, the values or the files under the colors directory?
I am assuming they are files.
Are they mandatory or optional?
> brightness-model: defines brightness level to color configuration
> mapping
> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
> - "rgb-<hue>": available only when all three red,green,blue colors
> are present in the colors directory.
> <hue> is a placeholder for given DT hue presets.
> - "rgbw-<hue>": Same as above, but available only when white color
> (any of amber or white-{cool|neutral|warm} can be
> mapped to white) is also available. In this mode
> max_brightness equals num-of-hue-presets + 1, and
> max_brightness, when set, turns the "white" LED on
Why do we need white combined here? Should this not be its own entity?
Again I don't like limiting the color palette from the DT. I think that the
user space can see what colors are available for that device and makes its own
decision on what color to present.
For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
same function trying to be achieved by the system designer? The RGB can be used to denote
notification status and the white can be used to denote that a charger is connected. Motorola
Droid did this.
> - "rgb-linear": I'm not sure if it should be available - it will
> have unpredictable results
>
> brightness: sets/reads brightness in the way specific to the
> current brightness-model. When more colors are available
> (e.g. amber, blue, cyan, green, red, violet, white), they
> are not touched by write to brightness).
>
> HSV->RGB conversion is left entirely to the userspace, which can set any
> color with use of the proposed interface.
>
> Let's agree on sysfs interface first, and only after that move
> to the DT details.
>
DT's are meant to describe hardware and not describe the product. Unless Rob does not see
an issue with defining product capabilities in the DT then we should keep that out of the DT.
Dan
> Best regards,
> Jacek Anaszewski
>
>> Better models even list some properties about how different color elements behave.
>>
>> I would expect red, green, blue to be the most common case. So automating for that for chip like what you are working now is reasonable.
>>
>> For simple case where we can expect red, green, blue mapping we can auto-configure the multi color element led with "red", "green" and "blue" color elements.
>>
>> But TI also have other kind of driver chips that could be used in "more freely" enabling use all of those combos.
>>
>> If user would have "amber", "green" and "blue" then we would need to add this definition in devicetree in order for user space to be able to recognize that now we have different config.
>>
>> Or if user would have most complex of those then in devicetree you would configure 7 color element led like "amber", "blue", "cyan", "green", "red", "violet", "white" as color elements.
>>
>> Then you could set them in one go:
>> echo "32 76 43 2 43 76 54" > color
>>
>> Now in this special case if we would have hsl brightness model and lets say it only knows red, green and blue. Then it would pick red, green and blue color element names and only adjust those others would be linear should there be non-zero value.
>>
>> In this case however you might be better doing it in user space as it might be preferable to control all values let say in sRGB space and then let the software transform result to all color elements and then setup entries to kernel. In here the ICC color profile might be the way to go to model your let and let user space software do the fancier math.
>>
>> As this latest example is the fanciest I would like to remind that the red, green, blue is the most common. I would make their life easier and then when you go to more advanced setups then you are are already mentally ready to do more complex things :)
>>
>> As an example in our case we can do with "red", "green", and "red", "green", "blue" combos fill all our current requirements we have. Perhaps white could be added as one thing in future (white is currently used only in lcd module's background).
>>
>> Latest proposal I have for the interface now lets you do all of those things so it should be easy enough for most cases and still flexes to more complex cases while keeping kernel space simple.
>>
>> Thanks,
>> Vesa Jääskeläinen
>>
>
>
--
------------------
Dan Murphy
Dan,
On 1/22/19 11:44 PM, Dan Murphy wrote:
> Jacek
>
> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>> Hi all,
>>
>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>> Hi Dan,
>>>
>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>> Jacek
>>>>
>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>> Jacek
>>>>>
>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>> Hi Dan,
>>>>>>
>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>> Hello
>>>>>>>
>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>> Hi!
>>>>>>>>
>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>> Hi!
>>>>>>>>>>
>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>> +
>>>>>>>>>>>> +Example:
>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>> +
>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>> +
>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>
>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>> like.
>>>>>>>>>>
>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>
>>>>>>>>> What?
>>>>>>>>
>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>
>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>
>>>>>>>
>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>> But everyone interprets colors differently.
>>>>>>>
>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>> Most probably not.
>>>>>>>
>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>
>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>
>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>
>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>> coefficients.
>>>>>>>
>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>> The colors should be close but may not be identical.
>>>>>>>
>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>> light pipe and LED driver technology.
>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>
>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>> a hardware aspect to the calculation.
>>>>>>>
>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>
>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>
>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>
>>>>>>>
>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>
>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>> I have.
>>>>>>>>>
>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>
>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>> colors?
>>>>>>>>
>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>
>>>>>>>
>>>>>>> Good suggestion for a rough test.
>>>>>>>
>>>>>>>>>> But...
>>>>>>>>>>
>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>> interface?
>>>>>>>>>
>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>
>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>> should work there, too.
>>>>>>>>
>>>>>>>
>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>
>>>>>>>>> <rant>
>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>> </rant>
>>>>>>>>
>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>
>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>> kernel.
>>>>>>>>
>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>
>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>> them.
>>>>>>>>
>>>>>>>
>>>>>>> Sigh. You did not answer my question.
>>>>>>>
>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>> RGB LED landscape.
>>>>>>>
>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>> maybe color capabilities but not specific colors.
>>>>>>
>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>
>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>
>>>>>> sysfs interface:
>>>>>>
>>>>>> brightness-model: space separated list of available options:
>>>>>> - rgb (default):
>>>>>> - creates color file with "red green blue" decimal values
>>>>>
>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>> Should the LED color come from the DT?
>>>>>
>>>>
>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>> But should they have the same interfaces as RGB?
>>>>
>>>> Should PWM control be a global interface?
>>>
>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>
>>> color_names: "red green blue white"
>>>
>>> echo "32 43 0 128" > color
>>>
>>> This way all elements would be set at same time from user space point of view.
>>>
>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>
>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>
>>> - red, green, blue
>>> - red, green, blue, amber
>>> - red, green, blue, white
>>> - red, green, blue, white - cool
>>> - red, green, blue, white - neutral
>>> - red, green, blue, white - warm
>>> - red, orange
>>> - purple, ultraviolet
>>> - amber, blue
>>> - amber, blue, cyan, green, red, violet, white - cool
>>> - amber, blue, green
>>> - amber, green, blue
>>> - and then lots of single special colors
>>
>> It suggested me another solution. Instead of LED RGB class
>> we would have LED multi-color class.
>>
>
> I was thinking the same thing this morning. But I was thinking that the RGB
> class should be an additional class to stand on its own or can register to the
> multi color class.
>
>> Sysfs interface design:
>> -----------------------
>>
>> colors: directory containing files that map to
>> the brightness of particular LEDs; there
>> would be predefined color names that LED class
>> driver should map iouts to, e.g.:
>
> Filling in the missing ideas with questions.
>
> Is it a directory or a file? If it is a directory does that not break the current
> directory label model?
>
> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>
> Or are you saying it would be something like (More then likely this is what you intended)
> /sys/class/leds/input4::numlock/colors?
Yes, this is what I meant.
> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
> knows that this is a multi color class and not a single LED color class.
Like I am going to come up with standardized color names
in my LED naming related patch, the multi-color names
can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
> variants when RGB is only available? And this can also present a single write to the kernel with the new
> color values.
My design already covers that in the form of files in the colors
directory. Like I stated: "files that map to the brightness of
particular LEDs". Single write is secured by "echo "write" > sync.
> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
> colors.
> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
> if we start adding defines like white_warm, white_neutral and other variations to the color.
We would not limit anything. Every color combination can be achieved
by following this exemplary sequence:
$ echo 154 > colors/red
$ echo 232 > colors/green
$ echo 43 > colors/blue
# echo "write" > sync //only this changes hardware state
brightness-model is provided only to define mapping of legacy brightness
levels (governed by brightness file and led_set_brightness() API) to
the specific combination of colors.
For instance we can define three brightness levels for green hue:
DT definition for it would look like below:
rgb-green = <0x277c33 0x37b048 0x47e45d>;
LED multi color class would then do the following mapping for
each of the three brightness levels for rgb-green brightness model:
$ echo rgb-green > brightness_model
$ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
$ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
$ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
> What about IR LEDs used for night vision products? Do these fall into the multi color class?
> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
> flash class but it could be a multi color LED as well.
>
> How would traversing through the full color palette work if you were to want to produce a multi
> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
> Or in a product like the gaming keyboards that will change color or change backlight brightness?
This is not meant as a solution for pattern generator but for
consolidated source of multi color light. In the simplest case
RGB LED elements like those used for lp5024 reference board,
but it could be RGBWAUV LED [0] as well.
For patterns traversing many LEDs I see a trigger as the best solution.
Hmm, now I see that trigger mechanism actually can serve as very
flexible pattern generator.
We would need a device that could be configured to register
a number of multi-led-patternN triggers, one per LED, and generate
events for each trigger in a loop.
The device would have to allow for configuring pattern intervals
via sysfs, like in case of current pattern trigger.
LED class devices would have to register for its events:
$/sys/class/leds/led1 echo multi-led-pattern1 > trigger
$/sys/class/leds/led2 echo multi-led-pattern2 > trigger
$/sys/class/leds/led3 echo multi-led-pattern3 > trigger
The ability to define brightness models in DT would
add even more flexibility.
> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
> capable of doing this?
>
> https://www.youtube.com/watch?v=pfKv3g2FeBE
> or something like this
>
> https://www.youtube.com/watch?v=PO3auX3f5C4
>
> The LP5036 has this capability.
>
>> - red
>> - green
>> - blue
>> - white
>> - sync: accepts "write" and "read", which executes
>> write/readout to/from a device respectively.
>>
>
> What are these above, the values or the files under the colors directory?
They are just color specific counterparts of monochrome brightness.
In terms of lp50xx they would map to OUTn_COLOR registers.
> I am assuming they are files.
Right.
> Are they mandatory or optional?
Mandatory, one per each iout to control.
>> brightness-model: defines brightness level to color configuration
>> mapping
>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>> - "rgb-<hue>": available only when all three red,green,blue colors
>> are present in the colors directory.
>> <hue> is a placeholder for given DT hue presets.
>> - "rgbw-<hue>": Same as above, but available only when white color
>> (any of amber or white-{cool|neutral|warm} can be
>> mapped to white) is also available. In this mode
>> max_brightness equals num-of-hue-presets + 1, and
>> max_brightness, when set, turns the "white" LED on
>
> Why do we need white combined here? Should this not be its own entity?
To be able to set white color. We're still talking about one LED
element (although they can be be physically few LEDs in one case).
This is brightness file, so we've got to stick to the semantics.
Max brightness level should be the brightest. With RGBW LEDs we
fortunately have a means to achieve pure white, that's why
rgbw-<hue> would be beneficial. If you increase L component of
HSL color space, the max value gives white for all hues.
So maybe this brightness-model would be rather called hsl-<hue>.
For RGBW LEDs, we would have to allow for more shades of white too,
like in [1].
> Again I don't like limiting the color palette from the DT. I think that the
> user space can see what colors are available for that device and makes its own
> decision on what color to present.
>
> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
> same function trying to be achieved by the system designer? The RGB can be used to denote
> notification status and the white can be used to denote that a charger is connected. Motorola
> Droid did this.
I hope I've just clarified my idea.
>
>> - "rgb-linear": I'm not sure if it should be available - it will
>> have unpredictable results
>>
>> brightness: sets/reads brightness in the way specific to the
>> current brightness-model. When more colors are available
>> (e.g. amber, blue, cyan, green, red, violet, white), they
>> are not touched by write to brightness).
>>
>> HSV->RGB conversion is left entirely to the userspace, which can set any
>> color with use of the proposed interface.
>>
>> Let's agree on sysfs interface first, and only after that move
>> to the DT details.
>>
>
> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
> an issue with defining product capabilities in the DT then we should keep that out of the DT.
LED element is a device. I see nothing irrelevant for DT in describing
the lighting specificity of a device mounted on the board. Please keep
in mind that it will not limit the number of colors available to set.
It will only allow to define mapping of brightness level to color.
We need that for current trigger mechanism to work with LED multi-color
class.
[0]
http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
[1] https://www.youtube.com/watch?v=NzlFmTqOh9M
--
Best regards,
Jacek Anaszewski
Jacek
Replying to code comments.
On 1/15/19 3:47 PM, Jacek Anaszewski wrote:
> Hi Da,
>
> Thank you for the v2.
>
I will probably submit v3 outside the realm of the multi color framework.
We can always convert as Pavel pointed out.
> I have some remarks below.
>
> On 1/14/19 10:17 PM, Dan Murphy wrote:
>> Introduce the LP5036/30/24/18 RGB LED driver.
>> The difference in these parts are the number of
>> LED outputs where the:
>>
>> LP5036 can control 36 LEDs
>> LP5030 can control 30 LEDs
>> LP5024 can control 24 LEDs
>> LP5018 can control 18 LEDs
>>
>> The device has the ability to group LED output into control banks
>> so that multiple LED banks can be controlled with the same mixing and
>> brightness. Inversely the LEDs can also be controlled independently.
>>
>> Signed-off-by: Dan Murphy <[email protected]>
>> ---
>>
>> v2 - Changed the mix and module files to a single "color" file, added the LP5030
>> and LP5036 register mapping, added ABI documentation, updated the parsing of
>> DT and led sources to match DT, renamed driver to leds-lp50xx.c - https://lore.kernel.org/patchwork/patch/1026515/
>>
>> Documentation/leds/leds-lp50xx.txt | 36 ++
>> drivers/leds/Kconfig | 7 +
>> drivers/leds/Makefile | 1 +
>> drivers/leds/leds-lp50xx.c | 754 +++++++++++++++++++++++++++++
>> 4 files changed, 798 insertions(+)
>> create mode 100644 Documentation/leds/leds-lp50xx.txt
>> create mode 100644 drivers/leds/leds-lp50xx.c
>>
>> diff --git a/Documentation/leds/leds-lp50xx.txt b/Documentation/leds/leds-lp50xx.txt
>
> Please move it to
>
> Documentation/ABI/testing/sysfs-class-led-driver-lp50xx
>
> and use standard ABI documentation format.
>
Ack. I will add this file as well per the doc format.
>
>> new file mode 100644
>> index 000000000000..8b1b01dfdd22
>> --- /dev/null
>> +++ b/Documentation/leds/leds-lp50xx.txt
>> @@ -0,0 +1,36 @@
>> +LP5018/LP5024/LP5030/LP5036 Common Driver
>> +=================================================
>> +
>> +Authors: Dan Murphy <[email protected]>
>> +
>> +Description
>> +-----------
>> +The LP50XX RGB LED drivers have the ability to group multiple RGB cluster
>> +LEDs into a single group for simultaneous control or expose single RGB cluster
>> +for control. This device exposes different register interfaces to control
>> +the cluster brightness as well as the individual RGB LEDs color intensity.
>> +
>> +RGB Cluster Color Control
>> +-------------------------
>> +The LP50xx driver will expose a file called "color" for each LED class instance
>> +defined. This file will accept a 24-bit RGB value in which the the color of the
>> +RGB LEDs will be set.
>> +
>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>> +XX - Do not care ignored by the driver
>> +RR - is the 8 bit Red LED value
>> +GG - is the 8 bit Green LED value
>> +BB - is the 8 bit Blue LED value
>> +
>> +Example:
>> +LED module output 4 of the LP5024 will be a yellow color:
>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>> +
>> +LED module output 4 of the LP5024 will be dimmed 50%:
>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>> +
>> +LED banked RGBs of the LP5036 will be a white color:
>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>
> This part with example cans remain in Documentation/leds if you like.
>
>> +
>> +LED banked RGBs of the LP50364 will be dimmed 50%:
>> +echo 0x80 > /sys/class/leds/lp5036\:led_banked/brightness
>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
>> index a72f97fca57b..5f413445a667 100644
>> --- a/drivers/leds/Kconfig
>> +++ b/drivers/leds/Kconfig
>> @@ -326,6 +326,13 @@ config LEDS_LP3952
>> To compile this driver as a module, choose M here: the
>> module will be called leds-lp3952.
>> +config LEDS_LP50XX
>> + tristate "LED Support for TI LP5036/30/24/18 LED driver chip"
>> + depends on LEDS_CLASS && REGMAP_I2C
>> + help
>> + If you say yes here you get support for the Texas Instruments
>> + LP5036, LP5030, LP5024 and LP5018 LED driver.
>> +
>> config LEDS_LP55XX_COMMON
>> tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
>> depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
>> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
>> index 4c1b0054f379..852eff0b773f 100644
>> --- a/drivers/leds/Makefile
>> +++ b/drivers/leds/Makefile
>> @@ -32,6 +32,7 @@ obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
>> obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
>> obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
>> obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o
>> +obj-$(CONFIG_LEDS_LP50XX) += leds-lp50xx.o
>> obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o
>> obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
>> obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
>> diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
>> new file mode 100644
>> index 000000000000..41bb2e0129c8
>> --- /dev/null
>> +++ b/drivers/leds/leds-lp50xx.c
>> @@ -0,0 +1,754 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* TI LP50XX LED chip family driver
>> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
>> + */
>
> Let's use uniform "//" comment style here.
Ack
>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/i2c.h>
>> +#include <linux/init.h>
>> +#include <linux/leds.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/of.h>
>> +#include <linux/of_gpio.h>
>> +#include <linux/regmap.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/slab.h>
>> +#include <uapi/linux/uleds.h>
>> +
>> +#define LP50XX_DEV_CFG0 0x00
>> +#define LP50XX_DEV_CFG1 0x01
>> +#define LP50XX_LED_CFG0 0x02
>> +
>> +/* LP5018 and LP5024 registers */
>> +#define LP5024_BNK_BRT 0x03
>> +#define LP5024_BNKA_CLR 0x04
>> +#define LP5024_BNKB_CLR 0x05
>> +#define LP5024_BNKC_CLR 0x06
>> +#define LP5024_LED0_BRT 0x07
>> +#define LP5024_LED1_BRT 0x08
>> +#define LP5024_LED2_BRT 0x09
>> +#define LP5024_LED3_BRT 0x0a
>> +#define LP5024_LED4_BRT 0x0b
>> +#define LP5024_LED5_BRT 0x0c
>> +#define LP5024_LED6_BRT 0x0d
>> +#define LP5024_LED7_BRT 0x0e
>> +
>> +#define LP5024_OUT0_CLR 0x0f
>> +#define LP5024_OUT1_CLR 0x10
>> +#define LP5024_OUT2_CLR 0x11
>> +#define LP5024_OUT3_CLR 0x12
>> +#define LP5024_OUT4_CLR 0x13
>> +#define LP5024_OUT5_CLR 0x14
>> +#define LP5024_OUT6_CLR 0x15
>> +#define LP5024_OUT7_CLR 0x16
>> +#define LP5024_OUT8_CLR 0x17
>> +#define LP5024_OUT9_CLR 0x18
>> +#define LP5024_OUT10_CLR 0x19
>> +#define LP5024_OUT11_CLR 0x1a
>> +#define LP5024_OUT12_CLR 0x1b
>> +#define LP5024_OUT13_CLR 0x1c
>> +#define LP5024_OUT14_CLR 0x1d
>> +#define LP5024_OUT15_CLR 0x1e
>> +#define LP5024_OUT16_CLR 0x1f
>> +#define LP5024_OUT17_CLR 0x20
>> +#define LP5024_OUT18_CLR 0x21
>> +#define LP5024_OUT19_CLR 0x22
>> +#define LP5024_OUT20_CLR 0x23
>> +#define LP5024_OUT21_CLR 0x24
>> +#define LP5024_OUT22_CLR 0x25
>> +#define LP5024_OUT23_CLR 0x26
>> +#define LP5024_RESET 0x27
>> +
>> +/* LP5030 and LP5036 registers */
>> +#define LP5036_LED_CFG1 0x03
>> +#define LP5036_BNK_BRT 0x04
>> +#define LP5036_BNKA_CLR 0x05
>> +#define LP5036_BNKB_CLR 0x06
>> +#define LP5036_BNKC_CLR 0x07
>> +#define LP5036_LED0_BRT 0x08
>> +#define LP5036_LED1_BRT 0x09
>> +#define LP5036_LED2_BRT 0x0a
>> +#define LP5036_LED3_BRT 0x0b
>> +#define LP5036_LED4_BRT 0x0c
>> +#define LP5036_LED5_BRT 0x0d
>> +#define LP5036_LED6_BRT 0x0e
>> +#define LP5036_LED7_BRT 0x0f
>> +#define LP5036_LED8_BRT 0x10
>> +#define LP5036_LED9_BRT 0x11
>> +#define LP5036_LED10_BRT 0x12
>> +#define LP5036_LED11_BRT 0x13
>> +
>> +#define LP5036_OUT0_CLR 0x14
>> +#define LP5036_OUT1_CLR 0x15
>> +#define LP5036_OUT2_CLR 0x16
>> +#define LP5036_OUT3_CLR 0x17
>> +#define LP5036_OUT4_CLR 0x18
>> +#define LP5036_OUT5_CLR 0x19
>> +#define LP5036_OUT6_CLR 0x1a
>> +#define LP5036_OUT7_CLR 0x1b
>> +#define LP5036_OUT8_CLR 0x1c
>> +#define LP5036_OUT9_CLR 0x1d
>> +#define LP5036_OUT10_CLR 0x1e
>> +#define LP5036_OUT11_CLR 0x1f
>> +#define LP5036_OUT12_CLR 0x20
>> +#define LP5036_OUT13_CLR 0x21
>> +#define LP5036_OUT14_CLR 0x22
>> +#define LP5036_OUT15_CLR 0x23
>> +#define LP5036_OUT16_CLR 0x24
>> +#define LP5036_OUT17_CLR 0x25
>> +#define LP5036_OUT18_CLR 0x26
>> +#define LP5036_OUT19_CLR 0x27
>> +#define LP5036_OUT20_CLR 0x28
>> +#define LP5036_OUT21_CLR 0x29
>> +#define LP5036_OUT22_CLR 0x2a
>> +#define LP5036_OUT23_CLR 0x2b
>> +#define LP5036_OUT24_CLR 0x2c
>> +#define LP5036_OUT25_CLR 0x2d
>> +#define LP5036_OUT26_CLR 0x2e
>> +#define LP5036_OUT27_CLR 0x2f
>> +#define LP5036_OUT28_CLR 0x30
>> +#define LP5036_OUT29_CLR 0x31
>> +#define LP5036_OUT30_CLR 0x32
>> +#define LP5036_OUT31_CLR 0x33
>> +#define LP5036_OUT32_CLR 0x34
>> +#define LP5036_OUT33_CLR 0x35
>> +#define LP5036_OUT34_CLR 0x36
>> +#define LP5036_OUT35_CLR 0x37
>> +#define LP5036_RESET 0x38
>> +
>> +#define LP50XX_SW_RESET 0xff
>> +
>> +#define LP50XX_CHIP_EN BIT(6)
>> +
>> +#define LP5018_MAX_LED_STRINGS 6
>> +#define LP5024_MAX_LED_STRINGS 8
>> +#define LP5030_MAX_LED_STRINGS 10
>> +#define LP5036_MAX_LED_STRINGS 12
>> +
>> +enum lp50xx_model {
>> + LP5018,
>> + LP5024,
>> + LP5030,
>> + LP5036,
>> +};
>> +
>> +struct lp50xx_led {
>> + u32 led_strings[LP5036_MAX_LED_STRINGS];
>
> It is possible to have only one bank, so this can be a property
> of struct lp50xx. Moreover, it doesn't need to be an array,
> but should be:
>
> unsigned long bank_modules;
>
> Then you will be able to use bitops on it, where bit position will
> refer to the id of RGB LED module assigned to the bank.
>
ACK. Had to think a bit on this to make sure there was enough room
but aligning on LEDn_MODULES/BANKS should be fine
>> + char label[LED_MAX_NAME_SIZE];
>> + struct led_classdev led_dev;
>> + struct lp50xx *priv;
>> + int led_number;
>> + u8 ctrl_bank_enabled;
>> +};
>> +
>> +/**
>> + * struct lp50xx -
>> + * @enable_gpio: Hardware enable gpio
>> + * @regulator: LED supply regulator pointer
>> + * @client: Pointer to the I2C client
>> + * @regmap: Devices register map
>> + * @dev: Pointer to the devices device struct
>> + * @lock: Lock for reading/writing the device
>> + * @model_id: ID of the device
>> + * @leds: Array of LED strings
>
> Please don't use capital letters for property description.
> Still, some of the properties below remain undocumented.
>
You are referring to ID and I2C or do you mean no capitals to start the
description?
Yes I added the properties and missed documenting them.
>> + */
>> +struct lp50xx {
>> + struct gpio_desc *enable_gpio;
>> + struct regulator *regulator;
>> + struct i2c_client *client;
>> + struct regmap *regmap;
>> + struct device *dev;
>> + struct mutex lock;
>> + enum lp50xx_model model_id;
>> + int max_leds;
>> + int num_of_leds;
>> +
>> + u8 led_brightness0_reg;
>> + u8 mix_out0_reg;
>> + u8 bank_brt_reg;
>> + u8 bank_mix_reg;
>> + u8 reset_reg;
>> +
>> + /* This needs to be at the end of the struct */
>> + struct lp50xx_led leds[];
>> +};
>> +
>> +static const struct reg_default lp5024_reg_defs[] = {
>> + {LP50XX_DEV_CFG0, 0x0},
>> + {LP50XX_DEV_CFG1, 0x3c},
>> + {LP50XX_LED_CFG0, 0x0},
>> + {LP5024_BNK_BRT, 0xff},
>> + {LP5024_BNKA_CLR, 0x0f},
>> + {LP5024_BNKB_CLR, 0x0f},
>> + {LP5024_BNKC_CLR, 0x0f},
>> + {LP5024_LED0_BRT, 0x0f},
>> + {LP5024_LED1_BRT, 0xff},
>> + {LP5024_LED2_BRT, 0xff},
>> + {LP5024_LED3_BRT, 0xff},
>> + {LP5024_LED4_BRT, 0xff},
>> + {LP5024_LED5_BRT, 0xff},
>> + {LP5024_LED6_BRT, 0xff},
>> + {LP5024_LED7_BRT, 0xff},
>> + {LP5024_OUT0_CLR, 0x0f},
>> + {LP5024_OUT1_CLR, 0x00},
>> + {LP5024_OUT2_CLR, 0x00},
>> + {LP5024_OUT3_CLR, 0x00},
>> + {LP5024_OUT4_CLR, 0x00},
>> + {LP5024_OUT5_CLR, 0x00},
>> + {LP5024_OUT6_CLR, 0x00},
>> + {LP5024_OUT7_CLR, 0x00},
>> + {LP5024_OUT8_CLR, 0x00},
>> + {LP5024_OUT9_CLR, 0x00},
>> + {LP5024_OUT10_CLR, 0x00},
>> + {LP5024_OUT11_CLR, 0x00},
>> + {LP5024_OUT12_CLR, 0x00},
>> + {LP5024_OUT13_CLR, 0x00},
>> + {LP5024_OUT14_CLR, 0x00},
>> + {LP5024_OUT15_CLR, 0x00},
>> + {LP5024_OUT16_CLR, 0x00},
>> + {LP5024_OUT17_CLR, 0x00},
>> + {LP5024_OUT18_CLR, 0x00},
>> + {LP5024_OUT19_CLR, 0x00},
>> + {LP5024_OUT20_CLR, 0x00},
>> + {LP5024_OUT21_CLR, 0x00},
>> + {LP5024_OUT22_CLR, 0x00},
>> + {LP5024_OUT23_CLR, 0x00},
>> + {LP5024_RESET, 0x00}
>> +};
>> +
>> +static const struct reg_default lp5036_reg_defs[] = {
>> + {LP50XX_DEV_CFG0, 0x0},
>> + {LP50XX_DEV_CFG1, 0x3c},
>> + {LP50XX_LED_CFG0, 0x0},
>> + {LP5036_LED_CFG1, 0x0},
>> + {LP5036_BNK_BRT, 0xff},
>> + {LP5036_BNKA_CLR, 0x0f},
>> + {LP5036_BNKB_CLR, 0x0f},
>> + {LP5036_BNKC_CLR, 0x0f},
>> + {LP5036_LED0_BRT, 0x0f},
>> + {LP5036_LED1_BRT, 0xff},
>> + {LP5036_LED2_BRT, 0xff},
>> + {LP5036_LED3_BRT, 0xff},
>> + {LP5036_LED4_BRT, 0xff},
>> + {LP5036_LED5_BRT, 0xff},
>> + {LP5036_LED6_BRT, 0xff},
>> + {LP5036_LED7_BRT, 0xff},
>> + {LP5036_OUT0_CLR, 0x0f},
>> + {LP5036_OUT1_CLR, 0x00},
>> + {LP5036_OUT2_CLR, 0x00},
>> + {LP5036_OUT3_CLR, 0x00},
>> + {LP5036_OUT4_CLR, 0x00},
>> + {LP5036_OUT5_CLR, 0x00},
>> + {LP5036_OUT6_CLR, 0x00},
>> + {LP5036_OUT7_CLR, 0x00},
>> + {LP5036_OUT8_CLR, 0x00},
>> + {LP5036_OUT9_CLR, 0x00},
>> + {LP5036_OUT10_CLR, 0x00},
>> + {LP5036_OUT11_CLR, 0x00},
>> + {LP5036_OUT12_CLR, 0x00},
>> + {LP5036_OUT13_CLR, 0x00},
>> + {LP5036_OUT14_CLR, 0x00},
>> + {LP5036_OUT15_CLR, 0x00},
>> + {LP5036_OUT16_CLR, 0x00},
>> + {LP5036_OUT17_CLR, 0x00},
>> + {LP5036_OUT18_CLR, 0x00},
>> + {LP5036_OUT19_CLR, 0x00},
>> + {LP5036_OUT20_CLR, 0x00},
>> + {LP5036_OUT21_CLR, 0x00},
>> + {LP5036_OUT22_CLR, 0x00},
>> + {LP5036_OUT23_CLR, 0x00},
>> + {LP5036_OUT24_CLR, 0x00},
>> + {LP5036_OUT25_CLR, 0x00},
>> + {LP5036_OUT26_CLR, 0x00},
>> + {LP5036_OUT27_CLR, 0x00},
>> + {LP5036_OUT28_CLR, 0x00},
>> + {LP5036_OUT29_CLR, 0x00},
>> + {LP5036_OUT30_CLR, 0x00},
>> + {LP5036_OUT31_CLR, 0x00},
>> + {LP5036_OUT32_CLR, 0x00},
>> + {LP5036_OUT33_CLR, 0x00},
>> + {LP5036_OUT34_CLR, 0x00},
>> + {LP5036_OUT35_CLR, 0x00},
>> + {LP5036_RESET, 0x00}
>> +};
>> +
>> +static const struct regmap_config lp5024_regmap_config = {
>> + .reg_bits = 8,
>> + .val_bits = 8,
>> +
>> + .max_register = LP5024_RESET,
>> + .reg_defaults = lp5024_reg_defs,
>> + .num_reg_defaults = ARRAY_SIZE(lp5024_reg_defs),
>> + .cache_type = REGCACHE_RBTREE,
>> +};
>> +
>> +static const struct regmap_config lp5036_regmap_config = {
>> + .reg_bits = 8,
>> + .val_bits = 8,
>> +
>> + .max_register = LP5036_RESET,
>> + .reg_defaults = lp5036_reg_defs,
>> + .num_reg_defaults = ARRAY_SIZE(lp5036_reg_defs),
>> + .cache_type = REGCACHE_RBTREE,
>> +};
>> +
>> +static ssize_t color_show(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>> + led_dev);
>> + struct lp50xx *priv = led->priv;
>> + unsigned int red_val, green_val, blue_val;
>> + u8 red_reg, green_reg, blue_reg;
>> + u32 mix_value = 0;
>> + u8 led_offset;
>> + int ret;
>> +
>> + if (led->ctrl_bank_enabled) {
>> + red_reg = priv->bank_mix_reg;
>> + green_reg = priv->bank_mix_reg + 1;
>> + blue_reg = priv->bank_mix_reg + 2;
>> + } else {
>> + led_offset = (led->led_number * 3);
>> + red_reg = priv->mix_out0_reg + led_offset;
>> + green_reg = priv->mix_out0_reg + led_offset + 1;
>> + blue_reg = priv->mix_out0_reg + led_offset + 2;
>> + }
>> +
>> + ret = regmap_read(priv->regmap, red_reg, &red_val);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot read LED value\n");
>> + goto out;
>> + }
>> +
>> + ret = regmap_read(priv->regmap, green_reg, &green_val);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot read LED value\n");
>> + goto out;
>> + }
>> +
>> + ret = regmap_read(priv->regmap, blue_reg, &blue_val);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot read LED value\n");
>> + goto out;
>> + }
>> +
>> + mix_value = (red_val << 16 | green_val << 8 | blue_val);
>> +
>> +out:
>> + return scnprintf(buf, PAGE_SIZE, "0x%X\n", mix_value);
>> +}
>> +
>> +static ssize_t color_store(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf, size_t size)
>> +{
>> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>> + led_dev);
>> + struct lp50xx *priv = led->priv;
>> + u8 led_offset;
>> + unsigned long mix_value;
>> + u8 red_reg, green_reg, blue_reg;
>> + u8 red_val, green_val, blue_val;
>> + int ret;
>> +
>> + ret = kstrtoul(buf, 0, &mix_value);
>> + if (ret)
>> + return ret;
>> +
>> + if (led->ctrl_bank_enabled) {
>> + red_reg = priv->bank_mix_reg;
>> + green_reg = priv->bank_mix_reg + 1;
>> + blue_reg = priv->bank_mix_reg + 2;
>> + } else {
>> + led_offset = (led->led_number * 3);
>> + red_reg = priv->mix_out0_reg + led_offset;
>> + green_reg = priv->mix_out0_reg + led_offset + 1;
>> + blue_reg = priv->mix_out0_reg + led_offset + 2;
>> + }
>> +
>> + red_val = (mix_value & 0xff0000) >> 16;
>> + green_val = (mix_value & 0xff00) >> 8;
>> + blue_val = (mix_value & 0xff);
>
> I've been rather thinking about space separated list of decimal
> "red green blue" values, but maybe this way it will be less
> controversial. Let's if there will be other opinions.
>
Has anything changed based on this?
Should I change the file name from "color" to something else?
>> +
>> + ret = regmap_write(priv->regmap, red_reg, red_val);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot write LED value\n");
>> + goto out;
>> + }
>> +
>> + ret = regmap_write(priv->regmap, green_reg, green_val);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot write LED value\n");
>> + goto out;
>> + }
>> +
>> + ret = regmap_write(priv->regmap, blue_reg, blue_val);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot write LED value\n");
>> + goto out;
>> + }
>> +out:
>> + return size;
>> +}
>> +
>> +static DEVICE_ATTR_RW(color);
>> +
>> +static struct attribute *lp50xx_led_color_attrs[] = {
>> + &dev_attr_color.attr,
>> + NULL
>> +};
>> +ATTRIBUTE_GROUPS(lp50xx_led_color);
>> +
>> +static int lp50xx_brightness_set(struct led_classdev *led_cdev,
>> + enum led_brightness brt_val)
>> +{
>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>> + led_dev);
>> + int ret = 0;
>> + u8 reg_val;
>> +
>> + mutex_lock(&led->priv->lock);
>> +
>> + if (led->ctrl_bank_enabled)
>> + reg_val = led->priv->bank_brt_reg;
>> + else
>> + reg_val = led->priv->led_brightness0_reg + led->led_number;
>> +
>> + ret = regmap_write(led->priv->regmap, reg_val, brt_val);
>> +
>> + mutex_unlock(&led->priv->lock);
>> +
>> + return ret;
>> +}
>> +
>> +static enum led_brightness lp50xx_brightness_get(struct led_classdev *led_cdev)
>> +{
>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>> + led_dev);
>> + unsigned int brt_val;
>> + u8 reg_val;
>> + int ret;
>> +
>> + mutex_lock(&led->priv->lock);
>> +
>> + if (led->ctrl_bank_enabled)
>> + reg_val = led->priv->bank_brt_reg;
>> + else
>> + reg_val = led->priv->led_brightness0_reg + led->led_number;
>> +
>> + ret = regmap_read(led->priv->regmap, reg_val, &brt_val);
>> +
>> + mutex_unlock(&led->priv->lock);
>> +
>> + return brt_val;
>> +}
>> +
>> +static void lp50xx_set_led_values(struct lp50xx *priv)
>> +{
>> + if (priv->model_id == LP5018 || priv->model_id == LP5024) {
>> + priv->led_brightness0_reg = LP5024_LED0_BRT;
>> + priv->mix_out0_reg = LP5024_OUT0_CLR;
>> + priv->bank_brt_reg = LP5024_BNK_BRT;
>> + priv->bank_mix_reg = LP5024_BNKA_CLR;
>> + priv->reset_reg = LP5024_RESET;
>> + } else {
>> + priv->led_brightness0_reg = LP5036_LED0_BRT;
>> + priv->mix_out0_reg = LP5036_OUT0_CLR;
>> + priv->bank_brt_reg = LP5036_BNK_BRT;
>> + priv->bank_mix_reg = LP5036_BNKA_CLR;
>> + priv->reset_reg = LP5036_RESET;
>> + }
>> +}
>> +
>> +static int lp50xx_set_banks(struct lp50xx *priv)
>> +{
>> + struct lp50xx_led *led;
>> + u8 led_ctrl_enable = 0;
>> + u8 led1_ctrl_enable = 0;
>> + u8 ctrl_ext = 0;
>> + int i, j;
>> + int ret;
>> +
>> + for (i = 0; i <= priv->num_of_leds; i++) {
>> + led = &priv->leds[i];
>> + if (!led->ctrl_bank_enabled)
>> + continue;
>> +
>> + for (j = 0; j <= priv->max_leds - 1; j++) {
>> + if (led->led_strings[j] > (LP5024_MAX_LED_STRINGS - 1)) {
>> + ctrl_ext = led->led_strings[j] - LP5024_MAX_LED_STRINGS;
>> + led1_ctrl_enable |= (1 << ctrl_ext);
>> + } else {
>> + led_ctrl_enable |= (1 << led->led_strings[j]);
>> + }
>> + }
>> + }
>
> With centralized bank_modules flags it should look simpler.
>
I don't think so. The LP5030 and LP5036 have 2 registers to denote Module vs banked.
But once I convert it we will know.
>> +
>> + ret = regmap_write(priv->regmap, LP50XX_LED_CFG0, led_ctrl_enable);
>> +
>> + if (led1_ctrl_enable)
>> + ret = regmap_write(priv->regmap, LP5036_LED_CFG1,
>> + led1_ctrl_enable);
>> +
>> + return ret;
>> +}
>> +
>> +static int lp50xx_init(struct lp50xx *priv)
>> +{
>> + int ret;
>> +
>> + lp50xx_set_led_values(priv);
>> +
>> + if (priv->enable_gpio) {
>> + gpiod_direction_output(priv->enable_gpio, 1);
>> + } else {
>> + ret = regmap_write(priv->regmap, priv->reset_reg,
>> + LP50XX_SW_RESET);
>> + if (ret) {
>> + dev_err(&priv->client->dev,
>> + "Cannot reset the device\n");
>> + goto out;
>> + }
>> + }
>> +
>> + ret = lp50xx_set_banks(priv);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "Cannot set the banks\n");
>> + goto out;
>> + }
>> +
>> + ret = regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
>> + if (ret)
>> + dev_err(&priv->client->dev, "Cannot write ctrl enable\n");
>> +
>> +out:
>> + return ret;
>> +}
>> +
>> +static int lp50xx_probe_dt(struct lp50xx *priv)
>> +{
>> + struct fwnode_handle *child = NULL;
>> + struct lp50xx_led *led;
>> + int control_bank_defined = 0;
>> + const char *name;
>> + int led_number;
>> + size_t i = 0;
>> + int ret;
>> +
>> + priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
>> + "enable", GPIOD_OUT_LOW);
>> + if (IS_ERR(priv->enable_gpio)) {
>> + ret = PTR_ERR(priv->enable_gpio);
>> + dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
>> + ret);
>> + return ret;
>> + }
>> +
>> + priv->regulator = devm_regulator_get(&priv->client->dev, "vled");
>> + if (IS_ERR(priv->regulator))
>> + priv->regulator = NULL;
>> +
>> + if (priv->model_id == LP5018)
>> + priv->max_leds = LP5018_MAX_LED_STRINGS;
>> + else if (priv->model_id == LP5024)
>> + priv->max_leds = LP5024_MAX_LED_STRINGS;
>> + else if (priv->model_id == LP5030)
>> + priv->max_leds = LP5030_MAX_LED_STRINGS;
>> + else
>> + priv->max_leds = LP5036_MAX_LED_STRINGS;
>
> Let's change STRINGS to MODULEs.
>
ACK.
>> +
>> + device_for_each_child_node(&priv->client->dev, child) {
>> + led = &priv->leds[i];
>> +
>> + if (fwnode_property_present(child, "ti,led-bank")) {
>> + led->ctrl_bank_enabled = 1;
>> + if (!control_bank_defined)
>> + control_bank_defined = 1;
>> + else {
>> + dev_err(&priv->client->dev,
>> + "ti,led-bank defined twice\n");
>> + fwnode_handle_put(child);
>> + goto child_out;
>> + }
>> + } else {
>> + led->ctrl_bank_enabled = 0;
>> + }
>
> Any bit set in bank_modules will signify that bank is defined
> and enabled.
>
This is stored so that when the brightness or color is called the correct
register either bank or LEDn_MODULES is used.
This way I don't have to go out and read the devices bank enable register
and try to determine what was banked and what was not.
Dan
>> + if (led->ctrl_bank_enabled) {
>> + ret = fwnode_property_read_u32_array(child,
>> + "ti,led-bank",
>> + NULL, 0);
>> + ret = fwnode_property_read_u32_array(child,
>> + "ti,led-bank",
>> + led->led_strings,
>> + ret);
>> +
>> + led->led_number = led->led_strings[0];
>> +
>> + } else {
>> + ret = fwnode_property_read_u32(child, "ti,led-module",
>> + &led_number);
>> +
>> + led->led_number = led_number;
>> + }
>> + if (ret) {
>> + dev_err(&priv->client->dev,
>> + "led sourcing property missing\n");
>> + fwnode_handle_put(child);
>> + goto child_out;
>> + }
>> +
>> + if (led_number > priv->max_leds) {
>> + dev_err(&priv->client->dev,
>> + "led-sources property is invalid\n");
>> + ret = -EINVAL;
>> + fwnode_handle_put(child);
>> + goto child_out;
>> + }
>> +
>> + ret = fwnode_property_read_string(child, "label", &name);
>> + if (ret)
>> + snprintf(led->label, sizeof(led->label),
>> + "%s::", priv->client->name);
>> + else
>> + snprintf(led->label, sizeof(led->label),
>> + "%s:%s", priv->client->name, name);
>> +
>> + fwnode_property_read_string(child, "linux,default-trigger",
>> + &led->led_dev.default_trigger);
>> +
>> + led->priv = priv;
>> + led->led_dev.name = led->label;
>> + led->led_dev.brightness_set_blocking = lp50xx_brightness_set;
>> + led->led_dev.brightness_get = lp50xx_brightness_get;
>> + led->led_dev.groups = lp50xx_led_color_groups;
>> +
>> + ret = devm_led_classdev_register(&priv->client->dev,
>> + &led->led_dev);
>> + if (ret) {
>> + dev_err(&priv->client->dev, "led register err: %d\n",
>> + ret);
>> + fwnode_handle_put(child);
>> + goto child_out;
>> + }
>> + i++;
>> + }
>> + priv->num_of_leds = i;
>> +
>> +child_out:
>> + return ret;
>> +}
>> +
>> +static int lp50xx_probe(struct i2c_client *client,
>> + const struct i2c_device_id *id)
>> +{
>> + struct lp50xx *led;
>> + int count;
>> + int ret;
>> +
>> + count = device_get_child_node_count(&client->dev);
>> + if (!count) {
>> + dev_err(&client->dev, "LEDs are not defined in device tree!");
>> + return -ENODEV;
>> + }
>> +
>> + led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
>> + GFP_KERNEL);
>> + if (!led)
>> + return -ENOMEM;
>> +
>> + mutex_init(&led->lock);
>> + led->client = client;
>> + led->dev = &client->dev;
>> + led->model_id = id->driver_data;
>> + i2c_set_clientdata(client, led);
>> +
>> + if (led->model_id == LP5018 || led->model_id == LP5024)
>> + led->regmap = devm_regmap_init_i2c(client,
>> + &lp5024_regmap_config);
>> + else
>> + led->regmap = devm_regmap_init_i2c(client,
>> + &lp5036_regmap_config);
>> +
>> + if (IS_ERR(led->regmap)) {
>> + ret = PTR_ERR(led->regmap);
>> + dev_err(&client->dev, "Failed to allocate register map: %d\n",
>> + ret);
>> + return ret;
>> + }
>> +
>> + ret = lp50xx_probe_dt(led);
>> + if (ret)
>> + return ret;
>> +
>> + ret = lp50xx_init(led);
>> + if (ret)
>> + return ret;
>> +
>> + return 0;
>> +}
>> +
>> +static int lp50xx_remove(struct i2c_client *client)
>> +{
>> + struct lp50xx *led = i2c_get_clientdata(client);
>> + int ret;
>> +
>> + ret = regmap_update_bits(led->regmap, LP50XX_DEV_CFG0,
>> + LP50XX_CHIP_EN, 0);
>> + if (ret) {
>> + dev_err(&led->client->dev, "Failed to disable regulator\n");
>> + return ret;
>> + }
>> +
>> + if (led->enable_gpio)
>> + gpiod_direction_output(led->enable_gpio, 0);
>> +
>> + if (led->regulator) {
>> + ret = regulator_disable(led->regulator);
>> + if (ret)
>> + dev_err(&led->client->dev,
>> + "Failed to disable regulator\n");
>> + }
>> +
>> + mutex_destroy(&led->lock);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct i2c_device_id lp50xx_id[] = {
>> + { "lp5018", LP5018 },
>> + { "lp5024", LP5024 },
>> + { "lp5030", LP5030 },
>> + { "lp5036", LP5036 },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(i2c, lp50xx_id);
>> +
>> +static const struct of_device_id of_lp50xx_leds_match[] = {
>> + { .compatible = "ti,lp5018", },
>> + { .compatible = "ti,lp5024", },
>> + { .compatible = "ti,lp5030", },
>> + { .compatible = "ti,lp5036", },
>> + {},
>> +};
>> +MODULE_DEVICE_TABLE(of, of_lp50xx_leds_match);
>> +
>> +static struct i2c_driver lp50xx_driver = {
>> + .driver = {
>> + .name = "lp50xx",
>> + .of_match_table = of_lp50xx_leds_match,
>> + },
>> + .probe = lp50xx_probe,
>> + .remove = lp50xx_remove,
>> + .id_table = lp50xx_id,
>> +};
>> +module_i2c_driver(lp50xx_driver);
>> +
>> +MODULE_DESCRIPTION("Texas Instruments LP5024 LED driver");
>> +MODULE_AUTHOR("Dan Murphy <[email protected]>");
>> +MODULE_LICENSE("GPL v2");
>>
>
--
------------------
Dan Murphy
Jacek
On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
> Dan,
>
> On 1/22/19 11:44 PM, Dan Murphy wrote:
>> Jacek
>>
>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>> Hi all,
>>>
>>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>>> Hi Dan,
>>>>
>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>> Jacek
>>>>>
>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>> Jacek
>>>>>>
>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>> Hi Dan,
>>>>>>>
>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>> Hello
>>>>>>>>
>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>> Hi!
>>>>>>>>>
>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>> Hi!
>>>>>>>>>>>
>>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +Example:
>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>>
>>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>>> like.
>>>>>>>>>>>
>>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>>
>>>>>>>>>> What?
>>>>>>>>>
>>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>
>>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>
>>>>>>>>
>>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>>> But everyone interprets colors differently.
>>>>>>>>
>>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>>> Most probably not.
>>>>>>>>
>>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>>
>>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>>
>>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>>
>>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>>> coefficients.
>>>>>>>>
>>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>>> The colors should be close but may not be identical.
>>>>>>>>
>>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>>> light pipe and LED driver technology.
>>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>>
>>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>>> a hardware aspect to the calculation.
>>>>>>>>
>>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>>
>>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>>
>>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>>
>>>>>>>>
>>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>>
>>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>>> I have.
>>>>>>>>>>
>>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>>
>>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>>> colors?
>>>>>>>>>
>>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>>
>>>>>>>>
>>>>>>>> Good suggestion for a rough test.
>>>>>>>>
>>>>>>>>>>> But...
>>>>>>>>>>>
>>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>>> interface?
>>>>>>>>>>
>>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>>
>>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>>> should work there, too.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>>
>>>>>>>>>> <rant>
>>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>>> </rant>
>>>>>>>>>
>>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>>
>>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>>> kernel.
>>>>>>>>>
>>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>>
>>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>>> them.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Sigh. You did not answer my question.
>>>>>>>>
>>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>>> RGB LED landscape.
>>>>>>>>
>>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>>> maybe color capabilities but not specific colors.
>>>>>>>
>>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>>
>>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>>
>>>>>>> sysfs interface:
>>>>>>>
>>>>>>> brightness-model: space separated list of available options:
>>>>>>> - rgb (default):
>>>>>>> - creates color file with "red green blue" decimal values
>>>>>>
>>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>>> Should the LED color come from the DT?
>>>>>>
>>>>>
>>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>>> But should they have the same interfaces as RGB?
>>>>>
>>>>> Should PWM control be a global interface?
>>>>
>>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>>
>>>> color_names: "red green blue white"
>>>>
>>>> echo "32 43 0 128" > color
>>>>
>>>> This way all elements would be set at same time from user space point of view.
>>>>
>>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>>
>>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>>
>>>> - red, green, blue
>>>> - red, green, blue, amber
>>>> - red, green, blue, white
>>>> - red, green, blue, white - cool
>>>> - red, green, blue, white - neutral
>>>> - red, green, blue, white - warm
>>>> - red, orange
>>>> - purple, ultraviolet
>>>> - amber, blue
>>>> - amber, blue, cyan, green, red, violet, white - cool
>>>> - amber, blue, green
>>>> - amber, green, blue
>>>> - and then lots of single special colors
>>>
>>> It suggested me another solution. Instead of LED RGB class
>>> we would have LED multi-color class.
>>>
>>
>> I was thinking the same thing this morning. But I was thinking that the RGB
>> class should be an additional class to stand on its own or can register to the
>> multi color class.
>>
>>> Sysfs interface design:
>>> -----------------------
>>>
>>> colors: directory containing files that map to
>>> the brightness of particular LEDs; there
>>> would be predefined color names that LED class
>>> driver should map iouts to, e.g.:
>>
>> Filling in the missing ideas with questions.
>>
>> Is it a directory or a file? If it is a directory does that not break the current
>> directory label model?
>>
>> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
>> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
>> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>>
>> Or are you saying it would be something like (More then likely this is what you intended)
>> /sys/class/leds/input4::numlock/colors?
>
> Yes, this is what I meant.
>
OK. Thanks for the clarification
>> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
>> knows that this is a multi color class and not a single LED color class.
>
> Like I am going to come up with standardized color names
> in my LED naming related patch, the multi-color names
> can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
>
That may be better it is descriptive off the command line.
>> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
>> variants when RGB is only available? And this can also present a single write to the kernel with the new
>> color values.
>
> My design already covers that in the form of files in the colors
> directory. Like I stated: "files that map to the brightness of
> particular LEDs". Single write is secured by "echo "write" > sync.
>
OK. So set the new values and then tell the set the sync which will make the device driver write the
device.
Sounds good. how about echo 1 > sync and we can stay away from a long string conversion
>> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
>> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
>> colors.
>> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
>> if we start adding defines like white_warm, white_neutral and other variations to the color.
>
> We would not limit anything. Every color combination can be achieved
> by following this exemplary sequence:
>
> $ echo 154 > colors/red
> $ echo 232 > colors/green
> $ echo 43 > colors/blue
> # echo "write" > sync //only this changes hardware state
>
> brightness-model is provided only to define mapping of legacy brightness
> levels (governed by brightness file and led_set_brightness() API) to
> the specific combination of colors.
>
> For instance we can define three brightness levels for green hue:
>
> DT definition for it would look like below:
>
> rgb-green = <0x277c33 0x37b048 0x47e45d>;
>
> LED multi color class would then do the following mapping for
> each of the three brightness levels for rgb-green brightness model:
>
> $ echo rgb-green > brightness_model
> $ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
> $ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
> $ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
>
OK I would have to play with this on the LP devices.
>> What about IR LEDs used for night vision products? Do these fall into the multi color class?
>> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
>> flash class but it could be a multi color LED as well.
>>
>> How would traversing through the full color palette work if you were to want to produce a multi
>> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
>> Or in a product like the gaming keyboards that will change color or change backlight brightness?
>
> This is not meant as a solution for pattern generator but for
> consolidated source of multi color light. In the simplest case
> RGB LED elements like those used for lp5024 reference board,
> but it could be RGBWAUV LED [0] as well.
>
> For patterns traversing many LEDs I see a trigger as the best solution.
> Hmm, now I see that trigger mechanism actually can serve as very
> flexible pattern generator.
>
> We would need a device that could be configured to register
> a number of multi-led-patternN triggers, one per LED, and generate
> events for each trigger in a loop.
>
> The device would have to allow for configuring pattern intervals
> via sysfs, like in case of current pattern trigger.
>
> LED class devices would have to register for its events:
>
> $/sys/class/leds/led1 echo multi-led-pattern1 > trigger
> $/sys/class/leds/led2 echo multi-led-pattern2 > trigger
> $/sys/class/leds/led3 echo multi-led-pattern3 > trigger
>
A bit off topic but I like the idea. We should save this for another day
> The ability to define brightness models in DT would
> add even more flexibility.
>
brightness models would be mandatory to support in the driver but an optional
DT entry.
Is that a correct assumption?
>> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
>> capable of doing this?
>>
>> https://www.youtube.com/watch?v=pfKv3g2FeBE
>> or something like this
>>
>> https://www.youtube.com/watch?v=PO3auX3f5C4
>>
>> The LP5036 has this capability.
>>
>>> - red
>>> - green
>>> - blue
>>> - white
>>> - sync: accepts "write" and "read", which executes
>>> write/readout to/from a device respectively.
>>>
>>
>> What are these above, the values or the files under the colors directory?
>
> They are just color specific counterparts of monochrome brightness.
> In terms of lp50xx they would map to OUTn_COLOR registers.
>
>> I am assuming they are files.
>
> Right.
>
>> Are they mandatory or optional?
>
> Mandatory, one per each iout to control.
>
OK And all the LEDs within this directory would be considered a LED cluster?
And if there are 2 like colors of the LED defined in the same cluster would we just see a single
file and write a common value to that file and the driver would have to update each
red LED within that cluster. No independent control of like colored LEDs within the
registered LED cluster.
If the developer wants this level of control they would have to register two separate classes
Correct?
>>> brightness-model: defines brightness level to color configuration
>>> mapping
>>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>>> - "rgb-<hue>": available only when all three red,green,blue colors
>>> are present in the colors directory.
>>> <hue> is a placeholder for given DT hue presets.
>>> - "rgbw-<hue>": Same as above, but available only when white color
>>> (any of amber or white-{cool|neutral|warm} can be
>>> mapped to white) is also available. In this mode
>>> max_brightness equals num-of-hue-presets + 1, and
>>> max_brightness, when set, turns the "white" LED on
>>
>> Why do we need white combined here? Should this not be its own entity?
>
> To be able to set white color. We're still talking about one LED
> element (although they can be be physically few LEDs in one case).
> This is brightness file, so we've got to stick to the semantics.
> Max brightness level should be the brightest. With RGBW LEDs we
> fortunately have a means to achieve pure white, that's why
> rgbw-<hue> would be beneficial. If you increase L component of
> HSL color space, the max value gives white for all hues.
> So maybe this brightness-model would be rather called hsl-<hue>.
>
> For RGBW LEDs, we would have to allow for more shades of white too,
> like in [1].
>
Yep.
>> Again I don't like limiting the color palette from the DT. I think that the
>> user space can see what colors are available for that device and makes its own
>> decision on what color to present.
>>
>> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
>> same function trying to be achieved by the system designer? The RGB can be used to denote
>> notification status and the white can be used to denote that a charger is connected. Motorola
>> Droid did this.
>
> I hope I've just clarified my idea.
>
Its getting clearer. I would like to see it in code and play with it not as a user
but as a developer. Make sure the paper model works as well as the real implementation.
Is this model clear to the developer?
How would a developer define what values are appropriate for the brightness-model?
Does the driver have to become overly complex to support simple color generation?
Thoughts on putting code to idea?
>>
>>> - "rgb-linear": I'm not sure if it should be available - it will
>>> have unpredictable results
>>>
>>> brightness: sets/reads brightness in the way specific to the
>>> current brightness-model. When more colors are available
>>> (e.g. amber, blue, cyan, green, red, violet, white), they
>>> are not touched by write to brightness).
>>>
>>> HSV->RGB conversion is left entirely to the userspace, which can set any
>>> color with use of the proposed interface.
>>>
>>> Let's agree on sysfs interface first, and only after that move
>>> to the DT details.
>>>
>>
>> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
>> an issue with defining product capabilities in the DT then we should keep that out of the DT.
>
> LED element is a device. I see nothing irrelevant for DT in describing the lighting specificity of a device mounted on the board. Please keep
> in mind that it will not limit the number of colors available to set.
> It will only allow to define mapping of brightness level to color.
> We need that for current trigger mechanism to work with LED multi-color
> class.
>
I see this now.
Dan
> [0] http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
> [1] https://www.youtube.com/watch?v=NzlFmTqOh9M
>
--
------------------
Dan Murphy
Dan,
On 1/24/19 9:32 PM, Dan Murphy wrote:
> Jacek
>
> Replying to code comments.
>
> On 1/15/19 3:47 PM, Jacek Anaszewski wrote:
>> Hi Da,
>>
>> Thank you for the v2.
>>
>
> I will probably submit v3 outside the realm of the multi color framework.
> We can always convert as Pavel pointed out.
>
>> I have some remarks below.
>>
>> On 1/14/19 10:17 PM, Dan Murphy wrote:
>>> Introduce the LP5036/30/24/18 RGB LED driver.
>>> The difference in these parts are the number of
>>> LED outputs where the:
>>>
>>> LP5036 can control 36 LEDs
>>> LP5030 can control 30 LEDs
>>> LP5024 can control 24 LEDs
>>> LP5018 can control 18 LEDs
>>>
>>> The device has the ability to group LED output into control banks
>>> so that multiple LED banks can be controlled with the same mixing and
>>> brightness. Inversely the LEDs can also be controlled independently.
>>>
>>> Signed-off-by: Dan Murphy <[email protected]>
>>> ---
>>>
>>> v2 - Changed the mix and module files to a single "color" file, added the LP5030
>>> and LP5036 register mapping, added ABI documentation, updated the parsing of
>>> DT and led sources to match DT, renamed driver to leds-lp50xx.c - https://lore.kernel.org/patchwork/patch/1026515/
>>>
>>> Documentation/leds/leds-lp50xx.txt | 36 ++
>>> drivers/leds/Kconfig | 7 +
>>> drivers/leds/Makefile | 1 +
>>> drivers/leds/leds-lp50xx.c | 754 +++++++++++++++++++++++++++++
>>> 4 files changed, 798 insertions(+)
>>> create mode 100644 Documentation/leds/leds-lp50xx.txt
>>> create mode 100644 drivers/leds/leds-lp50xx.c
>>>
>>> diff --git a/Documentation/leds/leds-lp50xx.txt b/Documentation/leds/leds-lp50xx.txt
>>
>> Please move it to
>>
>> Documentation/ABI/testing/sysfs-class-led-driver-lp50xx
>>
>> and use standard ABI documentation format.
>>
>
> Ack. I will add this file as well per the doc format.
>
>>
>>> new file mode 100644
>>> index 000000000000..8b1b01dfdd22
>>> --- /dev/null
>>> +++ b/Documentation/leds/leds-lp50xx.txt
>>> @@ -0,0 +1,36 @@
>>> +LP5018/LP5024/LP5030/LP5036 Common Driver
>>> +=================================================
>>> +
>>> +Authors: Dan Murphy <[email protected]>
>>> +
>>> +Description
>>> +-----------
>>> +The LP50XX RGB LED drivers have the ability to group multiple RGB cluster
>>> +LEDs into a single group for simultaneous control or expose single RGB cluster
>>> +for control. This device exposes different register interfaces to control
>>> +the cluster brightness as well as the individual RGB LEDs color intensity.
>>> +
>>> +RGB Cluster Color Control
>>> +-------------------------
>>> +The LP50xx driver will expose a file called "color" for each LED class instance
>>> +defined. This file will accept a 24-bit RGB value in which the the color of the
>>> +RGB LEDs will be set.
>>> +
>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>> +XX - Do not care ignored by the driver
>>> +RR - is the 8 bit Red LED value
>>> +GG - is the 8 bit Green LED value
>>> +BB - is the 8 bit Blue LED value
>>> +
>>> +Example:
>>> +LED module output 4 of the LP5024 will be a yellow color:
>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>> +
>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>> +
>>> +LED banked RGBs of the LP5036 will be a white color:
>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>
>> This part with example cans remain in Documentation/leds if you like.
>>
>>> +
>>> +LED banked RGBs of the LP50364 will be dimmed 50%:
>>> +echo 0x80 > /sys/class/leds/lp5036\:led_banked/brightness
>>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
>>> index a72f97fca57b..5f413445a667 100644
>>> --- a/drivers/leds/Kconfig
>>> +++ b/drivers/leds/Kconfig
>>> @@ -326,6 +326,13 @@ config LEDS_LP3952
>>> To compile this driver as a module, choose M here: the
>>> module will be called leds-lp3952.
>>> +config LEDS_LP50XX
>>> + tristate "LED Support for TI LP5036/30/24/18 LED driver chip"
>>> + depends on LEDS_CLASS && REGMAP_I2C
>>> + help
>>> + If you say yes here you get support for the Texas Instruments
>>> + LP5036, LP5030, LP5024 and LP5018 LED driver.
>>> +
>>> config LEDS_LP55XX_COMMON
>>> tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
>>> depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
>>> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
>>> index 4c1b0054f379..852eff0b773f 100644
>>> --- a/drivers/leds/Makefile
>>> +++ b/drivers/leds/Makefile
>>> @@ -32,6 +32,7 @@ obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
>>> obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
>>> obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
>>> obj-$(CONFIG_LEDS_LP3952) += leds-lp3952.o
>>> +obj-$(CONFIG_LEDS_LP50XX) += leds-lp50xx.o
>>> obj-$(CONFIG_LEDS_LP55XX_COMMON) += leds-lp55xx-common.o
>>> obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
>>> obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
>>> diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
>>> new file mode 100644
>>> index 000000000000..41bb2e0129c8
>>> --- /dev/null
>>> +++ b/drivers/leds/leds-lp50xx.c
>>> @@ -0,0 +1,754 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/* TI LP50XX LED chip family driver
>>> + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
>>> + */
>>
>> Let's use uniform "//" comment style here.
>
> Ack
>
>>
>>> +#include <linux/gpio/consumer.h>
>>> +#include <linux/i2c.h>
>>> +#include <linux/init.h>
>>> +#include <linux/leds.h>
>>> +#include <linux/module.h>
>>> +#include <linux/mutex.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_gpio.h>
>>> +#include <linux/regmap.h>
>>> +#include <linux/regulator/consumer.h>
>>> +#include <linux/slab.h>
>>> +#include <uapi/linux/uleds.h>
>>> +
>>> +#define LP50XX_DEV_CFG0 0x00
>>> +#define LP50XX_DEV_CFG1 0x01
>>> +#define LP50XX_LED_CFG0 0x02
>>> +
>>> +/* LP5018 and LP5024 registers */
>>> +#define LP5024_BNK_BRT 0x03
>>> +#define LP5024_BNKA_CLR 0x04
>>> +#define LP5024_BNKB_CLR 0x05
>>> +#define LP5024_BNKC_CLR 0x06
>>> +#define LP5024_LED0_BRT 0x07
>>> +#define LP5024_LED1_BRT 0x08
>>> +#define LP5024_LED2_BRT 0x09
>>> +#define LP5024_LED3_BRT 0x0a
>>> +#define LP5024_LED4_BRT 0x0b
>>> +#define LP5024_LED5_BRT 0x0c
>>> +#define LP5024_LED6_BRT 0x0d
>>> +#define LP5024_LED7_BRT 0x0e
>>> +
>>> +#define LP5024_OUT0_CLR 0x0f
>>> +#define LP5024_OUT1_CLR 0x10
>>> +#define LP5024_OUT2_CLR 0x11
>>> +#define LP5024_OUT3_CLR 0x12
>>> +#define LP5024_OUT4_CLR 0x13
>>> +#define LP5024_OUT5_CLR 0x14
>>> +#define LP5024_OUT6_CLR 0x15
>>> +#define LP5024_OUT7_CLR 0x16
>>> +#define LP5024_OUT8_CLR 0x17
>>> +#define LP5024_OUT9_CLR 0x18
>>> +#define LP5024_OUT10_CLR 0x19
>>> +#define LP5024_OUT11_CLR 0x1a
>>> +#define LP5024_OUT12_CLR 0x1b
>>> +#define LP5024_OUT13_CLR 0x1c
>>> +#define LP5024_OUT14_CLR 0x1d
>>> +#define LP5024_OUT15_CLR 0x1e
>>> +#define LP5024_OUT16_CLR 0x1f
>>> +#define LP5024_OUT17_CLR 0x20
>>> +#define LP5024_OUT18_CLR 0x21
>>> +#define LP5024_OUT19_CLR 0x22
>>> +#define LP5024_OUT20_CLR 0x23
>>> +#define LP5024_OUT21_CLR 0x24
>>> +#define LP5024_OUT22_CLR 0x25
>>> +#define LP5024_OUT23_CLR 0x26
>>> +#define LP5024_RESET 0x27
>>> +
>>> +/* LP5030 and LP5036 registers */
>>> +#define LP5036_LED_CFG1 0x03
>>> +#define LP5036_BNK_BRT 0x04
>>> +#define LP5036_BNKA_CLR 0x05
>>> +#define LP5036_BNKB_CLR 0x06
>>> +#define LP5036_BNKC_CLR 0x07
>>> +#define LP5036_LED0_BRT 0x08
>>> +#define LP5036_LED1_BRT 0x09
>>> +#define LP5036_LED2_BRT 0x0a
>>> +#define LP5036_LED3_BRT 0x0b
>>> +#define LP5036_LED4_BRT 0x0c
>>> +#define LP5036_LED5_BRT 0x0d
>>> +#define LP5036_LED6_BRT 0x0e
>>> +#define LP5036_LED7_BRT 0x0f
>>> +#define LP5036_LED8_BRT 0x10
>>> +#define LP5036_LED9_BRT 0x11
>>> +#define LP5036_LED10_BRT 0x12
>>> +#define LP5036_LED11_BRT 0x13
>>> +
>>> +#define LP5036_OUT0_CLR 0x14
>>> +#define LP5036_OUT1_CLR 0x15
>>> +#define LP5036_OUT2_CLR 0x16
>>> +#define LP5036_OUT3_CLR 0x17
>>> +#define LP5036_OUT4_CLR 0x18
>>> +#define LP5036_OUT5_CLR 0x19
>>> +#define LP5036_OUT6_CLR 0x1a
>>> +#define LP5036_OUT7_CLR 0x1b
>>> +#define LP5036_OUT8_CLR 0x1c
>>> +#define LP5036_OUT9_CLR 0x1d
>>> +#define LP5036_OUT10_CLR 0x1e
>>> +#define LP5036_OUT11_CLR 0x1f
>>> +#define LP5036_OUT12_CLR 0x20
>>> +#define LP5036_OUT13_CLR 0x21
>>> +#define LP5036_OUT14_CLR 0x22
>>> +#define LP5036_OUT15_CLR 0x23
>>> +#define LP5036_OUT16_CLR 0x24
>>> +#define LP5036_OUT17_CLR 0x25
>>> +#define LP5036_OUT18_CLR 0x26
>>> +#define LP5036_OUT19_CLR 0x27
>>> +#define LP5036_OUT20_CLR 0x28
>>> +#define LP5036_OUT21_CLR 0x29
>>> +#define LP5036_OUT22_CLR 0x2a
>>> +#define LP5036_OUT23_CLR 0x2b
>>> +#define LP5036_OUT24_CLR 0x2c
>>> +#define LP5036_OUT25_CLR 0x2d
>>> +#define LP5036_OUT26_CLR 0x2e
>>> +#define LP5036_OUT27_CLR 0x2f
>>> +#define LP5036_OUT28_CLR 0x30
>>> +#define LP5036_OUT29_CLR 0x31
>>> +#define LP5036_OUT30_CLR 0x32
>>> +#define LP5036_OUT31_CLR 0x33
>>> +#define LP5036_OUT32_CLR 0x34
>>> +#define LP5036_OUT33_CLR 0x35
>>> +#define LP5036_OUT34_CLR 0x36
>>> +#define LP5036_OUT35_CLR 0x37
>>> +#define LP5036_RESET 0x38
>>> +
>>> +#define LP50XX_SW_RESET 0xff
>>> +
>>> +#define LP50XX_CHIP_EN BIT(6)
>>> +
>>> +#define LP5018_MAX_LED_STRINGS 6
>>> +#define LP5024_MAX_LED_STRINGS 8
>>> +#define LP5030_MAX_LED_STRINGS 10
>>> +#define LP5036_MAX_LED_STRINGS 12
>>> +
>>> +enum lp50xx_model {
>>> + LP5018,
>>> + LP5024,
>>> + LP5030,
>>> + LP5036,
>>> +};
>>> +
>>> +struct lp50xx_led {
>>> + u32 led_strings[LP5036_MAX_LED_STRINGS];
>>
>> It is possible to have only one bank, so this can be a property
>> of struct lp50xx. Moreover, it doesn't need to be an array,
>> but should be:
>>
>> unsigned long bank_modules;
>>
>> Then you will be able to use bitops on it, where bit position will
>> refer to the id of RGB LED module assigned to the bank.
>>
>
> ACK. Had to think a bit on this to make sure there was enough room
> but aligning on LEDn_MODULES/BANKS should be fine
>
>>> + char label[LED_MAX_NAME_SIZE];
>>> + struct led_classdev led_dev;
>>> + struct lp50xx *priv;
>>> + int led_number;
>>> + u8 ctrl_bank_enabled;
>>> +};
>>> +
>>> +/**
>>> + * struct lp50xx -
>>> + * @enable_gpio: Hardware enable gpio
>>> + * @regulator: LED supply regulator pointer
>>> + * @client: Pointer to the I2C client
>>> + * @regmap: Devices register map
>>> + * @dev: Pointer to the devices device struct
>>> + * @lock: Lock for reading/writing the device
>>> + * @model_id: ID of the device
>>> + * @leds: Array of LED strings
>>
>> Please don't use capital letters for property description.
>> Still, some of the properties below remain undocumented.
>>
>
> You are referring to ID and I2C or do you mean no capitals to start the
> description?
The latter.
> Yes I added the properties and missed documenting them.
>
>>> + */
>>> +struct lp50xx {
>>> + struct gpio_desc *enable_gpio;
>>> + struct regulator *regulator;
>>> + struct i2c_client *client;
>>> + struct regmap *regmap;
>>> + struct device *dev;
>>> + struct mutex lock;
>>> + enum lp50xx_model model_id;
>>> + int max_leds;
>>> + int num_of_leds;
>>> +
>>> + u8 led_brightness0_reg;
>>> + u8 mix_out0_reg;
>>> + u8 bank_brt_reg;
>>> + u8 bank_mix_reg;
>>> + u8 reset_reg;
>>> +
>>> + /* This needs to be at the end of the struct */
>>> + struct lp50xx_led leds[];
>>> +};
>>> +
>>> +static const struct reg_default lp5024_reg_defs[] = {
>>> + {LP50XX_DEV_CFG0, 0x0},
>>> + {LP50XX_DEV_CFG1, 0x3c},
>>> + {LP50XX_LED_CFG0, 0x0},
>>> + {LP5024_BNK_BRT, 0xff},
>>> + {LP5024_BNKA_CLR, 0x0f},
>>> + {LP5024_BNKB_CLR, 0x0f},
>>> + {LP5024_BNKC_CLR, 0x0f},
>>> + {LP5024_LED0_BRT, 0x0f},
>>> + {LP5024_LED1_BRT, 0xff},
>>> + {LP5024_LED2_BRT, 0xff},
>>> + {LP5024_LED3_BRT, 0xff},
>>> + {LP5024_LED4_BRT, 0xff},
>>> + {LP5024_LED5_BRT, 0xff},
>>> + {LP5024_LED6_BRT, 0xff},
>>> + {LP5024_LED7_BRT, 0xff},
>>> + {LP5024_OUT0_CLR, 0x0f},
>>> + {LP5024_OUT1_CLR, 0x00},
>>> + {LP5024_OUT2_CLR, 0x00},
>>> + {LP5024_OUT3_CLR, 0x00},
>>> + {LP5024_OUT4_CLR, 0x00},
>>> + {LP5024_OUT5_CLR, 0x00},
>>> + {LP5024_OUT6_CLR, 0x00},
>>> + {LP5024_OUT7_CLR, 0x00},
>>> + {LP5024_OUT8_CLR, 0x00},
>>> + {LP5024_OUT9_CLR, 0x00},
>>> + {LP5024_OUT10_CLR, 0x00},
>>> + {LP5024_OUT11_CLR, 0x00},
>>> + {LP5024_OUT12_CLR, 0x00},
>>> + {LP5024_OUT13_CLR, 0x00},
>>> + {LP5024_OUT14_CLR, 0x00},
>>> + {LP5024_OUT15_CLR, 0x00},
>>> + {LP5024_OUT16_CLR, 0x00},
>>> + {LP5024_OUT17_CLR, 0x00},
>>> + {LP5024_OUT18_CLR, 0x00},
>>> + {LP5024_OUT19_CLR, 0x00},
>>> + {LP5024_OUT20_CLR, 0x00},
>>> + {LP5024_OUT21_CLR, 0x00},
>>> + {LP5024_OUT22_CLR, 0x00},
>>> + {LP5024_OUT23_CLR, 0x00},
>>> + {LP5024_RESET, 0x00}
>>> +};
>>> +
>>> +static const struct reg_default lp5036_reg_defs[] = {
>>> + {LP50XX_DEV_CFG0, 0x0},
>>> + {LP50XX_DEV_CFG1, 0x3c},
>>> + {LP50XX_LED_CFG0, 0x0},
>>> + {LP5036_LED_CFG1, 0x0},
>>> + {LP5036_BNK_BRT, 0xff},
>>> + {LP5036_BNKA_CLR, 0x0f},
>>> + {LP5036_BNKB_CLR, 0x0f},
>>> + {LP5036_BNKC_CLR, 0x0f},
>>> + {LP5036_LED0_BRT, 0x0f},
>>> + {LP5036_LED1_BRT, 0xff},
>>> + {LP5036_LED2_BRT, 0xff},
>>> + {LP5036_LED3_BRT, 0xff},
>>> + {LP5036_LED4_BRT, 0xff},
>>> + {LP5036_LED5_BRT, 0xff},
>>> + {LP5036_LED6_BRT, 0xff},
>>> + {LP5036_LED7_BRT, 0xff},
>>> + {LP5036_OUT0_CLR, 0x0f},
>>> + {LP5036_OUT1_CLR, 0x00},
>>> + {LP5036_OUT2_CLR, 0x00},
>>> + {LP5036_OUT3_CLR, 0x00},
>>> + {LP5036_OUT4_CLR, 0x00},
>>> + {LP5036_OUT5_CLR, 0x00},
>>> + {LP5036_OUT6_CLR, 0x00},
>>> + {LP5036_OUT7_CLR, 0x00},
>>> + {LP5036_OUT8_CLR, 0x00},
>>> + {LP5036_OUT9_CLR, 0x00},
>>> + {LP5036_OUT10_CLR, 0x00},
>>> + {LP5036_OUT11_CLR, 0x00},
>>> + {LP5036_OUT12_CLR, 0x00},
>>> + {LP5036_OUT13_CLR, 0x00},
>>> + {LP5036_OUT14_CLR, 0x00},
>>> + {LP5036_OUT15_CLR, 0x00},
>>> + {LP5036_OUT16_CLR, 0x00},
>>> + {LP5036_OUT17_CLR, 0x00},
>>> + {LP5036_OUT18_CLR, 0x00},
>>> + {LP5036_OUT19_CLR, 0x00},
>>> + {LP5036_OUT20_CLR, 0x00},
>>> + {LP5036_OUT21_CLR, 0x00},
>>> + {LP5036_OUT22_CLR, 0x00},
>>> + {LP5036_OUT23_CLR, 0x00},
>>> + {LP5036_OUT24_CLR, 0x00},
>>> + {LP5036_OUT25_CLR, 0x00},
>>> + {LP5036_OUT26_CLR, 0x00},
>>> + {LP5036_OUT27_CLR, 0x00},
>>> + {LP5036_OUT28_CLR, 0x00},
>>> + {LP5036_OUT29_CLR, 0x00},
>>> + {LP5036_OUT30_CLR, 0x00},
>>> + {LP5036_OUT31_CLR, 0x00},
>>> + {LP5036_OUT32_CLR, 0x00},
>>> + {LP5036_OUT33_CLR, 0x00},
>>> + {LP5036_OUT34_CLR, 0x00},
>>> + {LP5036_OUT35_CLR, 0x00},
>>> + {LP5036_RESET, 0x00}
>>> +};
>>> +
>>> +static const struct regmap_config lp5024_regmap_config = {
>>> + .reg_bits = 8,
>>> + .val_bits = 8,
>>> +
>>> + .max_register = LP5024_RESET,
>>> + .reg_defaults = lp5024_reg_defs,
>>> + .num_reg_defaults = ARRAY_SIZE(lp5024_reg_defs),
>>> + .cache_type = REGCACHE_RBTREE,
>>> +};
>>> +
>>> +static const struct regmap_config lp5036_regmap_config = {
>>> + .reg_bits = 8,
>>> + .val_bits = 8,
>>> +
>>> + .max_register = LP5036_RESET,
>>> + .reg_defaults = lp5036_reg_defs,
>>> + .num_reg_defaults = ARRAY_SIZE(lp5036_reg_defs),
>>> + .cache_type = REGCACHE_RBTREE,
>>> +};
>>> +
>>> +static ssize_t color_show(struct device *dev,
>>> + struct device_attribute *attr,
>>> + char *buf)
>>> +{
>>> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
>>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>>> + led_dev);
>>> + struct lp50xx *priv = led->priv;
>>> + unsigned int red_val, green_val, blue_val;
>>> + u8 red_reg, green_reg, blue_reg;
>>> + u32 mix_value = 0;
>>> + u8 led_offset;
>>> + int ret;
>>> +
>>> + if (led->ctrl_bank_enabled) {
>>> + red_reg = priv->bank_mix_reg;
>>> + green_reg = priv->bank_mix_reg + 1;
>>> + blue_reg = priv->bank_mix_reg + 2;
>>> + } else {
>>> + led_offset = (led->led_number * 3);
>>> + red_reg = priv->mix_out0_reg + led_offset;
>>> + green_reg = priv->mix_out0_reg + led_offset + 1;
>>> + blue_reg = priv->mix_out0_reg + led_offset + 2;
>>> + }
>>> +
>>> + ret = regmap_read(priv->regmap, red_reg, &red_val);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot read LED value\n");
>>> + goto out;
>>> + }
>>> +
>>> + ret = regmap_read(priv->regmap, green_reg, &green_val);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot read LED value\n");
>>> + goto out;
>>> + }
>>> +
>>> + ret = regmap_read(priv->regmap, blue_reg, &blue_val);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot read LED value\n");
>>> + goto out;
>>> + }
>>> +
>>> + mix_value = (red_val << 16 | green_val << 8 | blue_val);
>>> +
>>> +out:
>>> + return scnprintf(buf, PAGE_SIZE, "0x%X\n", mix_value);
>>> +}
>>> +
>>> +static ssize_t color_store(struct device *dev,
>>> + struct device_attribute *attr,
>>> + const char *buf, size_t size)
>>> +{
>>> + struct led_classdev *led_cdev = dev_get_drvdata(dev);
>>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>>> + led_dev);
>>> + struct lp50xx *priv = led->priv;
>>> + u8 led_offset;
>>> + unsigned long mix_value;
>>> + u8 red_reg, green_reg, blue_reg;
>>> + u8 red_val, green_val, blue_val;
>>> + int ret;
>>> +
>>> + ret = kstrtoul(buf, 0, &mix_value);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + if (led->ctrl_bank_enabled) {
>>> + red_reg = priv->bank_mix_reg;
>>> + green_reg = priv->bank_mix_reg + 1;
>>> + blue_reg = priv->bank_mix_reg + 2;
>>> + } else {
>>> + led_offset = (led->led_number * 3);
>>> + red_reg = priv->mix_out0_reg + led_offset;
>>> + green_reg = priv->mix_out0_reg + led_offset + 1;
>>> + blue_reg = priv->mix_out0_reg + led_offset + 2;
>>> + }
>>> +
>>> + red_val = (mix_value & 0xff0000) >> 16;
>>> + green_val = (mix_value & 0xff00) >> 8;
>>> + blue_val = (mix_value & 0xff);
>>
>> I've been rather thinking about space separated list of decimal
>> "red green blue" values, but maybe this way it will be less
>> controversial. Let's if there will be other opinions.
>>
>
> Has anything changed based on this?
> Should I change the file name from "color" to something else?
Yes, I'd stick to my most recent proposal:
"colors" directory with red,green,blue files mapped to IOUTn_COLOR
register, and the file "sync" in this directory accepting "write"
and "read" strings.
We could think of some alternatives for the "colors" directory
and "sync" file names.
s/colors/color_intensities/ ?
s/sync/rw ?
For rw case we could have values "1" for write and "0" for read.
>>> +
>>> + ret = regmap_write(priv->regmap, red_reg, red_val);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot write LED value\n");
>>> + goto out;
>>> + }
>>> +
>>> + ret = regmap_write(priv->regmap, green_reg, green_val);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot write LED value\n");
>>> + goto out;
>>> + }
>>> +
>>> + ret = regmap_write(priv->regmap, blue_reg, blue_val);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot write LED value\n");
>>> + goto out;
>>> + }
>>> +out:
>>> + return size;
>>> +}
>>> +
>>> +static DEVICE_ATTR_RW(color);
>>> +
>>> +static struct attribute *lp50xx_led_color_attrs[] = {
>>> + &dev_attr_color.attr,
>>> + NULL
>>> +};
>>> +ATTRIBUTE_GROUPS(lp50xx_led_color);
>>> +
>>> +static int lp50xx_brightness_set(struct led_classdev *led_cdev,
>>> + enum led_brightness brt_val)
>>> +{
>>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>>> + led_dev);
>>> + int ret = 0;
>>> + u8 reg_val;
>>> +
>>> + mutex_lock(&led->priv->lock);
>>> +
>>> + if (led->ctrl_bank_enabled)
>>> + reg_val = led->priv->bank_brt_reg;
>>> + else
>>> + reg_val = led->priv->led_brightness0_reg + led->led_number;
>>> +
>>> + ret = regmap_write(led->priv->regmap, reg_val, brt_val);
>>> +
>>> + mutex_unlock(&led->priv->lock);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static enum led_brightness lp50xx_brightness_get(struct led_classdev *led_cdev)
>>> +{
>>> + struct lp50xx_led *led = container_of(led_cdev, struct lp50xx_led,
>>> + led_dev);
>>> + unsigned int brt_val;
>>> + u8 reg_val;
>>> + int ret;
>>> +
>>> + mutex_lock(&led->priv->lock);
>>> +
>>> + if (led->ctrl_bank_enabled)
>>> + reg_val = led->priv->bank_brt_reg;
>>> + else
>>> + reg_val = led->priv->led_brightness0_reg + led->led_number;
>>> +
>>> + ret = regmap_read(led->priv->regmap, reg_val, &brt_val);
>>> +
>>> + mutex_unlock(&led->priv->lock);
>>> +
>>> + return brt_val;
>>> +}
>>> +
>>> +static void lp50xx_set_led_values(struct lp50xx *priv)
>>> +{
>>> + if (priv->model_id == LP5018 || priv->model_id == LP5024) {
>>> + priv->led_brightness0_reg = LP5024_LED0_BRT;
>>> + priv->mix_out0_reg = LP5024_OUT0_CLR;
>>> + priv->bank_brt_reg = LP5024_BNK_BRT;
>>> + priv->bank_mix_reg = LP5024_BNKA_CLR;
>>> + priv->reset_reg = LP5024_RESET;
>>> + } else {
>>> + priv->led_brightness0_reg = LP5036_LED0_BRT;
>>> + priv->mix_out0_reg = LP5036_OUT0_CLR;
>>> + priv->bank_brt_reg = LP5036_BNK_BRT;
>>> + priv->bank_mix_reg = LP5036_BNKA_CLR;
>>> + priv->reset_reg = LP5036_RESET;
>>> + }
>>> +}
>>> +
>>> +static int lp50xx_set_banks(struct lp50xx *priv)
>>> +{
>>> + struct lp50xx_led *led;
>>> + u8 led_ctrl_enable = 0;
>>> + u8 led1_ctrl_enable = 0;
>>> + u8 ctrl_ext = 0;
>>> + int i, j;
>>> + int ret;
>>> +
>>> + for (i = 0; i <= priv->num_of_leds; i++) {
>>> + led = &priv->leds[i];
>>> + if (!led->ctrl_bank_enabled)
>>> + continue;
>>> +
>>> + for (j = 0; j <= priv->max_leds - 1; j++) {
>>> + if (led->led_strings[j] > (LP5024_MAX_LED_STRINGS - 1)) {
>>> + ctrl_ext = led->led_strings[j] - LP5024_MAX_LED_STRINGS;
>>> + led1_ctrl_enable |= (1 << ctrl_ext);
>>> + } else {
>>> + led_ctrl_enable |= (1 << led->led_strings[j]);
>>> + }
>>> + }
>>> + }
>>
>> With centralized bank_modules flags it should look simpler.
>>
>
> I don't think so. The LP5030 and LP5036 have 2 registers to denote Module vs banked.
>
> But once I convert it we will know.
>
>>> +
>>> + ret = regmap_write(priv->regmap, LP50XX_LED_CFG0, led_ctrl_enable);
>>> +
>>> + if (led1_ctrl_enable)
>>> + ret = regmap_write(priv->regmap, LP5036_LED_CFG1,
>>> + led1_ctrl_enable);
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static int lp50xx_init(struct lp50xx *priv)
>>> +{
>>> + int ret;
>>> +
>>> + lp50xx_set_led_values(priv);
>>> +
>>> + if (priv->enable_gpio) {
>>> + gpiod_direction_output(priv->enable_gpio, 1);
>>> + } else {
>>> + ret = regmap_write(priv->regmap, priv->reset_reg,
>>> + LP50XX_SW_RESET);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev,
>>> + "Cannot reset the device\n");
>>> + goto out;
>>> + }
>>> + }
>>> +
>>> + ret = lp50xx_set_banks(priv);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "Cannot set the banks\n");
>>> + goto out;
>>> + }
>>> +
>>> + ret = regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
>>> + if (ret)
>>> + dev_err(&priv->client->dev, "Cannot write ctrl enable\n");
>>> +
>>> +out:
>>> + return ret;
>>> +}
>>> +
>>> +static int lp50xx_probe_dt(struct lp50xx *priv)
>>> +{
>>> + struct fwnode_handle *child = NULL;
>>> + struct lp50xx_led *led;
>>> + int control_bank_defined = 0;
>>> + const char *name;
>>> + int led_number;
>>> + size_t i = 0;
>>> + int ret;
>>> +
>>> + priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
>>> + "enable", GPIOD_OUT_LOW);
>>> + if (IS_ERR(priv->enable_gpio)) {
>>> + ret = PTR_ERR(priv->enable_gpio);
>>> + dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
>>> + ret);
>>> + return ret;
>>> + }
>>> +
>>> + priv->regulator = devm_regulator_get(&priv->client->dev, "vled");
>>> + if (IS_ERR(priv->regulator))
>>> + priv->regulator = NULL;
>>> +
>>> + if (priv->model_id == LP5018)
>>> + priv->max_leds = LP5018_MAX_LED_STRINGS;
>>> + else if (priv->model_id == LP5024)
>>> + priv->max_leds = LP5024_MAX_LED_STRINGS;
>>> + else if (priv->model_id == LP5030)
>>> + priv->max_leds = LP5030_MAX_LED_STRINGS;
>>> + else
>>> + priv->max_leds = LP5036_MAX_LED_STRINGS;
>>
>> Let's change STRINGS to MODULEs.
>>
>
> ACK.
>
>>> +
>>> + device_for_each_child_node(&priv->client->dev, child) {
>>> + led = &priv->leds[i];
>>> +
>>> + if (fwnode_property_present(child, "ti,led-bank")) {
>>> + led->ctrl_bank_enabled = 1;
>>> + if (!control_bank_defined)
>>> + control_bank_defined = 1;
>>> + else {
>>> + dev_err(&priv->client->dev,
>>> + "ti,led-bank defined twice\n");
>>> + fwnode_handle_put(child);
>>> + goto child_out;
>>> + }
>>> + } else {
>>> + led->ctrl_bank_enabled = 0;
>>> + }
>>
>> Any bit set in bank_modules will signify that bank is defined
>> and enabled.
>>
>
> This is stored so that when the brightness or color is called the correct
> register either bank or LEDn_MODULES is used.
>
> This way I don't have to go out and read the devices bank enable register
> and try to determine what was banked and what was not.
You don't need to read the register but its cached state
(even via regmap - if you don't mark register volatile
then it will return cached register state).
I suppose it doesn't change in time in hardware?
I meant that instead of:
if (!control_bank_defined)
you will be able to do the following check:
if (!bank_modules)
Also you will not need led->ctrl_bank_enabled, because
bank_modules == 0 will mean bank disabled.
>>> + if (led->ctrl_bank_enabled) {
>>> + ret = fwnode_property_read_u32_array(child,
>>> + "ti,led-bank",
>>> + NULL, 0);
>>> + ret = fwnode_property_read_u32_array(child,
>>> + "ti,led-bank",
>>> + led->led_strings,
>>> + ret);
>>> +
>>> + led->led_number = led->led_strings[0];
>>> +
>>> + } else {
>>> + ret = fwnode_property_read_u32(child, "ti,led-module",
>>> + &led_number);
>>> +
>>> + led->led_number = led_number;
>>> + }
>>> + if (ret) {
>>> + dev_err(&priv->client->dev,
>>> + "led sourcing property missing\n");
>>> + fwnode_handle_put(child);
>>> + goto child_out;
>>> + }
>>> +
>>> + if (led_number > priv->max_leds) {
>>> + dev_err(&priv->client->dev,
>>> + "led-sources property is invalid\n");
>>> + ret = -EINVAL;
>>> + fwnode_handle_put(child);
>>> + goto child_out;
>>> + }
>>> +
>>> + ret = fwnode_property_read_string(child, "label", &name);
>>> + if (ret)
>>> + snprintf(led->label, sizeof(led->label),
>>> + "%s::", priv->client->name);
>>> + else
>>> + snprintf(led->label, sizeof(led->label),
>>> + "%s:%s", priv->client->name, name);
>>> +
>>> + fwnode_property_read_string(child, "linux,default-trigger",
>>> + &led->led_dev.default_trigger);
>>> +
>>> + led->priv = priv;
>>> + led->led_dev.name = led->label;
>>> + led->led_dev.brightness_set_blocking = lp50xx_brightness_set;
>>> + led->led_dev.brightness_get = lp50xx_brightness_get;
>>> + led->led_dev.groups = lp50xx_led_color_groups;
>>> +
>>> + ret = devm_led_classdev_register(&priv->client->dev,
>>> + &led->led_dev);
>>> + if (ret) {
>>> + dev_err(&priv->client->dev, "led register err: %d\n",
>>> + ret);
>>> + fwnode_handle_put(child);
>>> + goto child_out;
>>> + }
>>> + i++;
>>> + }
>>> + priv->num_of_leds = i;
>>> +
>>> +child_out:
>>> + return ret;
>>> +}
>>> +
>>> +static int lp50xx_probe(struct i2c_client *client,
>>> + const struct i2c_device_id *id)
>>> +{
>>> + struct lp50xx *led;
>>> + int count;
>>> + int ret;
>>> +
>>> + count = device_get_child_node_count(&client->dev);
>>> + if (!count) {
>>> + dev_err(&client->dev, "LEDs are not defined in device tree!");
>>> + return -ENODEV;
>>> + }
>>> +
>>> + led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
>>> + GFP_KERNEL);
>>> + if (!led)
>>> + return -ENOMEM;
>>> +
>>> + mutex_init(&led->lock);
>>> + led->client = client;
>>> + led->dev = &client->dev;
>>> + led->model_id = id->driver_data;
>>> + i2c_set_clientdata(client, led);
>>> +
>>> + if (led->model_id == LP5018 || led->model_id == LP5024)
>>> + led->regmap = devm_regmap_init_i2c(client,
>>> + &lp5024_regmap_config);
>>> + else
>>> + led->regmap = devm_regmap_init_i2c(client,
>>> + &lp5036_regmap_config);
>>> +
>>> + if (IS_ERR(led->regmap)) {
>>> + ret = PTR_ERR(led->regmap);
>>> + dev_err(&client->dev, "Failed to allocate register map: %d\n",
>>> + ret);
>>> + return ret;
>>> + }
>>> +
>>> + ret = lp50xx_probe_dt(led);
>>> + if (ret)
>>> + �� return ret;
>>> +
>>> + ret = lp50xx_init(led);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int lp50xx_remove(struct i2c_client *client)
>>> +{
>>> + struct lp50xx *led = i2c_get_clientdata(client);
>>> + int ret;
>>> +
>>> + ret = regmap_update_bits(led->regmap, LP50XX_DEV_CFG0,
>>> + LP50XX_CHIP_EN, 0);
>>> + if (ret) {
>>> + dev_err(&led->client->dev, "Failed to disable regulator\n");
>>> + return ret;
>>> + }
>>> +
>>> + if (led->enable_gpio)
>>> + gpiod_direction_output(led->enable_gpio, 0);
>>> +
>>> + if (led->regulator) {
>>> + ret = regulator_disable(led->regulator);
>>> + if (ret)
>>> + dev_err(&led->client->dev,
>>> + "Failed to disable regulator\n");
>>> + }
>>> +
>>> + mutex_destroy(&led->lock);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static const struct i2c_device_id lp50xx_id[] = {
>>> + { "lp5018", LP5018 },
>>> + { "lp5024", LP5024 },
>>> + { "lp5030", LP5030 },
>>> + { "lp5036", LP5036 },
>>> + { }
>>> +};
>>> +MODULE_DEVICE_TABLE(i2c, lp50xx_id);
>>> +
>>> +static const struct of_device_id of_lp50xx_leds_match[] = {
>>> + { .compatible = "ti,lp5018", },
>>> + { .compatible = "ti,lp5024", },
>>> + { .compatible = "ti,lp5030", },
>>> + { .compatible = "ti,lp5036", },
>>> + {},
>>> +};
>>> +MODULE_DEVICE_TABLE(of, of_lp50xx_leds_match);
>>> +
>>> +static struct i2c_driver lp50xx_driver = {
>>> + .driver = {
>>> + .name = "lp50xx",
>>> + .of_match_table = of_lp50xx_leds_match,
>>> + },
>>> + .probe = lp50xx_probe,
>>> + .remove = lp50xx_remove,
>>> + .id_table = lp50xx_id,
>>> +};
>>> +module_i2c_driver(lp50xx_driver);
>>> +
>>> +MODULE_DESCRIPTION("Texas Instruments LP5024 LED driver");
>>> +MODULE_AUTHOR("Dan Murphy <[email protected]>");
>>> +MODULE_LICENSE("GPL v2");
>>>
>>
>
>
--
Best regards,
Jacek Anaszewski
Dan
On 1/24/19 10:00 PM, Dan Murphy wrote:
> Jacek
>
> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
>> Dan,
>>
>> On 1/22/19 11:44 PM, Dan Murphy wrote:
>>> Jacek
>>>
>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>>> Hi all,
>>>>
>>>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>>>> Hi Dan,
>>>>>
>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>>> Jacek
>>>>>>
>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>>> Jacek
>>>>>>>
>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>>> Hi Dan,
>>>>>>>>
>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>>> Hello
>>>>>>>>>
>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>>> Hi!
>>>>>>>>>>
>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>>> Hi!
>>>>>>>>>>>>
>>>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +Example:
>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>>>
>>>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>>>> like.
>>>>>>>>>>>>
>>>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>>>
>>>>>>>>>>> What?
>>>>>>>>>>
>>>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>
>>>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>>>> But everyone interprets colors differently.
>>>>>>>>>
>>>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>>>> Most probably not.
>>>>>>>>>
>>>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>>>
>>>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>>>
>>>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>>>
>>>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>>>> coefficients.
>>>>>>>>>
>>>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>>>> The colors should be close but may not be identical.
>>>>>>>>>
>>>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>>>> light pipe and LED driver technology.
>>>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>>>
>>>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>>>> a hardware aspect to the calculation.
>>>>>>>>>
>>>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>>>
>>>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>>>
>>>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>>>
>>>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>>>> I have.
>>>>>>>>>>>
>>>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>>>
>>>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>>>> colors?
>>>>>>>>>>
>>>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Good suggestion for a rough test.
>>>>>>>>>
>>>>>>>>>>>> But...
>>>>>>>>>>>>
>>>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>>>> interface?
>>>>>>>>>>>
>>>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>>>
>>>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>>>> should work there, too.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>>>
>>>>>>>>>>> <rant>
>>>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>>>> </rant>
>>>>>>>>>>
>>>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>>>
>>>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>>>> kernel.
>>>>>>>>>>
>>>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>>>
>>>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>>>> them.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Sigh. You did not answer my question.
>>>>>>>>>
>>>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>>>> RGB LED landscape.
>>>>>>>>>
>>>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>>>> maybe color capabilities but not specific colors.
>>>>>>>>
>>>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>>>
>>>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>>>
>>>>>>>> sysfs interface:
>>>>>>>>
>>>>>>>> brightness-model: space separated list of available options:
>>>>>>>> - rgb (default):
>>>>>>>> - creates color file with "red green blue" decimal values
>>>>>>>
>>>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>>>> Should the LED color come from the DT?
>>>>>>>
>>>>>>
>>>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>>>> But should they have the same interfaces as RGB?
>>>>>>
>>>>>> Should PWM control be a global interface?
>>>>>
>>>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>>>
>>>>> color_names: "red green blue white"
>>>>>
>>>>> echo "32 43 0 128" > color
>>>>>
>>>>> This way all elements would be set at same time from user space point of view.
>>>>>
>>>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>>>
>>>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>>>
>>>>> - red, green, blue
>>>>> - red, green, blue, amber
>>>>> - red, green, blue, white
>>>>> - red, green, blue, white - cool
>>>>> - red, green, blue, white - neutral
>>>>> - red, green, blue, white - warm
>>>>> - red, orange
>>>>> - purple, ultraviolet
>>>>> - amber, blue
>>>>> - amber, blue, cyan, green, red, violet, white - cool
>>>>> - amber, blue, green
>>>>> - amber, green, blue
>>>>> - and then lots of single special colors
>>>>
>>>> It suggested me another solution. Instead of LED RGB class
>>>> we would have LED multi-color class.
>>>>
>>>
>>> I was thinking the same thing this morning. But I was thinking that the RGB
>>> class should be an additional class to stand on its own or can register to the
>>> multi color class.
>>>
>>>> Sysfs interface design:
>>>> -----------------------
>>>>
>>>> colors: directory containing files that map to
>>>> the brightness of particular LEDs; there
>>>> would be predefined color names that LED class
>>>> driver should map iouts to, e.g.:
>>>
>>> Filling in the missing ideas with questions.
>>>
>>> Is it a directory or a file? If it is a directory does that not break the current
>>> directory label model?
>>>
>>> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
>>> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
>>> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>>>
>>> Or are you saying it would be something like (More then likely this is what you intended)
>>> /sys/class/leds/input4::numlock/colors?
>>
>> Yes, this is what I meant.
>>
>
> OK. Thanks for the clarification
>
>>> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
>>> knows that this is a multi color class and not a single LED color class.
>>
>> Like I am going to come up with standardized color names
>> in my LED naming related patch, the multi-color names
>> can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
>>
>
> That may be better it is descriptive off the command line.
>
>>> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
>>> variants when RGB is only available? And this can also present a single write to the kernel with the new
>>> color values.
>>
>> My design already covers that in the form of files in the colors
>> directory. Like I stated: "files that map to the brightness of
>> particular LEDs". Single write is secured by "echo "write" > sync.
>>
>
> OK. So set the new values and then tell the set the sync which will make the device driver write the
> device.
>
> Sounds good. how about echo 1 > sync and we can stay away from a long string conversion
We need also to be able to do a readout.
If we changed "sync" to "rw" then we could come up with intuitive
semantics:
echo 1 > rw // write
echo 0 > rw // read
rw file would have WO permission.
>>> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
>>> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
>>> colors.
>>> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
>>> if we start adding defines like white_warm, white_neutral and other variations to the color.
>>
>> We would not limit anything. Every color combination can be achieved
>> by following this exemplary sequence:
>>
>> $ echo 154 > colors/red
>> $ echo 232 > colors/green
>> $ echo 43 > colors/blue
>> # echo "write" > sync //only this changes hardware state
>>
>> brightness-model is provided only to define mapping of legacy brightness
>> levels (governed by brightness file and led_set_brightness() API) to
>> the specific combination of colors.
>>
>> For instance we can define three brightness levels for green hue:
>>
>> DT definition for it would look like below:
>>
>> rgb-green = <0x277c33 0x37b048 0x47e45d>;
>>
>> LED multi color class would then do the following mapping for
>> each of the three brightness levels for rgb-green brightness model:
>>
>> $ echo rgb-green > brightness_model
>> $ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
>> $ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
>> $ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
>>
>
> OK I would have to play with this on the LP devices.
>
>>> What about IR LEDs used for night vision products? Do these fall into the multi color class?
>>> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
>>> flash class but it could be a multi color LED as well.
>>>
>>> How would traversing through the full color palette work if you were to want to produce a multi
>>> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
>>> Or in a product like the gaming keyboards that will change color or change backlight brightness?
>>
>> This is not meant as a solution for pattern generator but for
>> consolidated source of multi color light. In the simplest case
>> RGB LED elements like those used for lp5024 reference board,
>> but it could be RGBWAUV LED [0] as well.
>>
>> For patterns traversing many LEDs I see a trigger as the best solution.
>> Hmm, now I see that trigger mechanism actually can serve as very
>> flexible pattern generator.
>>
>> We would need a device that could be configured to register
>> a number of multi-led-patternN triggers, one per LED, and generate
>> events for each trigger in a loop.
>>
>> The device would have to allow for configuring pattern intervals
>> via sysfs, like in case of current pattern trigger.
>>
>> LED class devices would have to register for its events:
>>
>> $/sys/class/leds/led1 echo multi-led-pattern1 > trigger
>> $/sys/class/leds/led2 echo multi-led-pattern2 > trigger
>> $/sys/class/leds/led3 echo multi-led-pattern3 > trigger
>>
>
> A bit off topic but I like the idea. We should save this for another day
Yes, that's another story.
>> The ability to define brightness models in DT would
>> add even more flexibility.
>>
>
> brightness models would be mandatory to support in the driver but an optional
> DT entry.
>
> Is that a correct assumption?
Correct.
>>> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
>>> capable of doing this?
>>>
>>> https://www.youtube.com/watch?v=pfKv3g2FeBE
>>> or something like this
>>>
>>> https://www.youtube.com/watch?v=PO3auX3f5C4
>>>
>>> The LP5036 has this capability.
>>>
>>>> - red
>>>> - green
>>>> - blue
>>>> - white
>>>> - sync: accepts "write" and "read", which executes
>>>> write/readout to/from a device respectively.
>>>>
>>>
>>> What are these above, the values or the files under the colors directory?
>>
>> They are just color specific counterparts of monochrome brightness.
>> In terms of lp50xx they would map to OUTn_COLOR registers.
>>
>>> I am assuming they are files.
>>
>> Right.
>>
>>> Are they mandatory or optional?
>>
>> Mandatory, one per each iout to control.
>>
>
> OK And all the LEDs within this directory would be considered a LED cluster?
>
> And if there are 2 like colors of the LED defined in the same cluster would we just see a single
> file and write a common value to that file and the driver would have to update each
> red LED within that cluster. No independent control of like colored LEDs within the
> registered LED cluster.
>
> If the developer wants this level of control they would have to register two separate classes
>
> Correct?
I would abide by one color to one iout mapping. Registering more LEDs
under the same color feels more of a task for trigger.
>>>> brightness-model: defines brightness level to color configuration
>>>> mapping
>>>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>>>> - "rgb-<hue>": available only when all three red,green,blue colors
>>>> are present in the colors directory.
>>>> <hue> is a placeholder for given DT hue presets.
>>>> - "rgbw-<hue>": Same as above, but available only when white color
>>>> (any of amber or white-{cool|neutral|warm} can be
>>>> mapped to white) is also available. In this mode
>>>> max_brightness equals num-of-hue-presets + 1, and
>>>> max_brightness, when set, turns the "white" LED on
>>>
>>> Why do we need white combined here? Should this not be its own entity?
>>
>> To be able to set white color. We're still talking about one LED
>> element (although they can be be physically few LEDs in one case).
>> This is brightness file, so we've got to stick to the semantics.
>> Max brightness level should be the brightest. With RGBW LEDs we
>> fortunately have a means to achieve pure white, that's why
>> rgbw-<hue> would be beneficial. If you increase L component of
>> HSL color space, the max value gives white for all hues.
>> So maybe this brightness-model would be rather called hsl-<hue>.
>>
>> For RGBW LEDs, we would have to allow for more shades of white too,
>> like in [1].
>>
>
> Yep.
But this all would be left to the DT designer decision.
>>> Again I don't like limiting the color palette from the DT. I think that the
>>> user space can see what colors are available for that device and makes its own
>>> decision on what color to present.
>>>
>>> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
>>> same function trying to be achieved by the system designer? The RGB can be used to denote
>>> notification status and the white can be used to denote that a charger is connected. Motorola
>>> Droid did this.
>>
>> I hope I've just clarified my idea.
>>
>
> Its getting clearer. I would like to see it in code and play with it not as a user
> but as a developer. Make sure the paper model works as well as the real implementation.
>
> Is this model clear to the developer?
> How would a developer define what values are appropriate for the brightness-model?
We could create guidelines e.g. that for hsl-<hue> pattern, the
colors corresponding to brightness levels should be arranged so
that increasing brightness felt like increasing value of
L component of HSL.
But we wouldn't be able to enforce adherence to a particular scheme.
> Does the driver have to become overly complex to support simple color generation?
Not at all. Caching the colors written to the files in colors directory
would be responsibility of LED multi-color class. On echo 1 > sync
the core would call a new op e.g.
color_set(struct led_classdev_multicolor *mcled_cdev)
Driver would read in it colors cached in struct led_classdev_multicolor
and write them to the hardware.
> Thoughts on putting code to idea?
>
>
>>>
>>>> - "rgb-linear": I'm not sure if it should be available - it will
>>>> have unpredictable results
>>>>
>>>> brightness: sets/reads brightness in the way specific to the
>>>> current brightness-model. When more colors are available
>>>> (e.g. amber, blue, cyan, green, red, violet, white), they
>>>> are not touched by write to brightness).
>>>>
>>>> HSV->RGB conversion is left entirely to the userspace, which can set any
>>>> color with use of the proposed interface.
>>>>
>>>> Let's agree on sysfs interface first, and only after that move
>>>> to the DT details.
>>>>
>>>
>>> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
>>> an issue with defining product capabilities in the DT then we should keep that out of the DT.
>>
>> LED element is a device. I see nothing irrelevant for DT in describing the lighting specificity of a device mounted on the board. Please keep
>> in mind that it will not limit the number of colors available to set.
>> It will only allow to define mapping of brightness level to color.
>> We need that for current trigger mechanism to work with LED multi-color
>> class.
>>
>
> I see this now.
>
> Dan
>
>> [0] http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
>> [1] https://www.youtube.com/watch?v=NzlFmTqOh9M
>>
>
>
--
Best regards,
Jacek Anaszewski
Hi!
> >>What algorithm would be used for mapping brightness levels to RGB values
> >>in case of devices without hardware support for that?
> >
> >Output power = brightness / max_brightness * pwm_channel[x].
>
> IIUC you mean it as a formula for calculating r,g,b, values?
> I.e., on brightness setting we would have to do this calculation for
> each of three channels?
>
> Then, it will result in changing hue as well. That's why we're
> discussing HSV.
It should not change the hue, AFAICT, modulo the rounding errors.
> >>s/pwm/color/
> >
> >s/pwm/power/ would work for me.
>
> Power implies physical units. I'd prefer "intensity".
Intensity would work for me, too.
> >>Besides white also other color presets could be defined in DT.
> >
> >They should not be neccessary. When userspace knows what is white and
> >that power is linear with values in power_channels, it should be able
> >to do colorspace conversion itself.
>
> Have you verified it in practice? Would it allow to convert RGB values
> of the color displayed on the monitor to LED RGB class intensities,
> allowing to achieve similar color on the LED?
Yes, I think so.
My code is in unicsy_demo repository, in monitor/notint.py .
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
> > First, I think we want to decide if RGB LED should be presented as
> > 3 LEDs or as 1 LED... and what to do with existing RGB leds being
> > presented as 3 LEDs.
>
> What do we do with RGBW drivers? Like the LP5562. RGB can be grouped as a single
> LED but does the white LED get grouped too or should it register as a new LED?
>
> I am assuming the answer is that it would register as a new LED.
We could extend this to more than three channels, and specify "color"
for each channel. We could probably specify wavelength for
monochromatic LEDs and color temperature for white LEDs....
> > pwm_channels -- "1000 240 300" -- "red part should be full on, green
> > should be pwm controlled to 240/1000, blue should be 300/1000"
> >
>
> Why 1000? Why not based on a duty cycle percentage and let the LED driver figure out
> what that means to the device?
>
> pwm_channels -- "100 24 30" -- red part is full on 100%, green is 24% duty cycle and
> blue is 30% duty cycle.
Percentage would work, too. Having base of 1000 (not 100) gives a bit
more precision.
> > pwm_white -- "1000 500 400" -- tells userspace what to write to PWM
> > channels to get approximately white color.
> >
>
> Same as above on the duty cycle.
>
> But I still am in disagreement with the kernel detailing what is white or how to
> achieve white.
>
> Based on my earlier email about light pipes and the LED vendors and aging I think product
> developers will need to fine tune what is "white" on their product from user space or even a DT node.
>
Yes, this needs to be in the DT and kernel needs to expose it to
userspace in sysfs.
> > This would assume that RGB LEDs are always pwm controlled. That
> > seems to be true for hardware I seen.
> >
>
> GPIO LEDs can be binary or use PWM depending on what is needed.
>
> > + no complex math in kernel
>
> We can eliminate the math if we use the "color" file that was proposed and pass in absolute
> hex/decimal numbers for color.
No you can't.
> > + userspace knows enough to display arbitrary colors
> >
> > + userspace can use full range of available PWM intensities
> >
>
> Do we need a pwm_max file to indicate to the user space what the max values of the pwm
> is for each color?
Maybe. I'd assume brightness_max would be equal to max pwm.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Jacek
On 1/24/19 3:55 PM, Jacek Anaszewski wrote:
> Dan
>
> On 1/24/19 10:00 PM, Dan Murphy wrote:
>> Jacek
>>
>> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
>>> Dan,
>>>
>>> On 1/22/19 11:44 PM, Dan Murphy wrote:
>>>> Jacek
>>>>
>>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>>>> Hi all,
>>>>>
>>>>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>>>>> Hi Dan,
>>>>>>
>>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>>>> Jacek
>>>>>>>
>>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>>>> Jacek
>>>>>>>>
>>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>>>> Hi Dan,
>>>>>>>>>
>>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>>>> Hello
>>>>>>>>>>
>>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>>>> Hi!
>>>>>>>>>>>
>>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>
>>>>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +Example:
>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>>>>> like.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>>>>
>>>>>>>>>>>> What?
>>>>>>>>>>>
>>>>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>
>>>>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>>>>> But everyone interprets colors differently.
>>>>>>>>>>
>>>>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>>>>> Most probably not.
>>>>>>>>>>
>>>>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>>>>
>>>>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>>>>
>>>>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>>>>
>>>>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>>>>> coefficients.
>>>>>>>>>>
>>>>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>>>>> The colors should be close but may not be identical.
>>>>>>>>>>
>>>>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>>>>> light pipe and LED driver technology.
>>>>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>>>>
>>>>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>>>>> a hardware aspect to the calculation.
>>>>>>>>>>
>>>>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>>>>
>>>>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>>>>
>>>>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>>>>
>>>>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>>>>> I have.
>>>>>>>>>>>>
>>>>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>>>>
>>>>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>>>>> colors?
>>>>>>>>>>>
>>>>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Good suggestion for a rough test.
>>>>>>>>>>
>>>>>>>>>>>>> But...
>>>>>>>>>>>>>
>>>>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>>>>> interface?
>>>>>>>>>>>>
>>>>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>>>>
>>>>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>>>>> should work there, too.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>>>>
>>>>>>>>>>>> <rant>
>>>>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>>>>> </rant>
>>>>>>>>>>>
>>>>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>>>>
>>>>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>>>>> kernel.
>>>>>>>>>>>
>>>>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>>>>
>>>>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>>>>> them.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Sigh. You did not answer my question.
>>>>>>>>>>
>>>>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>>>>> RGB LED landscape.
>>>>>>>>>>
>>>>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>>>>> maybe color capabilities but not specific colors.
>>>>>>>>>
>>>>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>>>>
>>>>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>>>>
>>>>>>>>> sysfs interface:
>>>>>>>>>
>>>>>>>>> brightness-model: space separated list of available options:
>>>>>>>>> - rgb (default):
>>>>>>>>> - creates color file with "red green blue" decimal values
>>>>>>>>
>>>>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>>>>> Should the LED color come from the DT?
>>>>>>>>
>>>>>>>
>>>>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>>>>> But should they have the same interfaces as RGB?
>>>>>>>
>>>>>>> Should PWM control be a global interface?
>>>>>>
>>>>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>>>>
>>>>>> color_names: "red green blue white"
>>>>>>
>>>>>> echo "32 43 0 128" > color
>>>>>>
>>>>>> This way all elements would be set at same time from user space point of view.
>>>>>>
>>>>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>>>>
>>>>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>>>>
>>>>>> - red, green, blue
>>>>>> - red, green, blue, amber
>>>>>> - red, green, blue, white
>>>>>> - red, green, blue, white - cool
>>>>>> - red, green, blue, white - neutral
>>>>>> - red, green, blue, white - warm
>>>>>> - red, orange
>>>>>> - purple, ultraviolet
>>>>>> - amber, blue
>>>>>> - amber, blue, cyan, green, red, violet, white - cool
>>>>>> - amber, blue, green
>>>>>> - amber, green, blue
>>>>>> - and then lots of single special colors
>>>>>
>>>>> It suggested me another solution. Instead of LED RGB class
>>>>> we would have LED multi-color class.
>>>>>
>>>>
>>>> I was thinking the same thing this morning. But I was thinking that the RGB
>>>> class should be an additional class to stand on its own or can register to the
>>>> multi color class.
>>>>
>>>>> Sysfs interface design:
>>>>> -----------------------
>>>>>
>>>>> colors: directory containing files that map to
>>>>> the brightness of particular LEDs; there
>>>>> would be predefined color names that LED class
>>>>> driver should map iouts to, e.g.:
>>>>
>>>> Filling in the missing ideas with questions.
>>>>
>>>> Is it a directory or a file? If it is a directory does that not break the current
>>>> directory label model?
>>>>
>>>> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
>>>> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
>>>> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>>>>
>>>> Or are you saying it would be something like (More then likely this is what you intended)
>>>> /sys/class/leds/input4::numlock/colors?
>>>
>>> Yes, this is what I meant.
>>>
>>
>> OK. Thanks for the clarification
>>
>>>> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
>>>> knows that this is a multi color class and not a single LED color class.
>>>
>>> Like I am going to come up with standardized color names
>>> in my LED naming related patch, the multi-color names
>>> can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
>>>
>>
>> That may be better it is descriptive off the command line.
>>
>>>> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
>>>> variants when RGB is only available? And this can also present a single write to the kernel with the new
>>>> color values.
>>>
>>> My design already covers that in the form of files in the colors
>>> directory. Like I stated: "files that map to the brightness of
>>> particular LEDs". Single write is secured by "echo "write" > sync.
>>>
>>
>> OK. So set the new values and then tell the set the sync which will make the device driver write the
>> device.
>>
>> Sounds good. how about echo 1 > sync and we can stay away from a long string conversion
>
> We need also to be able to do a readout.
>
> If we changed "sync" to "rw" then we could come up with intuitive
> semantics:
>
> echo 1 > rw // write
> echo 0 > rw // read
>
> rw file would have WO permission.
I have re-written the lp50xx driver to show red, green, blue, sync and sync_enable files for each registered LED.
I added the sync_enable file so that the there can be real time control of the individual LEDs as well.
Turning on sync means that the user will write to one of the color files and the setting won't take affect until
sync is written.
If sync is off then the LED register is updated immediately.
Being able to turn on and off syncing maybe better. A developer may choose to set up the color and then sync
or they may want to ramp a specific color. This will help reduce user space writes but also reduce the number
of peripheral writes when color values do not change.
I am having difficulty in creating the colors directory in the device driver.
This appears to need to be done in the class when the class pointer is available.
>
>>>> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
>>>> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
>>>> colors.
>>>> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
>>>> if we start adding defines like white_warm, white_neutral and other variations to the color.
>>>
>>> We would not limit anything. Every color combination can be achieved
>>> by following this exemplary sequence:
>>>
>>> $ echo 154 > colors/red
>>> $ echo 232 > colors/green
>>> $ echo 43 > colors/blue
>>> # echo "write" > sync //only this changes hardware state
>>>
The code works more like this
$ :/sys/class/leds/lp5024:led1_mod# ls
blue device max_brightness red sync trigger
brightness green power subsystem sync_enable uevent
$ cat sync_enable
enabled // I can change this to return an int instead
$ echo 154 > red
$ echo 232 > green
$ echo 43 > blue
$ echo 1 > sync //this changes hardware state
$ echo 0 > sync_enable
$ cat sync_enable
disabled
$ echo 154 > red // changes red LED immediately
$ echo 232 > green // changes green LED immediately
$ echo 43 > blue // changes blue LED immediately
$ echo 1 > sync // Has no affect on the hardware
If this is OK I can post the patch with this update.
But I would rather put the file creation in a class and have the colors directory.
>>> brightness-model is provided only to define mapping of legacy brightness
>>> levels (governed by brightness file and led_set_brightness() API) to
>>> the specific combination of colors.
>>>
>>> For instance we can define three brightness levels for green hue:
>>>
>>> DT definition for it would look like below:
>>>
>>> rgb-green = <0x277c33 0x37b048 0x47e45d>;
>>>
>>> LED multi color class would then do the following mapping for
>>> each of the three brightness levels for rgb-green brightness model:
>>>
>>> $ echo rgb-green > brightness_model
>>> $ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
>>> $ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
>>> $ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
>>>
>>
>> OK I would have to play with this on the LP devices.
I have not done anything with this.
>>
>>>> What about IR LEDs used for night vision products? Do these fall into the multi color class?
>>>> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
>>>> flash class but it could be a multi color LED as well.
>>>>
>>>> How would traversing through the full color palette work if you were to want to produce a multi
>>>> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
>>>> Or in a product like the gaming keyboards that will change color or change backlight brightness?
>>>
>>> This is not meant as a solution for pattern generator but for
>>> consolidated source of multi color light. In the simplest case
>>> RGB LED elements like those used for lp5024 reference board,
>>> but it could be RGBWAUV LED [0] as well.
>>>
>>> For patterns traversing many LEDs I see a trigger as the best solution.
>>> Hmm, now I see that trigger mechanism actually can serve as very
>>> flexible pattern generator.
>>>
>>> We would need a device that could be configured to register
>>> a number of multi-led-patternN triggers, one per LED, and generate
>>> events for each trigger in a loop.
>>>
>>> The device would have to allow for configuring pattern intervals
>>> via sysfs, like in case of current pattern trigger.
>>>
>>> LED class devices would have to register for its events:
>>>
>>> $/sys/class/leds/led1 echo multi-led-pattern1 > trigger
>>> $/sys/class/leds/led2 echo multi-led-pattern2 > trigger
>>> $/sys/class/leds/led3 echo multi-led-pattern3 > trigger
>>>
>>
>> A bit off topic but I like the idea. We should save this for another day
>
> Yes, that's another story.
>
>>> The ability to define brightness models in DT would
>>> add even more flexibility.
>>>
>>
>> brightness models would be mandatory to support in the driver but an optional
>> DT entry.
>>
>> Is that a correct assumption?
>
> Correct.
>
>>>> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
>>>> capable of doing this?
>>>>
>>>> https://www.youtube.com/watch?v=pfKv3g2FeBE
>>>> or something like this
>>>>
>>>> https://www.youtube.com/watch?v=PO3auX3f5C4
>>>>
>>>> The LP5036 has this capability.
>>>>
>>>>> - red
>>>>> - green
>>>>> - blue
>>>>> - white
>>>>> - sync: accepts "write" and "read", which executes
>>>>> write/readout to/from a device respectively.
>>>>>
>>>>
>>>> What are these above, the values or the files under the colors directory?
>>>
>>> They are just color specific counterparts of monochrome brightness.
>>> In terms of lp50xx they would map to OUTn_COLOR registers.
>>>
>>>> I am assuming they are files.
>>>
>>> Right.
>>>
>>>> Are they mandatory or optional?
>>>
>>> Mandatory, one per each iout to control.
>>>
>>
>> OK And all the LEDs within this directory would be considered a LED cluster?
>>
>> And if there are 2 like colors of the LED defined in the same cluster would we just see a single
>> file and write a common value to that file and the driver would have to update each
>> red LED within that cluster. No independent control of like colored LEDs within the
>> registered LED cluster.
>>
>> If the developer wants this level of control they would have to register two separate classes
>>
>> Correct?
>
> I would abide by one color to one iout mapping. Registering more LEDs
> under the same color feels more of a task for trigger.
>
>>>>> brightness-model: defines brightness level to color configuration
>>>>> mapping
>>>>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>>>>> - "rgb-<hue>": available only when all three red,green,blue colors
>>>>> are present in the colors directory.
>>>>> <hue> is a placeholder for given DT hue presets.
>>>>> - "rgbw-<hue>": Same as above, but available only when white color
>>>>> (any of amber or white-{cool|neutral|warm} can be
>>>>> mapped to white) is also available. In this mode
>>>>> max_brightness equals num-of-hue-presets + 1, and
>>>>> max_brightness, when set, turns the "white" LED on
>>>>
>>>> Why do we need white combined here? Should this not be its own entity?
>>>
>>> To be able to set white color. We're still talking about one LED
>>> element (although they can be be physically few LEDs in one case).
>>> This is brightness file, so we've got to stick to the semantics.
>>> Max brightness level should be the brightest. With RGBW LEDs we
>>> fortunately have a means to achieve pure white, that's why
>>> rgbw-<hue> would be beneficial. If you increase L component of
>>> HSL color space, the max value gives white for all hues.
>>> So maybe this brightness-model would be rather called hsl-<hue>.
>>>
>>> For RGBW LEDs, we would have to allow for more shades of white too,
>>> like in [1].
>>>
>>
>> Yep.
>
> But this all would be left to the DT designer decision.
>
>>>> Again I don't like limiting the color palette from the DT. I think that the
>>>> user space can see what colors are available for that device and makes its own
>>>> decision on what color to present.
>>>>
>>>> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
>>>> same function trying to be achieved by the system designer? The RGB can be used to denote
>>>> notification status and the white can be used to denote that a charger is connected. Motorola
>>>> Droid did this.
>>>
>>> I hope I've just clarified my idea.
>>>
>>
>> Its getting clearer. I would like to see it in code and play with it not as a user
>> but as a developer. Make sure the paper model works as well as the real implementation.
>>
>> Is this model clear to the developer?
>> How would a developer define what values are appropriate for the brightness-model?
>
> We could create guidelines e.g. that for hsl-<hue> pattern, the
> colors corresponding to brightness levels should be arranged so
> that increasing brightness felt like increasing value of
> L component of HSL.
>
> But we wouldn't be able to enforce adherence to a particular scheme.
>
>> Does the driver have to become overly complex to support simple color generation?
>
> Not at all. Caching the colors written to the files in colors directory
> would be responsibility of LED multi-color class. On echo 1 > sync
> the core would call a new op e.g.
>
> color_set(struct led_classdev_multicolor *mcled_cdev)
>
> Driver would read in it colors cached in struct led_classdev_multicolor
> and write them to the hardware.
>
>> Thoughts on putting code to idea?
>>
>>
>>>>
>>>>> - "rgb-linear": I'm not sure if it should be available - it will
>>>>> have unpredictable results
>>>>>
>>>>> brightness: sets/reads brightness in the way specific to the
>>>>> current brightness-model. When more colors are available
>>>>> (e.g. amber, blue, cyan, green, red, violet, white), they
>>>>> are not touched by write to brightness).
>>>>>
>>>>> HSV->RGB conversion is left entirely to the userspace, which can set any
>>>>> color with use of the proposed interface.
>>>>>
>>>>> Let's agree on sysfs interface first, and only after that move
>>>>> to the DT details.
>>>>>
>>>>
>>>> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
>>>> an issue with defining product capabilities in the DT then we should keep that out of the DT.
>>>
>>> LED element is a device. I see nothing irrelevant for DT in describing the lighting specificity of a device mounted on the board. Please keep
>>> in mind that it will not limit the number of colors available to set.
>>> It will only allow to define mapping of brightness level to color.
>>> We need that for current trigger mechanism to work with LED multi-color
>>> class.
>>>
>>
>> I see this now.
>>
>> Dan
>>
>>> [0] http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
>>> [1] https://www.youtube.com/watch?v=NzlFmTqOh9M
>>>
>>
>>
>
--
------------------
Dan Murphy
Hi Dan,
On 1/29/19 2:56 PM, Dan Murphy wrote:
> Jacek
>
> On 1/24/19 3:55 PM, Jacek Anaszewski wrote:
>> Dan
>>
>> On 1/24/19 10:00 PM, Dan Murphy wrote:
>>> Jacek
>>>
>>> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
>>>> Dan,
>>>>
>>>> On 1/22/19 11:44 PM, Dan Murphy wrote:
>>>>> Jacek
>>>>>
>>>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>>>>>> Hi Dan,
>>>>>>>
>>>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>>>>> Jacek
>>>>>>>>
>>>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>>>>> Jacek
>>>>>>>>>
>>>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>>>>> Hi Dan,
>>>>>>>>>>
>>>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>>>>> Hello
>>>>>>>>>>>
>>>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>>>>> Hi!
>>>>>>>>>>>>
>>>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>> +Example:
>>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>>>>>> like.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>>>>>
>>>>>>>>>>>>> What?
>>>>>>>>>>>>
>>>>>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>>
>>>>>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>>>>>> But everyone interprets colors differently.
>>>>>>>>>>>
>>>>>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>>>>>> Most probably not.
>>>>>>>>>>>
>>>>>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>>>>>
>>>>>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>>>>>
>>>>>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>>>>>
>>>>>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>>>>>> coefficients.
>>>>>>>>>>>
>>>>>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>>>>>> The colors should be close but may not be identical.
>>>>>>>>>>>
>>>>>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>>>>>> light pipe and LED driver technology.
>>>>>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>>>>>
>>>>>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>>>>>> a hardware aspect to the calculation.
>>>>>>>>>>>
>>>>>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>>>>>
>>>>>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>>>>>
>>>>>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>>>>>> I have.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>>>>>
>>>>>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>>>>>> colors?
>>>>>>>>>>>>
>>>>>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Good suggestion for a rough test.
>>>>>>>>>>>
>>>>>>>>>>>>>> But...
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>>>>>> interface?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>>>>>
>>>>>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>>>>>> should work there, too.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>>>>>
>>>>>>>>>>>>> <rant>
>>>>>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>>>>>> </rant>
>>>>>>>>>>>>
>>>>>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>>>>>
>>>>>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>>>>>> kernel.
>>>>>>>>>>>>
>>>>>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>>>>>
>>>>>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>>>>>> them.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Sigh. You did not answer my question.
>>>>>>>>>>>
>>>>>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>>>>>> RGB LED landscape.
>>>>>>>>>>>
>>>>>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>>>>>> maybe color capabilities but not specific colors.
>>>>>>>>>>
>>>>>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>>>>>
>>>>>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>>>>>
>>>>>>>>>> sysfs interface:
>>>>>>>>>>
>>>>>>>>>> brightness-model: space separated list of available options:
>>>>>>>>>> - rgb (default):
>>>>>>>>>> - creates color file with "red green blue" decimal values
>>>>>>>>>
>>>>>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>>>>>> Should the LED color come from the DT?
>>>>>>>>>
>>>>>>>>
>>>>>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>>>>>> But should they have the same interfaces as RGB?
>>>>>>>>
>>>>>>>> Should PWM control be a global interface?
>>>>>>>
>>>>>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>>>>>
>>>>>>> color_names: "red green blue white"
>>>>>>>
>>>>>>> echo "32 43 0 128" > color
>>>>>>>
>>>>>>> This way all elements would be set at same time from user space point of view.
>>>>>>>
>>>>>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>>>>>
>>>>>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>>>>>
>>>>>>> - red, green, blue
>>>>>>> - red, green, blue, amber
>>>>>>> - red, green, blue, white
>>>>>>> - red, green, blue, white - cool
>>>>>>> - red, green, blue, white - neutral
>>>>>>> - red, green, blue, white - warm
>>>>>>> - red, orange
>>>>>>> - purple, ultraviolet
>>>>>>> - amber, blue
>>>>>>> - amber, blue, cyan, green, red, violet, white - cool
>>>>>>> - amber, blue, green
>>>>>>> - amber, green, blue
>>>>>>> - and then lots of single special colors
>>>>>>
>>>>>> It suggested me another solution. Instead of LED RGB class
>>>>>> we would have LED multi-color class.
>>>>>>
>>>>>
>>>>> I was thinking the same thing this morning. But I was thinking that the RGB
>>>>> class should be an additional class to stand on its own or can register to the
>>>>> multi color class.
>>>>>
>>>>>> Sysfs interface design:
>>>>>> -----------------------
>>>>>>
>>>>>> colors: directory containing files that map to
>>>>>> the brightness of particular LEDs; there
>>>>>> would be predefined color names that LED class
>>>>>> driver should map iouts to, e.g.:
>>>>>
>>>>> Filling in the missing ideas with questions.
>>>>>
>>>>> Is it a directory or a file? If it is a directory does that not break the current
>>>>> directory label model?
>>>>>
>>>>> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
>>>>> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
>>>>> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>>>>>
>>>>> Or are you saying it would be something like (More then likely this is what you intended)
>>>>> /sys/class/leds/input4::numlock/colors?
>>>>
>>>> Yes, this is what I meant.
>>>>
>>>
>>> OK. Thanks for the clarification
>>>
>>>>> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
>>>>> knows that this is a multi color class and not a single LED color class.
>>>>
>>>> Like I am going to come up with standardized color names
>>>> in my LED naming related patch, the multi-color names
>>>> can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
>>>>
>>>
>>> That may be better it is descriptive off the command line.
>>>
>>>>> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
>>>>> variants when RGB is only available? And this can also present a single write to the kernel with the new
>>>>> color values.
>>>>
>>>> My design already covers that in the form of files in the colors
>>>> directory. Like I stated: "files that map to the brightness of
>>>> particular LEDs". Single write is secured by "echo "write" > sync.
>>>>
>>>
>>> OK. So set the new values and then tell the set the sync which will make the device driver write the
>>> device.
>>>
>>> Sounds good. how about echo 1 > sync and we can stay away from a long string conversion
>>
>> We need also to be able to do a readout.
>>
>> If we changed "sync" to "rw" then we could come up with intuitive
>> semantics:
>>
>> echo 1 > rw // write
>> echo 0 > rw // read
>>
>> rw file would have WO permission.
>
> I have re-written the lp50xx driver to show red, green, blue, sync and sync_enable files for each registered LED.
Did you change your mind regarding LED multi color class implementation?
> I added the sync_enable file so that the there can be real time control of the individual LEDs as well.
Yes, it's a good idea.
> Turning on sync means that the user will write to one of the color files and the setting won't take affect until
> sync is written.
>
> If sync is off then the LED register is updated immediately.
>
> Being able to turn on and off syncing maybe better. A developer may choose to set up the color and then sync
> or they may want to ramp a specific color. This will help reduce user space writes but also reduce the number
> of peripheral writes when color values do not change.
>
> I am having difficulty in creating the colors directory in the device driver.
> This appears to need to be done in the class when the class pointer is available.
Not necessarily, you need only dev->kobj. Please follow the
implementation of drivers/usb/core/ledtrig-usbport.c. However I would
really prefer if it became a part of new LED multi color class.
>>>>> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
>>>>> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
>>>>> colors.
>>>>> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
>>>>> if we start adding defines like white_warm, white_neutral and other variations to the color.
>>>>
>>>> We would not limit anything. Every color combination can be achieved
>>>> by following this exemplary sequence:
>>>>
>>>> $ echo 154 > colors/red
>>>> $ echo 232 > colors/green
>>>> $ echo 43 > colors/blue
>>>> # echo "write" > sync //only this changes hardware state
>>>>
>
> The code works more like this
> $ :/sys/class/leds/lp5024:led1_mod# ls
> blue device max_brightness red sync trigger
> brightness green power subsystem sync_enable uevent
>
> $ cat sync_enable
> enabled // I can change this to return an int instead
> $ echo 154 > red
> $ echo 232 > green
> $ echo 43 > blue
> $ echo 1 > sync //this changes hardware state
>
> $ echo 0 > sync_enable
> $ cat sync_enable
> disabled
> $ echo 154 > red // changes red LED immediately
> $ echo 232 > green // changes green LED immediately
> $ echo 43 > blue // changes blue LED immediately
> $ echo 1 > sync // Has no affect on the hardware
>
> If this is OK I can post the patch with this update.
>
> But I would rather put the file creation in a class and have the colors directory.
Yes, please post your work when it is ready.
>>>> brightness-model is provided only to define mapping of legacy brightness
>>>> levels (governed by brightness file and led_set_brightness() API) to
>>>> the specific combination of colors.
>>>>
>>>> For instance we can define three brightness levels for green hue:
>>>>
>>>> DT definition for it would look like below:
>>>>
>>>> rgb-green = <0x277c33 0x37b048 0x47e45d>;
>>>>
>>>> LED multi color class would then do the following mapping for
>>>> each of the three brightness levels for rgb-green brightness model:
>>>>
>>>> $ echo rgb-green > brightness_model
>>>> $ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
>>>> $ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
>>>> $ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
>>>>
>>>
>>> OK I would have to play with this on the LP devices.
>
> I have not done anything with this.
>
>>>
>>>>> What about IR LEDs used for night vision products? Do these fall into the multi color class?
>>>>> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
>>>>> flash class but it could be a multi color LED as well.
>>>>>
>>>>> How would traversing through the full color palette work if you were to want to produce a multi
>>>>> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
>>>>> Or in a product like the gaming keyboards that will change color or change backlight brightness?
>>>>
>>>> This is not meant as a solution for pattern generator but for
>>>> consolidated source of multi color light. In the simplest case
>>>> RGB LED elements like those used for lp5024 reference board,
>>>> but it could be RGBWAUV LED [0] as well.
>>>>
>>>> For patterns traversing many LEDs I see a trigger as the best solution.
>>>> Hmm, now I see that trigger mechanism actually can serve as very
>>>> flexible pattern generator.
>>>>
>>>> We would need a device that could be configured to register
>>>> a number of multi-led-patternN triggers, one per LED, and generate
>>>> events for each trigger in a loop.
>>>>
>>>> The device would have to allow for configuring pattern intervals
>>>> via sysfs, like in case of current pattern trigger.
>>>>
>>>> LED class devices would have to register for its events:
>>>>
>>>> $/sys/class/leds/led1 echo multi-led-pattern1 > trigger
>>>> $/sys/class/leds/led2 echo multi-led-pattern2 > trigger
>>>> $/sys/class/leds/led3 echo multi-led-pattern3 > trigger
>>>>
>>>
>>> A bit off topic but I like the idea. We should save this for another day
>>
>> Yes, that's another story.
>>
>>>> The ability to define brightness models in DT would
>>>> add even more flexibility.
>>>>
>>>
>>> brightness models would be mandatory to support in the driver but an optional
>>> DT entry.
>>>
>>> Is that a correct assumption?
>>
>> Correct.
>>
>>>>> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
>>>>> capable of doing this?
>>>>>
>>>>> https://www.youtube.com/watch?v=pfKv3g2FeBE
>>>>> or something like this
>>>>>
>>>>> https://www.youtube.com/watch?v=PO3auX3f5C4
>>>>>
>>>>> The LP5036 has this capability.
>>>>>
>>>>>> - red
>>>>>> - green
>>>>>> - blue
>>>>>> - white
>>>>>> - sync: accepts "write" and "read", which executes
>>>>>> write/readout to/from a device respectively.
>>>>>>
>>>>>
>>>>> What are these above, the values or the files under the colors directory?
>>>>
>>>> They are just color specific counterparts of monochrome brightness.
>>>> In terms of lp50xx they would map to OUTn_COLOR registers.
>>>>
>>>>> I am assuming they are files.
>>>>
>>>> Right.
>>>>
>>>>> Are they mandatory or optional?
>>>>
>>>> Mandatory, one per each iout to control.
>>>>
>>>
>>> OK And all the LEDs within this directory would be considered a LED cluster?
>>>
>>> And if there are 2 like colors of the LED defined in the same cluster would we just see a single
>>> file and write a common value to that file and the driver would have to update each
>>> red LED within that cluster. No independent control of like colored LEDs within the
>>> registered LED cluster.
>>>
>>> If the developer wants this level of control they would have to register two separate classes
>>>
>>> Correct?
>>
>> I would abide by one color to one iout mapping. Registering more LEDs
>> under the same color feels more of a task for trigger.
>>
>>>>>> brightness-model: defines brightness level to color configuration
>>>>>> mapping
>>>>>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>>>>>> - "rgb-<hue>": available only when all three red,green,blue colors
>>>>>> are present in the colors directory.
>>>>>> <hue> is a placeholder for given DT hue presets.
>>>>>> - "rgbw-<hue>": Same as above, but available only when white color
>>>>>> (any of amber or white-{cool|neutral|warm} can be
>>>>>> mapped to white) is also available. In this mode
>>>>>> max_brightness equals num-of-hue-presets + 1, and
>>>>>> max_brightness, when set, turns the "white" LED on
>>>>>
>>>>> Why do we need white combined here? Should this not be its own entity?
>>>>
>>>> To be able to set white color. We're still talking about one LED
>>>> element (although they can be be physically few LEDs in one case).
>>>> This is brightness file, so we've got to stick to the semantics.
>>>> Max brightness level should be the brightest. With RGBW LEDs we
>>>> fortunately have a means to achieve pure white, that's why
>>>> rgbw-<hue> would be beneficial. If you increase L component of
>>>> HSL color space, the max value gives white for all hues.
>>>> So maybe this brightness-model would be rather called hsl-<hue>.
>>>>
>>>> For RGBW LEDs, we would have to allow for more shades of white too,
>>>> like in [1].
>>>>
>>>
>>> Yep.
>>
>> But this all would be left to the DT designer decision.
>>
>>>>> Again I don't like limiting the color palette from the DT. I think that the
>>>>> user space can see what colors are available for that device and makes its own
>>>>> decision on what color to present.
>>>>>
>>>>> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
>>>>> same function trying to be achieved by the system designer? The RGB can be used to denote
>>>>> notification status and the white can be used to denote that a charger is connected. Motorola
>>>>> Droid did this.
>>>>
>>>> I hope I've just clarified my idea.
>>>>
>>>
>>> Its getting clearer. I would like to see it in code and play with it not as a user
>>> but as a developer. Make sure the paper model works as well as the real implementation.
>>>
>>> Is this model clear to the developer?
>>> How would a developer define what values are appropriate for the brightness-model?
>>
>> We could create guidelines e.g. that for hsl-<hue> pattern, the
>> colors corresponding to brightness levels should be arranged so
>> that increasing brightness felt like increasing value of
>> L component of HSL.
>>
>> But we wouldn't be able to enforce adherence to a particular scheme.
>>
>>> Does the driver have to become overly complex to support simple color generation?
>>
>> Not at all. Caching the colors written to the files in colors directory
>> would be responsibility of LED multi-color class. On echo 1 > sync
>> the core would call a new op e.g.
>>
>> color_set(struct led_classdev_multicolor *mcled_cdev)
>>
>> Driver would read in it colors cached in struct led_classdev_multicolor
>> and write them to the hardware.
>>
>>> Thoughts on putting code to idea?
>>>
>>>
>>>>>
>>>>>> - "rgb-linear": I'm not sure if it should be available - it will
>>>>>> have unpredictable results
>>>>>>
>>>>>> brightness: sets/reads brightness in the way specific to the
>>>>>> current brightness-model. When more colors are available
>>>>>> (e.g. amber, blue, cyan, green, red, violet, white), they
>>>>>> are not touched by write to brightness).
>>>>>>
>>>>>> HSV->RGB conversion is left entirely to the userspace, which can set any
>>>>>> color with use of the proposed interface.
>>>>>>
>>>>>> Let's agree on sysfs interface first, and only after that move
>>>>>> to the DT details.
>>>>>>
>>>>>
>>>>> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
>>>>> an issue with defining product capabilities in the DT then we should keep that out of the DT.
>>>>
>>>> LED element is a device. I see nothing irrelevant for DT in describing the lighting specificity of a device mounted on the board. Please keep
>>>> in mind that it will not limit the number of colors available to set.
>>>> It will only allow to define mapping of brightness level to color.
>>>> We need that for current trigger mechanism to work with LED multi-color
>>>> class.
>>>>
>>>
>>> I see this now.
>>>
>>> Dan
>>>
>>>> [0] http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
>>>> [1] https://www.youtube.com/watch?v=NzlFmTqOh9M
>>>>
>>>
>>>
>>
>
>
--
Best regards,
Jacek Anaszewski
Jacek
On 1/29/19 2:19 PM, Jacek Anaszewski wrote:
> Hi Dan,
>
> On 1/29/19 2:56 PM, Dan Murphy wrote:
>> Jacek
>>
>> On 1/24/19 3:55 PM, Jacek Anaszewski wrote:
>>> Dan
>>>
>>> On 1/24/19 10:00 PM, Dan Murphy wrote:
>>>> Jacek
>>>>
>>>> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
>>>>> Dan,
>>>>>
>>>>> On 1/22/19 11:44 PM, Dan Murphy wrote:
>>>>>> Jacek
>>>>>>
>>>>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>>>>>> Hi all,
>>>>>>>
>>>>>>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>>>>>>> Hi Dan,
>>>>>>>>
>>>>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>>>>>> Jacek
>>>>>>>>>
>>>>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>>>>>> Jacek
>>>>>>>>>>
>>>>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>>>>>> Hi Dan,
>>>>>>>>>>>
>>>>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>>>>>> Hello
>>>>>>>>>>>>
>>>>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>> +Example:
>>>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>>>>>>> like.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> What?
>>>>>>>>>>>>>
>>>>>>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>>>
>>>>>>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>>>>>>> But everyone interprets colors differently.
>>>>>>>>>>>>
>>>>>>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>>>>>>> Most probably not.
>>>>>>>>>>>>
>>>>>>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>>>>>>
>>>>>>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>>>>>>
>>>>>>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>>>>>>
>>>>>>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>>>>>>> coefficients.
>>>>>>>>>>>>
>>>>>>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>>>>>>> The colors should be close but may not be identical.
>>>>>>>>>>>>
>>>>>>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>>>>>>> light pipe and LED driver technology.
>>>>>>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>>>>>>
>>>>>>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>>>>>>> a hardware aspect to the calculation.
>>>>>>>>>>>>
>>>>>>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>>>>>>
>>>>>>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>>>>>>
>>>>>>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>>>>>>> I have.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>>>>>>
>>>>>>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>>>>>>> colors?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Good suggestion for a rough test.
>>>>>>>>>>>>
>>>>>>>>>>>>>>> But...
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>>>>>>> interface?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>>>>>>> should work there, too.
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>>>>>>
>>>>>>>>>>>>>> <rant>
>>>>>>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>>>>>>> </rant>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>>>>>>> kernel.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>>>>>>> them.
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Sigh. You did not answer my question.
>>>>>>>>>>>>
>>>>>>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>>>>>>> RGB LED landscape.
>>>>>>>>>>>>
>>>>>>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>>>>>>> maybe color capabilities but not specific colors.
>>>>>>>>>>>
>>>>>>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>>>>>>
>>>>>>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>>>>>>
>>>>>>>>>>> sysfs interface:
>>>>>>>>>>>
>>>>>>>>>>> brightness-model: space separated list of available options:
>>>>>>>>>>> - rgb (default):
>>>>>>>>>>> - creates color file with "red green blue" decimal values
>>>>>>>>>>
>>>>>>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>>>>>>> Should the LED color come from the DT?
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>>>>>>> But should they have the same interfaces as RGB?
>>>>>>>>>
>>>>>>>>> Should PWM control be a global interface?
>>>>>>>>
>>>>>>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>>>>>>
>>>>>>>> color_names: "red green blue white"
>>>>>>>>
>>>>>>>> echo "32 43 0 128" > color
>>>>>>>>
>>>>>>>> This way all elements would be set at same time from user space point of view.
>>>>>>>>
>>>>>>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>>>>>>
>>>>>>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>>>>>>
>>>>>>>> - red, green, blue
>>>>>>>> - red, green, blue, amber
>>>>>>>> - red, green, blue, white
>>>>>>>> - red, green, blue, white - cool
>>>>>>>> - red, green, blue, white - neutral
>>>>>>>> - red, green, blue, white - warm
>>>>>>>> - red, orange
>>>>>>>> - purple, ultraviolet
>>>>>>>> - amber, blue
>>>>>>>> - amber, blue, cyan, green, red, violet, white - cool
>>>>>>>> - amber, blue, green
>>>>>>>> - amber, green, blue
>>>>>>>> - and then lots of single special colors
>>>>>>>
>>>>>>> It suggested me another solution. Instead of LED RGB class
>>>>>>> we would have LED multi-color class.
>>>>>>>
>>>>>>
>>>>>> I was thinking the same thing this morning. But I was thinking that the RGB
>>>>>> class should be an additional class to stand on its own or can register to the
>>>>>> multi color class.
>>>>>>
>>>>>>> Sysfs interface design:
>>>>>>> -----------------------
>>>>>>>
>>>>>>> colors: directory containing files that map to
>>>>>>> the brightness of particular LEDs; there
>>>>>>> would be predefined color names that LED class
>>>>>>> driver should map iouts to, e.g.:
>>>>>>
>>>>>> Filling in the missing ideas with questions.
>>>>>>
>>>>>> Is it a directory or a file? If it is a directory does that not break the current
>>>>>> directory label model?
>>>>>>
>>>>>> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
>>>>>> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
>>>>>> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>>>>>>
>>>>>> Or are you saying it would be something like (More then likely this is what you intended)
>>>>>> /sys/class/leds/input4::numlock/colors?
>>>>>
>>>>> Yes, this is what I meant.
>>>>>
>>>>
>>>> OK. Thanks for the clarification
>>>>
>>>>>> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
>>>>>> knows that this is a multi color class and not a single LED color class.
>>>>>
>>>>> Like I am going to come up with standardized color names
>>>>> in my LED naming related patch, the multi-color names
>>>>> can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
>>>>>
>>>>
>>>> That may be better it is descriptive off the command line.
>>>>
>>>>>> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
>>>>>> variants when RGB is only available? And this can also present a single write to the kernel with the new
>>>>>> color values.
>>>>>
>>>>> My design already covers that in the form of files in the colors
>>>>> directory. Like I stated: "files that map to the brightness of
>>>>> particular LEDs". Single write is secured by "echo "write" > sync.
>>>>>
>>>>
>>>> OK. So set the new values and then tell the set the sync which will make the device driver write the
>>>> device.
>>>>
>>>> Sounds good. how about echo 1 > sync and we can stay away from a long string conversion
>>>
>>> We need also to be able to do a readout.
>>>
>>> If we changed "sync" to "rw" then we could come up with intuitive
>>> semantics:
>>>
>>> echo 1 > rw // write
>>> echo 0 > rw // read
>>>
>>> rw file would have WO permission.
>>
>> I have re-written the lp50xx driver to show red, green, blue, sync and sync_enable files for each registered LED.
>
> Did you change your mind regarding LED multi color class implementation?
>
No. I just did not want to put effort into the class if the interfaces were not agreed upon.
So if we are good with the interfaces I can start the MC class.
>> I added the sync_enable file so that the there can be real time control of the individual LEDs as well.
>
> Yes, it's a good idea.
>
>> Turning on sync means that the user will write to one of the color files and the setting won't take affect until
>> sync is written.
>>
>> If sync is off then the LED register is updated immediately.
>>
>> Being able to turn on and off syncing maybe better. A developer may choose to set up the color and then sync
>> or they may want to ramp a specific color. This will help reduce user space writes but also reduce the number
>> of peripheral writes when color values do not change.
>>
>> I am having difficulty in creating the colors directory in the device driver.
>> This appears to need to be done in the class when the class pointer is available.
>
> Not necessarily, you need only dev->kobj. Please follow the implementation of drivers/usb/core/ledtrig-usbport.c. However I would
> really prefer if it became a part of new LED multi color class.
>
It will. I should be able to create the colors directory there as well.
I need to figure out how to cleanly tell the MC class what LEDs are available.
>>>>>> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
>>>>>> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
>>>>>> colors.
>>>>>> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
>>>>>> if we start adding defines like white_warm, white_neutral and other variations to the color.
>>>>>
>>>>> We would not limit anything. Every color combination can be achieved
>>>>> by following this exemplary sequence:
>>>>>
>>>>> $ echo 154 > colors/red
>>>>> $ echo 232 > colors/green
>>>>> $ echo 43 > colors/blue
>>>>> # echo "write" > sync //only this changes hardware state
>>>>>
>>
>> The code works more like this
>> $ :/sys/class/leds/lp5024:led1_mod# ls
>> blue device max_brightness red sync trigger
>> brightness green power subsystem sync_enable uevent
>>
>> $ cat sync_enable
>> enabled // I can change this to return an int instead
>> $ echo 154 > red
>> $ echo 232 > green
>> $ echo 43 > blue
>> $ echo 1 > sync //this changes hardware state
>>
>> $ echo 0 > sync_enable
>> $ cat sync_enable
>> disabled
>> $ echo 154 > red // changes red LED immediately
>> $ echo 232 > green // changes green LED immediately
>> $ echo 43 > blue // changes blue LED immediately
>> $ echo 1 > sync // Has no affect on the hardware
>>
>> If this is OK I can post the patch with this update.
>>
>> But I would rather put the file creation in a class and have the colors directory.
>
> Yes, please post your work when it is ready.
OK. I will derive the class and try to post it by the EOW.
>
>>>>> brightness-model is provided only to define mapping of legacy brightness
>>>>> levels (governed by brightness file and led_set_brightness() API) to
>>>>> the specific combination of colors.
>>>>>
>>>>> For instance we can define three brightness levels for green hue:
>>>>>
>>>>> DT definition for it would look like below:
>>>>>
>>>>> rgb-green = <0x277c33 0x37b048 0x47e45d>;
>>>>>
>>>>> LED multi color class would then do the following mapping for
>>>>> each of the three brightness levels for rgb-green brightness model:
>>>>>
>>>>> $ echo rgb-green > brightness_model
>>>>> $ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
>>>>> $ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
>>>>> $ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
>>>>>
>>>>
>>>> OK I would have to play with this on the LP devices.
>>
>> I have not done anything with this.
>>
I will omit this until we figure out how to nicely present this to user space from the MC class.
Or maybe it is something you can add once we have the class ready.
Dan
>>>>
>>>>>> What about IR LEDs used for night vision products? Do these fall into the multi color class?
>>>>>> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
>>>>>> flash class but it could be a multi color LED as well.
>>>>>>
>>>>>> How would traversing through the full color palette work if you were to want to produce a multi
>>>>>> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
>>>>>> Or in a product like the gaming keyboards that will change color or change backlight brightness?
>>>>>
>>>>> This is not meant as a solution for pattern generator but for
>>>>> consolidated source of multi color light. In the simplest case
>>>>> RGB LED elements like those used for lp5024 reference board,
>>>>> but it could be RGBWAUV LED [0] as well.
>>>>>
>>>>> For patterns traversing many LEDs I see a trigger as the best solution.
>>>>> Hmm, now I see that trigger mechanism actually can serve as very
>>>>> flexible pattern generator.
>>>>>
>>>>> We would need a device that could be configured to register
>>>>> a number of multi-led-patternN triggers, one per LED, and generate
>>>>> events for each trigger in a loop.
>>>>>
>>>>> The device would have to allow for configuring pattern intervals
>>>>> via sysfs, like in case of current pattern trigger.
>>>>>
>>>>> LED class devices would have to register for its events:
>>>>>
>>>>> $/sys/class/leds/led1 echo multi-led-pattern1 > trigger
>>>>> $/sys/class/leds/led2 echo multi-led-pattern2 > trigger
>>>>> $/sys/class/leds/led3 echo multi-led-pattern3 > trigger
>>>>>
>>>>
>>>> A bit off topic but I like the idea. We should save this for another day
>>>
>>> Yes, that's another story.
>>>
>>>>> The ability to define brightness models in DT would
>>>>> add even more flexibility.
>>>>>
>>>>
>>>> brightness models would be mandatory to support in the driver but an optional
>>>> DT entry.
>>>>
>>>> Is that a correct assumption?
>>>
>>> Correct.
>>>
>>>>>> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
>>>>>> capable of doing this?
>>>>>>
>>>>>> https://www.youtube.com/watch?v=pfKv3g2FeBE
>>>>>> or something like this
>>>>>>
>>>>>> https://www.youtube.com/watch?v=PO3auX3f5C4
>>>>>>
>>>>>> The LP5036 has this capability.
>>>>>>
>>>>>>> - red
>>>>>>> - green
>>>>>>> - blue
>>>>>>> - white
>>>>>>> - sync: accepts "write" and "read", which executes
>>>>>>> write/readout to/from a device respectively.
>>>>>>>
>>>>>>
>>>>>> What are these above, the values or the files under the colors directory?
>>>>>
>>>>> They are just color specific counterparts of monochrome brightness.
>>>>> In terms of lp50xx they would map to OUTn_COLOR registers.
>>>>>
>>>>>> I am assuming they are files.
>>>>>
>>>>> Right.
>>>>>
>>>>>> Are they mandatory or optional?
>>>>>
>>>>> Mandatory, one per each iout to control.
>>>>>
>>>>
>>>> OK And all the LEDs within this directory would be considered a LED cluster?
>>>>
>>>> And if there are 2 like colors of the LED defined in the same cluster would we just see a single
>>>> file and write a common value to that file and the driver would have to update each
>>>> red LED within that cluster. No independent control of like colored LEDs within the
>>>> registered LED cluster.
>>>>
>>>> If the developer wants this level of control they would have to register two separate classes
>>>>
>>>> Correct?
>>>
>>> I would abide by one color to one iout mapping. Registering more LEDs
>>> under the same color feels more of a task for trigger.
>>>
>>>>>>> brightness-model: defines brightness level to color configuration
>>>>>>> mapping
>>>>>>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>>>>>>> - "rgb-<hue>": available only when all three red,green,blue colors
>>>>>>> are present in the colors directory.
>>>>>>> <hue> is a placeholder for given DT hue presets.
>>>>>>> - "rgbw-<hue>": Same as above, but available only when white color
>>>>>>> (any of amber or white-{cool|neutral|warm} can be
>>>>>>> mapped to white) is also available. In this mode
>>>>>>> max_brightness equals num-of-hue-presets + 1, and
>>>>>>> max_brightness, when set, turns the "white" LED on
>>>>>>
>>>>>> Why do we need white combined here? Should this not be its own entity?
>>>>>
>>>>> To be able to set white color. We're still talking about one LED
>>>>> element (although they can be be physically few LEDs in one case).
>>>>> This is brightness file, so we've got to stick to the semantics.
>>>>> Max brightness level should be the brightest. With RGBW LEDs we
>>>>> fortunately have a means to achieve pure white, that's why
>>>>> rgbw-<hue> would be beneficial. If you increase L component of
>>>>> HSL color space, the max value gives white for all hues.
>>>>> So maybe this brightness-model would be rather called hsl-<hue>.
>>>>>
>>>>> For RGBW LEDs, we would have to allow for more shades of white too,
>>>>> like in [1].
>>>>>
>>>>
>>>> Yep.
>>>
>>> But this all would be left to the DT designer decision.
>>>
>>>>>> Again I don't like limiting the color palette from the DT. I think that the
>>>>>> user space can see what colors are available for that device and makes its own
>>>>>> decision on what color to present.
>>>>>>
>>>>>> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
>>>>>> same function trying to be achieved by the system designer? The RGB can be used to denote
>>>>>> notification status and the white can be used to denote that a charger is connected. Motorola
>>>>>> Droid did this.
>>>>>
>>>>> I hope I've just clarified my idea.
>>>>>
>>>>
>>>> Its getting clearer. I would like to see it in code and play with it not as a user
>>>> but as a developer. Make sure the paper model works as well as the real implementation.
>>>>
>>>> Is this model clear to the developer?
>>>> How would a developer define what values are appropriate for the brightness-model?
>>>
>>> We could create guidelines e.g. that for hsl-<hue> pattern, the
>>> colors corresponding to brightness levels should be arranged so
>>> that increasing brightness felt like increasing value of
>>> L component of HSL.
>>>
>>> But we wouldn't be able to enforce adherence to a particular scheme.
>>>
>>>> Does the driver have to become overly complex to support simple color generation?
>>>
>>> Not at all. Caching the colors written to the files in colors directory
>>> would be responsibility of LED multi-color class. On echo 1 > sync
>>> the core would call a new op e.g.
>>>
>>> color_set(struct led_classdev_multicolor *mcled_cdev)
>>>
>>> Driver would read in it colors cached in struct led_classdev_multicolor
>>> and write them to the hardware.
>>>
>>>> Thoughts on putting code to idea?
>>>>
>>>>
>>>>>>
>>>>>>> - "rgb-linear": I'm not sure if it should be available - it will
>>>>>>> have unpredictable results
>>>>>>>
>>>>>>> brightness: sets/reads brightness in the way specific to the
>>>>>>> current brightness-model. When more colors are available
>>>>>>> (e.g. amber, blue, cyan, green, red, violet, white), they
>>>>>>> are not touched by write to brightness).
>>>>>>>
>>>>>>> HSV->RGB conversion is left entirely to the userspace, which can set any
>>>>>>> color with use of the proposed interface.
>>>>>>>
>>>>>>> Let's agree on sysfs interface first, and only after that move
>>>>>>> to the DT details.
>>>>>>>
>>>>>>
>>>>>> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
>>>>>> an issue with defining product capabilities in the DT then we should keep that out of the DT.
>>>>>
>>>>> LED element is a device. I see nothing irrelevant for DT in describing the lighting specificity of a device mounted on the board. Please keep
>>>>> in mind that it will not limit the number of colors available to set.
>>>>> It will only allow to define mapping of brightness level to color.
>>>>> We need that for current trigger mechanism to work with LED multi-color
>>>>> class.
>>>>>
>>>>
>>>> I see this now.
>>>>
>>>> Dan
>>>>
>>>>> [0] http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
>>>>> [1] https://www.youtube.com/watch?v=NzlFmTqOh9M
>>>>>
>>>>
>>>>
>>>
>>
>>
>
--
------------------
Dan Murphy
Hi!
Could you, trim the parts of email you do not need in the reply? This
is quite annoying to follow:
On Tue 2019-01-29 14:26:20, Dan Murphy wrote:
> Jacek
>
> On 1/29/19 2:19 PM, Jacek Anaszewski wrote:
> > Hi Dan,
> >
> > On 1/29/19 2:56 PM, Dan Murphy wrote:
> >> Jacek
> >>
> >> On 1/24/19 3:55 PM, Jacek Anaszewski wrote:
> >>> Dan
> >>>
> >>> On 1/24/19 10:00 PM, Dan Murphy wrote:
> >>>> Jacek
> >>>>
> >>>> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
> >>>>> Dan,
> >>>>>
> >>>>> On 1/22/19 11:44 PM, Dan Murphy wrote:
> >>>>>> Jacek
> >>>>>>
> >>>>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
> >>>>>>> Hi all,
> >>>>>>>
> >>>>>>> On 1/20/19 7:42 AM, Vesa J??skel?inen wrote:
> >>>>>>>> Hi Dan,
> >>>>>>>>
> >>>>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
> >>>>>>>>> Jacek
> >>>>>>>>>
> >>>>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
> >>>>>>>>>> Jacek
> >>>>>>>>>>
> >>>>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
> >>>>>>>>>>> Hi Dan,
> >>>>>>>>>>>
> >>>>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
> >>>>>>>>>>>> Hello
> >>>>>>>>>>>>
> >>>>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
> >>>>>>>>>>>>> Hi!
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
> >>>>>>>>>>>>>>> Hi!
> >>>>>>>>>>>>>>>
...
> >> If this is OK I can post the patch with this update.
> >>
> >> But I would rather put the file creation in a class and have the colors directory.
> >
> > Yes, please post your work when it is ready.
>
> OK. I will derive the class and try to post it by the EOW.
You can do that, but if you post the description of kernel<->user
interface, first, you may save yourself a bit of coding...
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Pavel
On 1/29/19 3:45 PM, Pavel Machek wrote:
> Hi!
>
> Could you, trim the parts of email you do not need in the reply? This
> is quite annoying to follow:
>
Agreed.
> On Tue 2019-01-29 14:26:20, Dan Murphy wrote:
>> Jacek
>>
>> On 1/29/19 2:19 PM, Jacek Anaszewski wrote:
>>> Hi Dan,
>>>
>>> On 1/29/19 2:56 PM, Dan Murphy wrote:
>>>> Jacek
>>>>
>>>> On 1/24/19 3:55 PM, Jacek Anaszewski wrote:
>>>>> Dan
>>>>>
>>>>> On 1/24/19 10:00 PM, Dan Murphy wrote:
>>>>>> Jacek
>>>>>>
>>>>>> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
>>>>>>> Dan,
>>>>>>>
>>>>>>> On 1/22/19 11:44 PM, Dan Murphy wrote:
>>>>>>>> Jacek
>>>>>>>>
>>>>>>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>>>>>>>> Hi all,
>>>>>>>>>
>>>>>>>>> On 1/20/19 7:42 AM, Vesa J??skel?inen wrote:
>>>>>>>>>> Hi Dan,
>>>>>>>>>>
>>>>>>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>>>>>>>> Jacek
>>>>>>>>>>>
>>>>>>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>>>>>>>> Jacek
>>>>>>>>>>>>
>>>>>>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>>>>>>>> Hi Dan,
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>>>>>>>> Hello
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>>>>
> ...
>
>>>> If this is OK I can post the patch with this update.
>>>>
>>>> But I would rather put the file creation in a class and have the colors directory.
>>>
>>> Yes, please post your work when it is ready.
>>
>> OK. I will derive the class and try to post it by the EOW.
>
> You can do that, but if you post the description of kernel<->user
> interface, first, you may save yourself a bit of coding...
>
OK I will put together the interface doc first and push a RFC.
Then put some code together
Dan
> Thanks,
> Pavel
>
--
------------------
Dan Murphy
Dan,
On 1/29/19 9:26 PM, Dan Murphy wrote:
> Jacek
>
> On 1/29/19 2:19 PM, Jacek Anaszewski wrote:
>> Hi Dan,
>>
>> On 1/29/19 2:56 PM, Dan Murphy wrote:
>>> Jacek
>>>
>>> On 1/24/19 3:55 PM, Jacek Anaszewski wrote:
>>>> Dan
>>>>
>>>> On 1/24/19 10:00 PM, Dan Murphy wrote:
>>>>> Jacek
>>>>>
>>>>> On 1/23/19 3:52 PM, Jacek Anaszewski wrote:
>>>>>> Dan,
>>>>>>
>>>>>> On 1/22/19 11:44 PM, Dan Murphy wrote:
>>>>>>> Jacek
>>>>>>>
>>>>>>> On 1/22/19 3:39 PM, Jacek Anaszewski wrote:
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> On 1/20/19 7:42 AM, Vesa Jääskeläinen wrote:
>>>>>>>>> Hi Dan,
>>>>>>>>>
>>>>>>>>> On 18/01/2019 15.58, Dan Murphy wrote:
>>>>>>>>>> Jacek
>>>>>>>>>>
>>>>>>>>>> On 1/18/19 7:45 AM, Dan Murphy wrote:
>>>>>>>>>>> Jacek
>>>>>>>>>>>
>>>>>>>>>>> On 1/17/19 3:10 PM, Jacek Anaszewski wrote:
>>>>>>>>>>>> Hi Dan,
>>>>>>>>>>>>
>>>>>>>>>>>> On 1/16/19 7:41 PM, Dan Murphy wrote:
>>>>>>>>>>>>> Hello
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 1/16/19 4:55 AM, Pavel Machek wrote:
>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> On 1/15/19 4:22 PM, Pavel Machek wrote:
>>>>>>>>>>>>>>>> Hi!
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> +The 24-bit RGB value passed in follows the pattern 0xXXRRGGBB
>>>>>>>>>>>>>>>>>> +XX - Do not care ignored by the driver
>>>>>>>>>>>>>>>>>> +RR - is the 8 bit Red LED value
>>>>>>>>>>>>>>>>>> +GG - is the 8 bit Green LED value
>>>>>>>>>>>>>>>>>> +BB - is the 8 bit Blue LED value
>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>> +Example:
>>>>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be a yellow color:
>>>>>>>>>>>>>>>>>> +echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color
>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>> +LED module output 4 of the LP5024 will be dimmed 50%:
>>>>>>>>>>>>>>>>>> +echo 0x80 > /sys/class/leds/lp5024\:led4_mod/brightness
>>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>>> +LED banked RGBs of the LP5036 will be a white color:
>>>>>>>>>>>>>>>>>> +echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> This part with example cans remain in Documentation/leds if you
>>>>>>>>>>>>>>>>>> like.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Does it actually work like that on hardware?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> What?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> If you do echo 0xffffff > /sys/class/leds/lp5036\:led_banked/color,
>>>>>>>>>>>>>> does it actually produce white? With all the different RGB modules
>>>>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> If you do echo 0xe6de00 > /sys/class/leds/lp5024\:led4_mod/color, does
>>>>>>>>>>>>>> it actually produce yellow, with all the different RGB modules
>>>>>>>>>>>>>> manufacturers can use with lp5024P?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> I believe the answer to the general questions is no for any RGB cluster and driver out there.
>>>>>>>>>>>>> Because if you set the same values on each and every RGB device out there you will get varying shades of the color.
>>>>>>>>>>>>> But for this device yes the color does appear to be yellow to me versus what was displayed on my monitor by the HSL picker.
>>>>>>>>>>>>> But everyone interprets colors differently.
>>>>>>>>>>>>>
>>>>>>>>>>>>> If you write the same value for yellow or white on a droid 4 and the N900 do they produce the same color side by side?
>>>>>>>>>>>>> Most probably not.
>>>>>>>>>>>>>
>>>>>>>>>>>>> As you pointed out the PWM needs to be modified to obtain the correct white color to account for LED and other device constraints.
>>>>>>>>>>>>>
>>>>>>>>>>>>> But we need to take into account the light pipe. Pools nowadays have RGB LED spot lights in them. It can
>>>>>>>>>>>>> be set to white. On my pool right off the lens the color has a purplish hue to it. As the light is diffracted into
>>>>>>>>>>>>> the pool the color becomes white. The pool is clear. When I add chemicals to the pool and make it cloudy
>>>>>>>>>>>>> and turn on the lights the color off the lens is now white. This is an example on a large scale but the issue
>>>>>>>>>>>>> scales down to the hand helds and smart home applications.
>>>>>>>>>>>>>
>>>>>>>>>>>>> If the cluster is piped through a flexible optic 0xffffff may produce the "white" you want on its output.
>>>>>>>>>>>>>
>>>>>>>>>>>>> So an expectation of certain color without proper piping based on a single RGB value may be a little unreasonable.
>>>>>>>>>>>>> There may need to be a way to attenuate the values based on the hardware aspect of the equation ie light pipe (or lack thereof) and LED vendor.
>>>>>>>>>>>>> So if we write 0xffffff to the RGB driver the driver could adjust the intensity of the individual LEDs based on the diffraction
>>>>>>>>>>>>> coefficients.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I also think that is an unreasonable expectation here that writing a single value to any LED RGB driver would produce
>>>>>>>>>>>>> a "rest of the world" absolute color. Maybe it can produce something similar but not identical.
>>>>>>>>>>>>> As you indicated in the requirements there is more involved here then just the LED and the values written.
>>>>>>>>>>>>> The colors should be close but may not be identical.
>>>>>>>>>>>>>
>>>>>>>>>>>>> A 10 year old N900 should not be considered the gold standard for color production due to advancements in LED,
>>>>>>>>>>>>> light pipe and LED driver technology.
>>>>>>>>>>>>> The single package RGB clusters on the board I am testing is about the size of a single RGB LED from 10 years ago.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I agree that the interface developed should work on the device but the algorithm derived to obtain the color needs to have
>>>>>>>>>>>>> a hardware aspect to the calculation.
>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Is it supposed to support "normal" RGB colors as seen on monitors?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Monitors are not an application for this part.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> You did not answer the question. When you talk about yellow, is it
>>>>>>>>>>>>>> same yellow the rest of world talks about?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> See above. It is close to what was on my monitor displayed.
>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Because 100% PWM on all channels does not result in white on hardware
>>>>>>>>>>>>>>>> I have.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I don't know I am usually blinded by the light and have no diffuser over
>>>>>>>>>>>>>>> the LEDs to disperse the light so when I look I see all 3 colors.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> How can we have useful discussion about colors when you don't see the
>>>>>>>>>>>>>> colors?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Place a piece of paper over the LEDs....
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Good suggestion for a rough test.
>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> But...
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I believe we should have a reasonable design before we do something
>>>>>>>>>>>>>>>> like this. There's no guarantee someone will not use lp50xx with just
>>>>>>>>>>>>>>>> the white LEDs for example. How will this work? Plus existing hardware
>>>>>>>>>>>>>>>> already uses three separate LEDs for RGB LED. Why not provide same
>>>>>>>>>>>>>>>> interface?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Which existing hardware? Are they using this part?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Nokia N900. They are not using this part, but any interface we invent
>>>>>>>>>>>>>> should work there, too.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Yes a common interface would be nice with some sort of hardware tuning coefficient.
>>>>>>>>>>>>>
>>>>>>>>>>>>>>> <rant>
>>>>>>>>>>>>>>> Why are we delaying getting the RGB framework or HSV in?
>>>>>>>>>>>>>>> I would rather design against something you want instead of having
>>>>>>>>>>>>>>> everyone complain about every implementation I post.
>>>>>>>>>>>>>>> </rant>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Because you insist on creating new kernel interfaces, when existing
>>>>>>>>>>>>>> interfaces work, and are doing that badly.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Because your patches are of lower quality than is acceptable for linux
>>>>>>>>>>>>>> kernel.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Because you don't seem to be reading the emails.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I sent list of requirements for RGB led support. This does not meet
>>>>>>>>>>>>>> them.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Sigh. You did not answer my question.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Your requirements seem to be centered around monitors but that is only one application of the current
>>>>>>>>>>>>> RGB LED landscape.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I am willing to work with you on the HSV and adapting the LP50xx part to this framework.
>>>>>>>>>>>>> Or any RGB framework for that matter. I still don't agree with the kernel needing to declare colors
>>>>>>>>>>>>> maybe color capabilities but not specific colors.
>>>>>>>>>>>>
>>>>>>>>>>>> Dan, if you have a bandwidth for LED RGB class implementation
>>>>>>>>>>>> then please go ahead. It would be good to compare colors produced
>>>>>>>>>>>> by software HSV->RGB algorithm to what can be achieved with
>>>>>>>>>>>> LEDn_BRIGHTNESS feature.
>>>>>>>>>>>>
>>>>>>>>>>>> The requirements for LED RGB class as I would see it:
>>>>>>>>>>>>
>>>>>>>>>>>> sysfs interface:
>>>>>>>>>>>>
>>>>>>>>>>>> brightness-model: space separated list of available options:
>>>>>>>>>>>> - rgb (default):
>>>>>>>>>>>> - creates color file with "red green blue" decimal values
>>>>>>>>>>>
>>>>>>>>>>> What about other colored LEDs? Presenting RGB for an Amber LED does not seem right.
>>>>>>>>>>> Should the LED color come from the DT?
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> I thought about this, other non-RGB LEDs would not use the RGB framework.
>>>>>>>>>> But should they have the same interfaces as RGB?
>>>>>>>>>>
>>>>>>>>>> Should PWM control be a global interface?
>>>>>>>>>
>>>>>>>>> In order to being able to set multi color element led at one go I would recommend using then model:
>>>>>>>>>
>>>>>>>>> color_names: "red green blue white"
>>>>>>>>>
>>>>>>>>> echo "32 43 0 128" > color
>>>>>>>>>
>>>>>>>>> This way all elements would be set at same time from user space point of view.
>>>>>>>>>
>>>>>>>>> This of course requires that it is part of the physical/logical led that is being controlled. If it is a separate thing then it would logically be differently controlled mono color led.
>>>>>>>>>
>>>>>>>>> If you look what kinds of leds are available lets say from digikey you get all kinds of combos:
>>>>>>>>>
>>>>>>>>> - red, green, blue
>>>>>>>>> - red, green, blue, amber
>>>>>>>>> - red, green, blue, white
>>>>>>>>> - red, green, blue, white - cool
>>>>>>>>> - red, green, blue, white - neutral
>>>>>>>>> - red, green, blue, white - warm
>>>>>>>>> - red, orange
>>>>>>>>> - purple, ultraviolet
>>>>>>>>> - amber, blue
>>>>>>>>> - amber, blue, cyan, green, red, violet, white - cool
>>>>>>>>> - amber, blue, green
>>>>>>>>> - amber, green, blue
>>>>>>>>> - and then lots of single special colors
>>>>>>>>
>>>>>>>> It suggested me another solution. Instead of LED RGB class
>>>>>>>> we would have LED multi-color class.
>>>>>>>>
>>>>>>>
>>>>>>> I was thinking the same thing this morning. But I was thinking that the RGB
>>>>>>> class should be an additional class to stand on its own or can register to the
>>>>>>> multi color class.
>>>>>>>
>>>>>>>> Sysfs interface design:
>>>>>>>> -----------------------
>>>>>>>>
>>>>>>>> colors: directory containing files that map to
>>>>>>>> the brightness of particular LEDs; there
>>>>>>>> would be predefined color names that LED class
>>>>>>>> driver should map iouts to, e.g.:
>>>>>>>
>>>>>>> Filling in the missing ideas with questions.
>>>>>>>
>>>>>>> Is it a directory or a file? If it is a directory does that not break the current
>>>>>>> directory label model?
>>>>>>>
>>>>>>> so the path would be /sys/class/leds/colors ? (It is probably not this but needs clarification)
>>>>>>> How would this look if I had 2 of the same color LEDs? The Beagle bone black has 2 Blue LEDs.
>>>>>>> They are assigned to different triggers and have different directories. Both are GPIO controlled.
>>>>>>>
>>>>>>> Or are you saying it would be something like (More then likely this is what you intended)
>>>>>>> /sys/class/leds/input4::numlock/colors?
>>>>>>
>>>>>> Yes, this is what I meant.
>>>>>>
>>>>>
>>>>> OK. Thanks for the clarification
>>>>>
>>>>>>> Maybe it is mandated that "multi" be added to the label when the class is registered so the caller
>>>>>>> knows that this is a multi color class and not a single LED color class.
>>>>>>
>>>>>> Like I am going to come up with standardized color names
>>>>>> in my LED naming related patch, the multi-color names
>>>>>> can be defined as well, e.g.: rgb, rgbw, rgbwa, rgbwauv etc.
>>>>>>
>>>>>
>>>>> That may be better it is descriptive off the command line.
>>>>>
>>>>>>> What about providing a file called colors_raw which takes in the raw decimal values to obtain other color
>>>>>>> variants when RGB is only available? And this can also present a single write to the kernel with the new
>>>>>>> color values.
>>>>>>
>>>>>> My design already covers that in the form of files in the colors
>>>>>> directory. Like I stated: "files that map to the brightness of
>>>>>> particular LEDs". Single write is secured by "echo "write" > sync.
>>>>>>
>>>>>
>>>>> OK. So set the new values and then tell the set the sync which will make the device driver write the
>>>>> device.
>>>>>
>>>>> Sounds good. how about echo 1 > sync and we can stay away from a long string conversion
>>>>
>>>> We need also to be able to do a readout.
>>>>
>>>> If we changed "sync" to "rw" then we could come up with intuitive
>>>> semantics:
>>>>
>>>> echo 1 > rw // write
>>>> echo 0 > rw // read
>>>>
>>>> rw file would have WO permission.
>>>
>>> I have re-written the lp50xx driver to show red, green, blue, sync and sync_enable files for each registered LED.
>>
>> Did you change your mind regarding LED multi color class implementation?
>>
>
> No. I just did not want to put effort into the class if the interfaces were not agreed upon.
> So if we are good with the interfaces I can start the MC class.
I'm good with that. It would be nice to see some input from the
other people.
>>> I added the sync_enable file so that the there can be real time control of the individual LEDs as well.
>>
>> Yes, it's a good idea.
>>
>>> Turning on sync means that the user will write to one of the color files and the setting won't take affect until
>>> sync is written.
>>>
>>> If sync is off then the LED register is updated immediately.
>>>
>>> Being able to turn on and off syncing maybe better. A developer may choose to set up the color and then sync
>>> or they may want to ramp a specific color. This will help reduce user space writes but also reduce the number
>>> of peripheral writes when color values do not change.
>>>
>>> I am having difficulty in creating the colors directory in the device driver.
>>> This appears to need to be done in the class when the class pointer is available.
>>
>> Not necessarily, you need only dev->kobj. Please follow the implementation of drivers/usb/core/ledtrig-usbport.c. However I would
>> really prefer if it became a part of new LED multi color class.
>>
>
> It will. I should be able to create the colors directory there as well.
> I need to figure out how to cleanly tell the MC class what LEDs are available.
Of course the solution from ledtrig-usbport.c is equally good for the
class.
Related to the LED color identifications in the multi color class -
we'd need some defines in e.g. include/dt-bindings/leds/colors.h:
#define LED_COLOR_RED 0
#define LED_COLOR_GREEN 1
#define LED_COLOR_BLUE 2
Then, in the device tree we could have:
led-controller@8 {
...
led@0 {
multi-color = <LED_COLOR_RED
LED_COLOR_GREEN
LED_COLOR_BLUE>;
reg = <0x0>; // in case of lp5024 this would identify
// RGB LED module;
};
};
For pwm LEDs we would need a bit different approach, so I'd not
strive to create generic bindings for LED multi color class.
We need generic interface only for LED multi color class registration.
e.g.:
struct led_classdev_multicolor {
/* led class device */
struct led_classdev led_cdev; // for legacy brightness support
struct led_classdev *colors; // dynamically allocated array
void (*multicolor_set) (struct led_classdev_multicolor *led_mcdev);
void (*unicolor_set) (struct led_classdev *led_cdev,
enum led_brightness); // [color]_store ssyfs
// callback will call it
};
led_classdev_multicolor_register(struct device *parent,
struct led_classdev_multicolor *led_mcdev)
...
>>>>>>> I am not a fan of hard coding preset colors as you can see there are to many of them and variations of the color.
>>>>>>> In addition this severely limits the ability of the user. Unless we stick to primary colors only and not secondary
>>>>>>> colors.
>>>>>>> Defining and hard coding hte colors can get out of control and not maintainable moving forward. Especially
>>>>>>> if we start adding defines like white_warm, white_neutral and other variations to the color.
>>>>>>
>>>>>> We would not limit anything. Every color combination can be achieved
>>>>>> by following this exemplary sequence:
>>>>>>
>>>>>> $ echo 154 > colors/red
>>>>>> $ echo 232 > colors/green
>>>>>> $ echo 43 > colors/blue
>>>>>> # echo "write" > sync //only this changes hardware state
>>>>>>
>>>
>>> The code works more like this
>>> $ :/sys/class/leds/lp5024:led1_mod# ls
>>> blue device max_brightness red sync trigger
>>> brightness green power subsystem sync_enable uevent
>>>
>>> $ cat sync_enable
>>> enabled // I can change this to return an int instead
>>> $ echo 154 > red
>>> $ echo 232 > green
>>> $ echo 43 > blue
>>> $ echo 1 > sync //this changes hardware state
>>>
>>> $ echo 0 > sync_enable
>>> $ cat sync_enable
>>> disabled
>>> $ echo 154 > red // changes red LED immediately
>>> $ echo 232 > green // changes green LED immediately
>>> $ echo 43 > blue // changes blue LED immediately
>>> $ echo 1 > sync // Has no affect on the hardware
>>>
>>> If this is OK I can post the patch with this update.
>>>
>>> But I would rather put the file creation in a class and have the colors directory.
>>
>> Yes, please post your work when it is ready.
>
> OK. I will derive the class and try to post it by the EOW.
>
>>
>>>>>> brightness-model is provided only to define mapping of legacy brightness
>>>>>> levels (governed by brightness file and led_set_brightness() API) to
>>>>>> the specific combination of colors.
>>>>>>
>>>>>> For instance we can define three brightness levels for green hue:
>>>>>>
>>>>>> DT definition for it would look like below:
>>>>>>
>>>>>> rgb-green = <0x277c33 0x37b048 0x47e45d>;
>>>>>>
>>>>>> LED multi color class would then do the following mapping for
>>>>>> each of the three brightness levels for rgb-green brightness model:
>>>>>>
>>>>>> $ echo rgb-green > brightness_model
>>>>>> $ echo 1 > brightness // red=0x27, green=0x7c, blue=0x33
>>>>>> $ echo 2 > brightness // red=0x37, green=0xb0, blue=0x48
>>>>>> $ echo 3 > brightness // red=0x47, green=0xe4, blue=0x5d
>>>>>>
>>>>>
>>>>> OK I would have to play with this on the LP devices.
>>>
>>> I have not done anything with this.
>>>
>
> I will omit this until we figure out how to nicely present this to user space from the MC class.
Could you share what particularly is your concern?
> Or maybe it is something you can add once we have the class ready.
OK. But for the cases when neither LEDn_BRIGHTNESS feature nor
any DT color ranges are provided please do provide one brightness
model "onoff", that for brightness==1 will set brightness of all colors
to max, and turn them off on brightness==0.
>>>>>>> What about IR LEDs used for night vision products? Do these fall into the multi color class?
>>>>>>> We do have a driver I submitted that had an IR LED and a White LED combined. It was created against the
>>>>>>> flash class but it could be a multi color LED as well.
>>>>>>>
>>>>>>> How would traversing through the full color palette work if you were to want to produce a multi
>>>>>>> color ring like the LP50xx where the pattern can traverse from one end of the color spectrum and back?
>>>>>>> Or in a product like the gaming keyboards that will change color or change backlight brightness?
>>>>>>
>>>>>> This is not meant as a solution for pattern generator but for
>>>>>> consolidated source of multi color light. In the simplest case
>>>>>> RGB LED elements like those used for lp5024 reference board,
>>>>>> but it could be RGBWAUV LED [0] as well.
>>>>>>
>>>>>> For patterns traversing many LEDs I see a trigger as the best solution.
>>>>>> Hmm, now I see that trigger mechanism actually can serve as very
>>>>>> flexible pattern generator.
>>>>>>
>>>>>> We would need a device that could be configured to register
>>>>>> a number of multi-led-patternN triggers, one per LED, and generate
>>>>>> events for each trigger in a loop.
>>>>>>
>>>>>> The device would have to allow for configuring pattern intervals
>>>>>> via sysfs, like in case of current pattern trigger.
>>>>>>
>>>>>> LED class devices would have to register for its events:
>>>>>>
>>>>>> $/sys/class/leds/led1 echo multi-led-pattern1 > trigger
>>>>>> $/sys/class/leds/led2 echo multi-led-pattern2 > trigger
>>>>>> $/sys/class/leds/led3 echo multi-led-pattern3 > trigger
>>>>>>
>>>>>
>>>>> A bit off topic but I like the idea. We should save this for another day
>>>>
>>>> Yes, that's another story.
>>>>
>>>>>> The ability to define brightness models in DT would
>>>>>> add even more flexibility.
>>>>>>
>>>>>
>>>>> brightness models would be mandatory to support in the driver but an optional
>>>>> DT entry.
>>>>>
>>>>> Is that a correct assumption?
>>>>
>>>> Correct.
>>>>
>>>>>>> Not sure what color LEDs the keyboard manufacturers place on their keyboards but does the interface design
>>>>>>> capable of doing this?
>>>>>>>
>>>>>>> https://www.youtube.com/watch?v=pfKv3g2FeBE
>>>>>>> or something like this
>>>>>>>
>>>>>>> https://www.youtube.com/watch?v=PO3auX3f5C4
>>>>>>>
>>>>>>> The LP5036 has this capability.
>>>>>>>
>>>>>>>> - red
>>>>>>>> - green
>>>>>>>> - blue
>>>>>>>> - white
>>>>>>>> - sync: accepts "write" and "read", which executes
>>>>>>>> write/readout to/from a device respectively.
>>>>>>>>
>>>>>>>
>>>>>>> What are these above, the values or the files under the colors directory?
>>>>>>
>>>>>> They are just color specific counterparts of monochrome brightness.
>>>>>> In terms of lp50xx they would map to OUTn_COLOR registers.
>>>>>>
>>>>>>> I am assuming they are files.
>>>>>>
>>>>>> Right.
>>>>>>
>>>>>>> Are they mandatory or optional?
>>>>>>
>>>>>> Mandatory, one per each iout to control.
>>>>>>
>>>>>
>>>>> OK And all the LEDs within this directory would be considered a LED cluster?
>>>>>
>>>>> And if there are 2 like colors of the LED defined in the same cluster would we just see a single
>>>>> file and write a common value to that file and the driver would have to update each
>>>>> red LED within that cluster. No independent control of like colored LEDs within the
>>>>> registered LED cluster.
>>>>>
>>>>> If the developer wants this level of control they would have to register two separate classes
>>>>>
>>>>> Correct?
>>>>
>>>> I would abide by one color to one iout mapping. Registering more LEDs
>>>> under the same color feels more of a task for trigger.
>>>>
>>>>>>>> brightness-model: defines brightness level to color configuration
>>>>>>>> mapping
>>>>>>>> - "hardware": for devices with feature like LEDn_BRIGHTNESS of lp50xx
>>>>>>>> - "rgb-<hue>": available only when all three red,green,blue colors
>>>>>>>> are present in the colors directory.
>>>>>>>> <hue> is a placeholder for given DT hue presets.
>>>>>>>> - "rgbw-<hue>": Same as above, but available only when white color
>>>>>>>> (any of amber or white-{cool|neutral|warm} can be
>>>>>>>> mapped to white) is also available. In this mode
>>>>>>>> max_brightness equals num-of-hue-presets + 1, and
>>>>>>>> max_brightness, when set, turns the "white" LED on
>>>>>>>
>>>>>>> Why do we need white combined here? Should this not be its own entity?
>>>>>>
>>>>>> To be able to set white color. We're still talking about one LED
>>>>>> element (although they can be be physically few LEDs in one case).
>>>>>> This is brightness file, so we've got to stick to the semantics.
>>>>>> Max brightness level should be the brightest. With RGBW LEDs we
>>>>>> fortunately have a means to achieve pure white, that's why
>>>>>> rgbw-<hue> would be beneficial. If you increase L component of
>>>>>> HSL color space, the max value gives white for all hues.
>>>>>> So maybe this brightness-model would be rather called hsl-<hue>.
>>>>>>
>>>>>> For RGBW LEDs, we would have to allow for more shades of white too,
>>>>>> like in [1].
>>>>>>
>>>>>
>>>>> Yep.
>>>>
>>>> But this all would be left to the DT designer decision.
>>>>
>>>>>>> Again I don't like limiting the color palette from the DT. I think that the
>>>>>>> user space can see what colors are available for that device and makes its own
>>>>>>> decision on what color to present.
>>>>>>>
>>>>>>> For the RGBw what about RGB amber and RGB purple. Are the white LEDs always part of the
>>>>>>> same function trying to be achieved by the system designer? The RGB can be used to denote
>>>>>>> notification status and the white can be used to denote that a charger is connected. Motorola
>>>>>>> Droid did this.
>>>>>>
>>>>>> I hope I've just clarified my idea.
>>>>>>
>>>>>
>>>>> Its getting clearer. I would like to see it in code and play with it not as a user
>>>>> but as a developer. Make sure the paper model works as well as the real implementation.
>>>>>
>>>>> Is this model clear to the developer?
>>>>> How would a developer define what values are appropriate for the brightness-model?
>>>>
>>>> We could create guidelines e.g. that for hsl-<hue> pattern, the
>>>> colors corresponding to brightness levels should be arranged so
>>>> that increasing brightness felt like increasing value of
>>>> L component of HSL.
>>>>
>>>> But we wouldn't be able to enforce adherence to a particular scheme.
>>>>
>>>>> Does the driver have to become overly complex to support simple color generation?
>>>>
>>>> Not at all. Caching the colors written to the files in colors directory
>>>> would be responsibility of LED multi-color class. On echo 1 > sync
>>>> the core would call a new op e.g.
>>>>
>>>> color_set(struct led_classdev_multicolor *mcled_cdev)
>>>>
>>>> Driver would read in it colors cached in struct led_classdev_multicolor
>>>> and write them to the hardware.
>>>>
>>>>> Thoughts on putting code to idea?
>>>>>
>>>>>
>>>>>>>
>>>>>>>> - "rgb-linear": I'm not sure if it should be available - it will
>>>>>>>> have unpredictable results
>>>>>>>>
>>>>>>>> brightness: sets/reads brightness in the way specific to the
>>>>>>>> current brightness-model. When more colors are available
>>>>>>>> (e.g. amber, blue, cyan, green, red, violet, white), they
>>>>>>>> are not touched by write to brightness).
>>>>>>>>
>>>>>>>> HSV->RGB conversion is left entirely to the userspace, which can set any
>>>>>>>> color with use of the proposed interface.
>>>>>>>>
>>>>>>>> Let's agree on sysfs interface first, and only after that move
>>>>>>>> to the DT details.
>>>>>>>>
>>>>>>>
>>>>>>> DT's are meant to describe hardware and not describe the product. Unless Rob does not see
>>>>>>> an issue with defining product capabilities in the DT then we should keep that out of the DT.
>>>>>>
>>>>>> LED element is a device. I see nothing irrelevant for DT in describing the lighting specificity of a device mounted on the board. Please keep
>>>>>> in mind that it will not limit the number of colors available to set.
>>>>>> It will only allow to define mapping of brightness level to color.
>>>>>> We need that for current trigger mechanism to work with LED multi-color
>>>>>> class.
>>>>>>
>>>>>
>>>>> I see this now.
>>>>>
>>>>> Dan
>>>>>
>>>>>> [0] http://www.cobledarray.com/sale-4942931-10w-rgbwauv-led-diode-6-in-1-high-power-multicolor-led-chip.html
>>>>>> [1] https://www.youtube.com/watch?v=NzlFmTqOh9M
>>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>
>
--
Best regards,
Jacek Anaszewski