linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] leds: add support for apa102c leds
@ 2020-02-18  9:37 Nicolas Belin
  2020-02-18  9:37 ` [PATCH 1/3] dt-bindings: Document shiji vendor-prefix Nicolas Belin
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Nicolas Belin @ 2020-02-18  9:37 UTC (permalink / raw)
  To: linux-kernel, linux-leds, jacek.anaszewski, pavel, dmurphy; +Cc: Nicolas Belin

This patch series adds the driver and its related documentation 
for the APA102C RGB Leds.

Patch 1 adds the APA102C led manufacturer to the vendor-prefixes list.

Patch 2 Documents the APA102C led driver.

Patch 3 contains the actual driver code and modifications in the Kconfig 
and the Makefile.

Nicolas Belin (3):
  dt-bindings: Document shiji vendor-prefix
  dt-bindings: leds: Shiji Lighting APA102C LED driver
  drivers: leds: add support for apa102c leds

 .../devicetree/bindings/leds/leds-apa102c.yaml     |  91 +++++++
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 drivers/leds/Kconfig                               |  11 +
 drivers/leds/Makefile                              |   1 +
 drivers/leds/leds-apa102c.c                        | 268 +++++++++++++++++++++
 5 files changed, 373 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-apa102c.yaml
 create mode 100644 drivers/leds/leds-apa102c.c

-- 
2.7.4


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] dt-bindings: Document shiji vendor-prefix
  2020-02-18  9:37 [PATCH 0/3] leds: add support for apa102c leds Nicolas Belin
@ 2020-02-18  9:37 ` Nicolas Belin
  2020-02-18 12:40   ` Dan Murphy
  2020-02-18  9:37 ` [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver Nicolas Belin
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Nicolas Belin @ 2020-02-18  9:37 UTC (permalink / raw)
  To: linux-kernel, linux-leds, jacek.anaszewski, pavel, dmurphy; +Cc: Nicolas Belin

Shenzhen Shiji Lighting Co.,Ltd is a LED manufacturer.

Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 9e67944bec9c..a463286c3960 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -863,6 +863,8 @@ patternProperties:
     description: SGX Sensortech
   "^sharp,.*":
     description: Sharp Corporation
+  "^shiji,.*":
+    description: Shenzhen Shiji Lighting Co.,Ltd
   "^shimafuji,.*":
     description: Shimafuji Electric, Inc.
   "^si-en,.*":
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver
  2020-02-18  9:37 [PATCH 0/3] leds: add support for apa102c leds Nicolas Belin
  2020-02-18  9:37 ` [PATCH 1/3] dt-bindings: Document shiji vendor-prefix Nicolas Belin
@ 2020-02-18  9:37 ` Nicolas Belin
  2020-02-18 20:28   ` Jacek Anaszewski
  2020-02-20 10:30   ` Geert Uytterhoeven
  2020-02-18  9:37 ` [PATCH 3/3] drivers: leds: add support for apa102c leds Nicolas Belin
  2020-02-18 12:43 ` [PATCH 0/3] " Dan Murphy
  3 siblings, 2 replies; 14+ messages in thread
From: Nicolas Belin @ 2020-02-18  9:37 UTC (permalink / raw)
  To: linux-kernel, linux-leds, jacek.anaszewski, pavel, dmurphy; +Cc: Nicolas Belin

Document Shiji Lighting APA102C LED driver device tree bindings.

Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
---
 .../devicetree/bindings/leds/leds-apa102c.yaml     | 91 ++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-apa102c.yaml

diff --git a/Documentation/devicetree/bindings/leds/leds-apa102c.yaml b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
new file mode 100644
index 000000000000..24bc2fc19fcb
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/leds-apa102c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LED driver for Shiji Lighting - APA102C
+
+maintainers:
+  - Nicolas Belin <nbelin@baylibre.com>
+
+description:
+  Each LED is represented as a sub-node of the leds-apa102c device.  Each LED
+  is a three color RGB LED with 32 levels brightness adjustment that can be
+  cascaded so that multiple LEDs can be set with a single command.
+
+properties:
+  compatible:
+    const: shiji,apa102c
+
+  reg:
+    maxItems: 1
+
+  spi-max-frequency:
+    maximum: 1000000
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - spi-max-frequency
+  - '#address-cells'
+  - '#size-cells'
+
+patternProperties:
+  "^led@[0-9]+$":
+    type: object
+    description: |
+      Properties for an array of connected LEDs.
+
+    properties:
+      reg:
+        description: |
+          This property corresponds to the led index. It has to be between 0
+          and the number of managed leds minus 1
+        maxItems: 1
+
+      label:
+        description: |
+          This property corresponds to the name of the led. If not set,
+          the led index will be used to create the led name instead
+        maxItems: 1
+
+      linux,default-trigger: true
+
+    required:
+      - reg
+
+examples:
+  - |
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        led-controller@0 {
+            compatible = "shiji,apa102c";
+            reg = <0>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+            spi-max-frequency = <1000000>;
+            led@0 {
+                reg = <0>;
+                label = "led1";
+            };
+
+            led@1 {
+                reg = <1>;
+                label = "led2";
+            };
+
+            led@2 {
+                reg = <2>;
+                label = "led3";
+            };
+        };
+    };
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] drivers: leds: add support for apa102c leds
  2020-02-18  9:37 [PATCH 0/3] leds: add support for apa102c leds Nicolas Belin
  2020-02-18  9:37 ` [PATCH 1/3] dt-bindings: Document shiji vendor-prefix Nicolas Belin
  2020-02-18  9:37 ` [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver Nicolas Belin
@ 2020-02-18  9:37 ` Nicolas Belin
  2020-02-18 21:13   ` Jacek Anaszewski
  2020-02-18 12:43 ` [PATCH 0/3] " Dan Murphy
  3 siblings, 1 reply; 14+ messages in thread
From: Nicolas Belin @ 2020-02-18  9:37 UTC (permalink / raw)
  To: linux-kernel, linux-leds, jacek.anaszewski, pavel, dmurphy; +Cc: Nicolas Belin

Initilial commit in order to support the apa102c RGB leds.

Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
---
 drivers/leds/Kconfig        |  11 ++
 drivers/leds/Makefile       |   1 +
 drivers/leds/leds-apa102c.c | 268 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+)
 create mode 100644 drivers/leds/leds-apa102c.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index d82f1dea3711..4fafeaaf6ee8 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -69,6 +69,17 @@ config LEDS_AN30259A
 	  To compile this driver as a module, choose M here: the module
 	  will be called leds-an30259a.
 
+config LEDS_APA102C
+	tristate "LED Support for Shiji APA102C"
+	depends on LEDS_CLASS
+	depends on SPI
+	help
+	  This option enables support for the Shiji Lighthing APA102C RGB full color
+	  LEDs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called leds-apa102c.
+
 config LEDS_APU
 	tristate "Front panel LED support for PC Engines APU/APU2/APU3 boards"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index d7e1107753fb..ab17f90347cb 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_TRIGGERS)		+= led-triggers.o
 # LED Platform Drivers
 obj-$(CONFIG_LEDS_88PM860X)		+= leds-88pm860x.o
 obj-$(CONFIG_LEDS_AAT1290)		+= leds-aat1290.o
+obj-$(CONFIG_LEDS_APA102C)		+= leds-apa102c.o
 obj-$(CONFIG_LEDS_APU)			+= leds-apu.o
 obj-$(CONFIG_LEDS_AS3645A)		+= leds-as3645a.o
 obj-$(CONFIG_LEDS_AN30259A)		+= leds-an30259a.o
diff --git a/drivers/leds/leds-apa102c.c b/drivers/leds/leds-apa102c.c
new file mode 100644
index 000000000000..e7abe3f5b7c2
--- /dev/null
+++ b/drivers/leds/leds-apa102c.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Nicolas Belin <nbelin@baylibre.com>
+ */
+
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <uapi/linux/uleds.h>
+
+/*
+ *  APA102C SPI protocol description:
+ *  +------+----------------------------------------+------+
+ *  |START |               DATA FIELD:              | END  |
+ *  |FRAME |               N LED FRAMES             |FRAME |
+ *  +------+------+------+------+------+-----+------+------+
+ *  | 0*32 | LED1 | LED2 | LED3 | LED4 | --- | LEDN | 1*32 |
+ *  +------+------+------+------+------+-----+------+------+
+ *
+ *  +-----------------------------------+
+ *  |START FRAME 32bits                 |
+ *  +--------+--------+--------+--------+
+ *  |00000000|00000000|00000000|00000000|
+ *  +--------+--------+--------+--------+
+ *
+ *  +------------------------------------+
+ *  |LED  FRAME 32bits                   |
+ *  +---+-----+--------+--------+--------+
+ *  |111|LUMA |  BLUE  | GREEN  |  RED   |
+ *  +---+-----+--------+--------+--------+
+ *  |3b |5bits| 8bits  | 8bits  | 8bits  |
+ *  +---+-----+--------+--------+--------+
+ *  |MSB   LSB|MSB  LSB|MSB  LSB|MSB  LSB|
+ *  +---+-----+--------+--------+--------+
+ *
+ *  +-----------------------------------+
+ *  |END FRAME 32bits                   |
+ *  +--------+--------+--------+--------+
+ *  |11111111|11111111|11111111|11111111|
+ *  +--------+--------+--------+--------+
+ */
+
+/* apa102c default settings */
+#define CR_MAX_BRIGHTNESS	GENMASK(7, 0)
+#define LM_MAX_BRIGHTNESS	GENMASK(4, 0)
+#define CH_NUM			4
+#define START_BYTE		0
+#define END_BYTE		GENMASK(7, 0)
+#define LED_FRAME_HEADER	GENMASK(7, 5)
+
+enum led_channels {
+	RED,
+	GREEN,
+	BLUE,
+	LUMA,
+};
+
+struct apa102c_led {
+	char			name[LED_MAX_NAME_SIZE];
+	struct apa102c		*priv;
+	struct led_classdev	ldev;
+	u8			brightness;
+};
+
+struct apa102c {
+	size_t			led_count;
+	struct device		*dev;
+	struct mutex		lock;
+	struct spi_device	*spi;
+	u8			*buf;
+	struct apa102c_led	leds[];
+};
+
+static int apa102c_sync(struct apa102c *priv)
+{
+	int	ret;
+	size_t	i;
+	size_t	bytes = 0;
+
+	for (i = 0; i < 4; i++)
+		priv->buf[bytes++] = START_BYTE;
+
+	for (i = 0; i < priv->led_count; i++) {
+		priv->buf[bytes++] = LED_FRAME_HEADER |
+				     priv->leds[i * CH_NUM + LUMA].brightness;
+		priv->buf[bytes++] = priv->leds[i * CH_NUM + BLUE].brightness;
+		priv->buf[bytes++] = priv->leds[i * CH_NUM + GREEN].brightness;
+		priv->buf[bytes++] = priv->leds[i * CH_NUM + RED].brightness;
+	}
+
+	for (i = 0; i < 4; i++)
+		priv->buf[bytes++] = END_BYTE;
+
+	ret = spi_write(priv->spi, priv->buf, bytes);
+
+	return ret;
+}
+
+static int apa102c_set_sync(struct led_classdev *ldev,
+			   enum led_brightness brightness)
+{
+	int			ret;
+	struct apa102c_led	*led = container_of(ldev,
+						    struct apa102c_led,
+						    ldev);
+
+	dev_dbg(led->priv->dev, "Set brightness of %s to %d\n",
+		led->name, brightness);
+
+	mutex_lock(&led->priv->lock);
+	led->brightness = (u8)brightness;
+	ret = apa102c_sync(led->priv);
+	mutex_unlock(&led->priv->lock);
+
+	return ret;
+}
+
+static int apa102c_probe_dt(struct apa102c *priv)
+{
+	u32			i = 0;
+	int			j = 0;
+	struct apa102c_led	*led;
+	struct fwnode_handle	*child;
+	struct device_node	*np;
+	int			ret;
+	int			use_index;
+	const char		*str;
+	static const char	* const rgb_name[] = {"red",
+						      "green",
+						      "blue",
+						      "luma"};
+
+	device_for_each_child_node(priv->dev, child) {
+		np = to_of_node(child);
+
+		ret = fwnode_property_read_u32(child, "reg", &i);
+		if (ret)
+			return ret;
+
+		if (i >= priv->led_count)
+			return -EINVAL;
+
+		/* use the index to create the name if the label is not set */
+		use_index = fwnode_property_read_string(child, "label", &str);
+
+		/* for each physical LED, 4 LEDs are created representing
+		 * the 4 components: red, green, blue and global luma.
+		 */
+		for (j = 0; j < CH_NUM; j++) {
+			led = &priv->leds[i * CH_NUM + j];
+
+			if (use_index)
+				snprintf(led->name, sizeof(led->name),
+					 "apa102c:%s:%d", rgb_name[j], i);
+			else
+				snprintf(led->name, sizeof(led->name),
+					 "apa102c:%s:%s", rgb_name[j], str);
+
+			fwnode_property_read_string(child,
+						    "linux,default-trigger",
+						    &led->ldev.default_trigger);
+
+			led->priv			 = priv;
+			led->ldev.name			 = led->name;
+			if (j == LUMA) {
+				led->ldev.brightness	 = led->brightness
+							 = LM_MAX_BRIGHTNESS;
+				led->ldev.max_brightness = LM_MAX_BRIGHTNESS;
+			} else {
+				led->ldev.brightness	 = led->brightness
+							 = 0;
+				led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
+			}
+
+			led->ldev.brightness_set_blocking = apa102c_set_sync;
+
+			ret = devm_led_classdev_register(priv->dev, &led->ldev);
+			if (ret) {
+				dev_err(priv->dev,
+					"failed to register LED %s, err %d",
+					led->name, ret);
+				fwnode_handle_put(child);
+				return ret;
+			}
+
+			led->ldev.dev->of_node = np;
+
+		}
+	}
+
+	return 0;
+}
+
+static int apa102c_probe(struct spi_device *spi)
+{
+	struct apa102c	*priv;
+	size_t		led_count;
+	int		ret;
+
+	led_count = device_get_child_node_count(&spi->dev);
+	if (!led_count) {
+		dev_err(&spi->dev, "No LEDs defined in device tree!");
+		return -ENODEV;
+	}
+
+	priv = devm_kzalloc(&spi->dev,
+			    struct_size(priv, leds, led_count * CH_NUM),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->buf = devm_kzalloc(&spi->dev, led_count * CH_NUM + 8, GFP_KERNEL);
+	if (!priv->buf)
+		return -ENOMEM;
+
+	mutex_init(&priv->lock);
+	priv->led_count	= led_count;
+	priv->dev	= &spi->dev;
+	priv->spi	= spi;
+
+	ret = apa102c_probe_dt(priv);
+	if (ret)
+		return ret;
+
+	/* Set the LEDs with default values at start */
+	apa102c_sync(priv);
+	if (ret)
+		return ret;
+
+	spi_set_drvdata(spi, priv);
+
+	return 0;
+}
+
+static int apa102c_remove(struct spi_device *spi)
+{
+	struct apa102c *priv = spi_get_drvdata(spi);
+
+	mutex_destroy(&priv->lock);
+
+	return 0;
+}
+
+static const struct of_device_id apa102c_dt_ids[] = {
+	{ .compatible = "shiji,apa102c", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, apa102c_dt_ids);
+
+static struct spi_driver apa102c_driver = {
+	.probe		= apa102c_probe,
+	.remove		= apa102c_remove,
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.of_match_table	= apa102c_dt_ids,
+	},
+};
+
+module_spi_driver(apa102c_driver);
+
+MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>");
+MODULE_DESCRIPTION("apa102c LED driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:apa102c");
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] dt-bindings: Document shiji vendor-prefix
  2020-02-18  9:37 ` [PATCH 1/3] dt-bindings: Document shiji vendor-prefix Nicolas Belin
@ 2020-02-18 12:40   ` Dan Murphy
  0 siblings, 0 replies; 14+ messages in thread
From: Dan Murphy @ 2020-02-18 12:40 UTC (permalink / raw)
  To: Nicolas Belin, linux-kernel, linux-leds, jacek.anaszewski, pavel

Nicolas

On 2/18/20 3:37 AM, Nicolas Belin wrote:
> Shenzhen Shiji Lighting Co.,Ltd is a LED manufacturer.
>
> Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
> ---

You need to add the devicetree mailing list and Rob Herring to this for 
their review of the dt bindings patches

Dan


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] leds: add support for apa102c leds
  2020-02-18  9:37 [PATCH 0/3] leds: add support for apa102c leds Nicolas Belin
                   ` (2 preceding siblings ...)
  2020-02-18  9:37 ` [PATCH 3/3] drivers: leds: add support for apa102c leds Nicolas Belin
@ 2020-02-18 12:43 ` Dan Murphy
  2020-02-18 21:26   ` Jacek Anaszewski
  2020-02-20 10:19   ` Nicolas Belin
  3 siblings, 2 replies; 14+ messages in thread
From: Dan Murphy @ 2020-02-18 12:43 UTC (permalink / raw)
  To: Nicolas Belin, linux-kernel, linux-leds, jacek.anaszewski, pavel

Hellp

On 2/18/20 3:37 AM, Nicolas Belin wrote:
> This patch series adds the driver and its related documentation
> for the APA102C RGB Leds.
>
> Patch 1 adds the APA102C led manufacturer to the vendor-prefixes list.
>
> Patch 2 Documents the APA102C led driver.
>
> Patch 3 contains the actual driver code and modifications in the Kconfig
> and the Makefile.

Is this something that can benefit from the Multicolor framework patches?

https://lore.kernel.org/patchwork/project/lkml/list/?series=427513

Can you RFC the APA102C driver on top of the Multicolor FW to see how it 
blends?

Dan


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver
  2020-02-18  9:37 ` [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver Nicolas Belin
@ 2020-02-18 20:28   ` Jacek Anaszewski
  2020-02-20 10:30   ` Geert Uytterhoeven
  1 sibling, 0 replies; 14+ messages in thread
From: Jacek Anaszewski @ 2020-02-18 20:28 UTC (permalink / raw)
  To: Nicolas Belin, linux-kernel, linux-leds, pavel, dmurphy

Hi Nicolas,

Thank you for the patch set.

On 2/18/20 10:37 AM, Nicolas Belin wrote:
> Document Shiji Lighting APA102C LED driver device tree bindings.
> 
> Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
> ---
>  .../devicetree/bindings/leds/leds-apa102c.yaml     | 91 ++++++++++++++++++++++
>  1 file changed, 91 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/leds/leds-apa102c.yaml
> 
> diff --git a/Documentation/devicetree/bindings/leds/leds-apa102c.yaml b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
> new file mode 100644
> index 000000000000..24bc2fc19fcb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
> @@ -0,0 +1,91 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/leds/leds-apa102c.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: LED driver for Shiji Lighting - APA102C
> +
> +maintainers:
> +  - Nicolas Belin <nbelin@baylibre.com>
> +
> +description:
> +  Each LED is represented as a sub-node of the leds-apa102c device.  Each LED
> +  is a three color RGB LED with 32 levels brightness adjustment that can be
> +  cascaded so that multiple LEDs can be set with a single command.
> +
> +properties:
> +  compatible:
> +    const: shiji,apa102c
> +
> +  reg:
> +    maxItems: 1
> +
> +  spi-max-frequency:
> +    maximum: 1000000
> +
> +  "#address-cells":
> +    const: 1
> +
> +  "#size-cells":
> +    const: 0
> +
> +required:
> +  - compatible
> +  - reg
> +  - spi-max-frequency
> +  - '#address-cells'
> +  - '#size-cells'
> +
> +patternProperties:
> +  "^led@[0-9]+$":
> +    type: object
> +    description: |
> +      Properties for an array of connected LEDs.
> +
> +    properties:
> +      reg:
> +        description: |
> +          This property corresponds to the led index. It has to be between 0
> +          and the number of managed leds minus 1
> +        maxItems: 1
> +
> +      label:

label property has been deprecated, please refer to common LED bindings
[0] and use function and color properties instead.

> +        description: |
> +          This property corresponds to the name of the led. If not set,
> +          the led index will be used to create the led name instead
> +        maxItems: 1
> +
> +      linux,default-trigger: true
> +
> +    required:
> +      - reg
> +
> +examples:
> +  - |
> +    spi {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        led-controller@0 {
> +            compatible = "shiji,apa102c";
> +            reg = <0>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +            spi-max-frequency = <1000000>;
> +            led@0 {
> +                reg = <0>;
> +                label = "led1";
> +            };
> +
> +            led@1 {
> +                reg = <1>;
> +                label = "led2";
> +            };
> +
> +            led@2 {
> +                reg = <2>;
> +                label = "led3";
> +            };
> +        };
> +    };
> 

[0] Documentation/devicetree/bindings/leds/common.txt

-- 
Best regards,
Jacek Anaszewski

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] drivers: leds: add support for apa102c leds
  2020-02-18  9:37 ` [PATCH 3/3] drivers: leds: add support for apa102c leds Nicolas Belin
@ 2020-02-18 21:13   ` Jacek Anaszewski
  2020-02-20 10:25     ` Nicolas Belin
  0 siblings, 1 reply; 14+ messages in thread
From: Jacek Anaszewski @ 2020-02-18 21:13 UTC (permalink / raw)
  To: Nicolas Belin, linux-kernel, linux-leds, pavel, dmurphy

Hi Nicolas,

On 2/18/20 10:37 AM, Nicolas Belin wrote:
> Initilial commit in order to support the apa102c RGB leds.
> 
> Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
> ---
>  drivers/leds/Kconfig        |  11 ++
>  drivers/leds/Makefile       |   1 +
>  drivers/leds/leds-apa102c.c | 268 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 280 insertions(+)
>  create mode 100644 drivers/leds/leds-apa102c.c
> 
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index d82f1dea3711..4fafeaaf6ee8 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -69,6 +69,17 @@ config LEDS_AN30259A
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called leds-an30259a.
>  
> +config LEDS_APA102C
> +	tristate "LED Support for Shiji APA102C"
> +	depends on LEDS_CLASS
> +	depends on SPI
> +	help
> +	  This option enables support for the Shiji Lighthing APA102C RGB full color
> +	  LEDs.
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called leds-apa102c.
> +
>  config LEDS_APU
>  	tristate "Front panel LED support for PC Engines APU/APU2/APU3 boards"
>  	depends on LEDS_CLASS
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index d7e1107753fb..ab17f90347cb 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_TRIGGERS)		+= led-triggers.o
>  # LED Platform Drivers
>  obj-$(CONFIG_LEDS_88PM860X)		+= leds-88pm860x.o
>  obj-$(CONFIG_LEDS_AAT1290)		+= leds-aat1290.o
> +obj-$(CONFIG_LEDS_APA102C)		+= leds-apa102c.o
>  obj-$(CONFIG_LEDS_APU)			+= leds-apu.o
>  obj-$(CONFIG_LEDS_AS3645A)		+= leds-as3645a.o
>  obj-$(CONFIG_LEDS_AN30259A)		+= leds-an30259a.o
> diff --git a/drivers/leds/leds-apa102c.c b/drivers/leds/leds-apa102c.c
> new file mode 100644
> index 000000000000..e7abe3f5b7c2
> --- /dev/null
> +++ b/drivers/leds/leds-apa102c.c
> @@ -0,0 +1,268 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Copyright (C) 2020 BayLibre, SAS
> + * Author: Nicolas Belin <nbelin@baylibre.com>
> + */

Please use "//" comment style for all the above lines.

> +
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/spi/spi.h>
> +#include <uapi/linux/uleds.h>
> +
> +/*
> + *  APA102C SPI protocol description:
> + *  +------+----------------------------------------+------+
> + *  |START |               DATA FIELD:              | END  |
> + *  |FRAME |               N LED FRAMES             |FRAME |
> + *  +------+------+------+------+------+-----+------+------+
> + *  | 0*32 | LED1 | LED2 | LED3 | LED4 | --- | LEDN | 1*32 |
> + *  +------+------+------+------+------+-----+------+------+
> + *
> + *  +-----------------------------------+
> + *  |START FRAME 32bits                 |
> + *  +--------+--------+--------+--------+
> + *  |00000000|00000000|00000000|00000000|
> + *  +--------+--------+--------+--------+
> + *
> + *  +------------------------------------+
> + *  |LED  FRAME 32bits                   |
> + *  +---+-----+--------+--------+--------+
> + *  |111|LUMA |  BLUE  | GREEN  |  RED   |
> + *  +---+-----+--------+--------+--------+
> + *  |3b |5bits| 8bits  | 8bits  | 8bits  |
> + *  +---+-----+--------+--------+--------+
> + *  |MSB   LSB|MSB  LSB|MSB  LSB|MSB  LSB|
> + *  +---+-----+--------+--------+--------+
> + *
> + *  +-----------------------------------+
> + *  |END FRAME 32bits                   |
> + *  +--------+--------+--------+--------+
> + *  |11111111|11111111|11111111|11111111|
> + *  +--------+--------+--------+--------+
> + */
> +
> +/* apa102c default settings */
> +#define CR_MAX_BRIGHTNESS	GENMASK(7, 0)
> +#define LM_MAX_BRIGHTNESS	GENMASK(4, 0)
> +#define CH_NUM			4
> +#define START_BYTE		0
> +#define END_BYTE		GENMASK(7, 0)
> +#define LED_FRAME_HEADER	GENMASK(7, 5)
> +
> +enum led_channels {
> +	RED,
> +	GREEN,
> +	BLUE,
> +	LUMA,
> +};
> +
> +struct apa102c_led {
> +	char			name[LED_MAX_NAME_SIZE];
> +	struct apa102c		*priv;
> +	struct led_classdev	ldev;
> +	u8			brightness;

Please drop this one, struct led_classdev already holds brightness
value.

> +};
> +
> +struct apa102c {
> +	size_t			led_count;
> +	struct device		*dev;
> +	struct mutex		lock;
> +	struct spi_device	*spi;
> +	u8			*buf;
> +	struct apa102c_led	leds[];
> +};
> +
> +static int apa102c_sync(struct apa102c *priv)
> +{
> +	int	ret;
> +	size_t	i;
> +	size_t	bytes = 0;
> +
> +	for (i = 0; i < 4; i++)
> +		priv->buf[bytes++] = START_BYTE;
> +
> +	for (i = 0; i < priv->led_count; i++) {
> +		priv->buf[bytes++] = LED_FRAME_HEADER |
> +				     priv->leds[i * CH_NUM + LUMA].brightness;
> +		priv->buf[bytes++] = priv->leds[i * CH_NUM + BLUE].brightness;
> +		priv->buf[bytes++] = priv->leds[i * CH_NUM + GREEN].brightness;
> +		priv->buf[bytes++] = priv->leds[i * CH_NUM + RED].brightness;

This is odd. You create separate LED class device for each color anyway,
so this seems pointless. We have pending LED multi color framework patch
set, as Dan mentioned, so you could try to use it. If you want to have
the patch set accepted quicker then just set brightness for one LED at
a time. You will be able to add LED multicolor class support later when
it will be ready.

> +	}
> +
> +	for (i = 0; i < 4; i++)
> +		priv->buf[bytes++] = END_BYTE;
> +
> +	ret = spi_write(priv->spi, priv->buf, bytes);
> +
> +	return ret;
> +}
> +
> +static int apa102c_set_sync(struct led_classdev *ldev,
> +			   enum led_brightness brightness)
> +{
> +	int			ret;
> +	struct apa102c_led	*led = container_of(ldev,
> +						    struct apa102c_led,
> +						    ldev);
> +
> +	dev_dbg(led->priv->dev, "Set brightness of %s to %d\n",
> +		led->name, brightness);
> +
> +	mutex_lock(&led->priv->lock);
> +	led->brightness = (u8)brightness;
> +	ret = apa102c_sync(led->priv);
> +	mutex_unlock(&led->priv->lock);
> +
> +	return ret;
> +}
> +
> +static int apa102c_probe_dt(struct apa102c *priv)
> +{
> +	u32			i = 0;
> +	int			j = 0;
> +	struct apa102c_led	*led;
> +	struct fwnode_handle	*child;
> +	struct device_node	*np;
> +	int			ret;
> +	int			use_index;
> +	const char		*str;
> +	static const char	* const rgb_name[] = {"red",
> +						      "green",
> +						      "blue",
> +						      "luma"};

We have LED_COLOR_ID* definitions in dt-bindings/leds/common.h
for red, green and blue. And regarding "luma" - what is specificity
of that one? If neither of existing definitions fits for it then
you are welcome to submit a patch adding LED_COLOR_ID_LUMA.

> +
> +	device_for_each_child_node(priv->dev, child) {
> +		np = to_of_node(child);
> +
> +		ret = fwnode_property_read_u32(child, "reg", &i);
> +		if (ret)
> +			return ret;
> +
> +		if (i >= priv->led_count)
> +			return -EINVAL;
> +
> +		/* use the index to create the name if the label is not set */
> +		use_index = fwnode_property_read_string(child, "label", &str);
> +
> +		/* for each physical LED, 4 LEDs are created representing
> +		 * the 4 components: red, green, blue and global luma.
> +		 */
> +		for (j = 0; j < CH_NUM; j++) {
> +			led = &priv->leds[i * CH_NUM + j];
> +
> +			if (use_index)
> +				snprintf(led->name, sizeof(led->name),
> +					 "apa102c:%s:%d", rgb_name[j], i);
> +			else
> +				snprintf(led->name, sizeof(led->name),
> +					 "apa102c:%s:%s", rgb_name[j], str);

LED core already handles LED name composition. Please refer to existing
LED class drivers that use devm_led_classdev_register_ext() API and use
it in your driver.

> +
> +			fwnode_property_read_string(child,
> +						    "linux,default-trigger",
> +						    &led->ldev.default_trigger);
> +
> +			led->priv			 = priv;
> +			led->ldev.name			 = led->name;
> +			if (j == LUMA) {
> +				led->ldev.brightness	 = led->brightness

What do you want to achieve here?

> +							 = LM_MAX_BRIGHTNESS;
> +				led->ldev.max_brightness = LM_MAX_BRIGHTNESS;
> +			} else {
> +				led->ldev.brightness	 = led->brightness
> +							 = 0;
> +				led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
> +			}
> +
> +			led->ldev.brightness_set_blocking = apa102c_set_sync;
> +
> +			ret = devm_led_classdev_register(priv->dev, &led->ldev);

As mentioned above - new *ext API will make your life easier.

> +			if (ret) {
> +				dev_err(priv->dev,
> +					"failed to register LED %s, err %d",
> +					led->name, ret);
> +				fwnode_handle_put(child);
> +				return ret;
> +			}
> +
> +			led->ldev.dev->of_node = np;
> +
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int apa102c_probe(struct spi_device *spi)
> +{
> +	struct apa102c	*priv;
> +	size_t		led_count;
> +	int		ret;
> +
> +	led_count = device_get_child_node_count(&spi->dev);
> +	if (!led_count) {
> +		dev_err(&spi->dev, "No LEDs defined in device tree!");
> +		return -ENODEV;
> +	}
> +
> +	priv = devm_kzalloc(&spi->dev,
> +			    struct_size(priv, leds, led_count * CH_NUM),
> +			    GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->buf = devm_kzalloc(&spi->dev, led_count * CH_NUM + 8, GFP_KERNEL);
> +	if (!priv->buf)
> +		return -ENOMEM;
> +
> +	mutex_init(&priv->lock);
> +	priv->led_count	= led_count;
> +	priv->dev	= &spi->dev;
> +	priv->spi	= spi;
> +
> +	ret = apa102c_probe_dt(priv);
> +	if (ret)
> +		return ret;
> +
> +	/* Set the LEDs with default values at start */
> +	apa102c_sync(priv);
> +	if (ret)
> +		return ret;
> +
> +	spi_set_drvdata(spi, priv);
> +
> +	return 0;
> +}
> +
> +static int apa102c_remove(struct spi_device *spi)
> +{
> +	struct apa102c *priv = spi_get_drvdata(spi);
> +
> +	mutex_destroy(&priv->lock);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id apa102c_dt_ids[] = {
> +	{ .compatible = "shiji,apa102c", },
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(of, apa102c_dt_ids);
> +
> +static struct spi_driver apa102c_driver = {
> +	.probe		= apa102c_probe,
> +	.remove		= apa102c_remove,
> +	.driver = {
> +		.name		= KBUILD_MODNAME,
> +		.of_match_table	= apa102c_dt_ids,
> +	},
> +};
> +
> +module_spi_driver(apa102c_driver);
> +
> +MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>");
> +MODULE_DESCRIPTION("apa102c LED driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("spi:apa102c");
> 

-- 
Best regards,
Jacek Anaszewski

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] leds: add support for apa102c leds
  2020-02-18 12:43 ` [PATCH 0/3] " Dan Murphy
@ 2020-02-18 21:26   ` Jacek Anaszewski
  2020-02-20 10:19   ` Nicolas Belin
  1 sibling, 0 replies; 14+ messages in thread
From: Jacek Anaszewski @ 2020-02-18 21:26 UTC (permalink / raw)
  To: Dan Murphy, Nicolas Belin, linux-kernel, linux-leds, pavel

Hi Dan,

On 2/18/20 1:43 PM, Dan Murphy wrote:
> Hellp
> 
> On 2/18/20 3:37 AM, Nicolas Belin wrote:
>> This patch series adds the driver and its related documentation
>> for the APA102C RGB Leds.
>>
>> Patch 1 adds the APA102C led manufacturer to the vendor-prefixes list.
>>
>> Patch 2 Documents the APA102C led driver.
>>
>> Patch 3 contains the actual driver code and modifications in the Kconfig
>> and the Makefile.
> 
> Is this something that can benefit from the Multicolor framework patches?
> 
> https://lore.kernel.org/patchwork/project/lkml/list/?series=427513
> 
> Can you RFC the APA102C driver on top of the Multicolor FW to see how it
> blends?

Just to let you know - I am currently playing with Samsung Galaxy S3,
which has mainline support, and also with a driver for its RGB LED:
leds-an30259a.c. I am adjusting that driver to LED multicolor class
and I will have certainly some more remarks (also to the variable naming
I proposed myself, which after few months feels awkward to me).

Generally speaking - we have to do everything to make the addition
of LED multicolor support to the driver way easier and more
straightforward since currently it is painful. I would go for
a separate compilation unit for multicolor specifc part of LED drivers.
But I will be able to tell more after few more days.

-- 
Best regards,
Jacek Anaszewski

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] leds: add support for apa102c leds
  2020-02-18 12:43 ` [PATCH 0/3] " Dan Murphy
  2020-02-18 21:26   ` Jacek Anaszewski
@ 2020-02-20 10:19   ` Nicolas Belin
  2020-02-26 14:19     ` Pavel Machek
  1 sibling, 1 reply; 14+ messages in thread
From: Nicolas Belin @ 2020-02-20 10:19 UTC (permalink / raw)
  To: Dan Murphy; +Cc: linux-kernel, linux-leds, jacek.anaszewski, pavel

Hi Dan,

Le mar. 18 févr. 2020 à 13:47, Dan Murphy <dmurphy@ti.com> a écrit :
>
> Hellp
>
> On 2/18/20 3:37 AM, Nicolas Belin wrote:
> > This patch series adds the driver and its related documentation
> > for the APA102C RGB Leds.
> >
> > Patch 1 adds the APA102C led manufacturer to the vendor-prefixes list.
> >
> > Patch 2 Documents the APA102C led driver.
> >
> > Patch 3 contains the actual driver code and modifications in the Kconfig
> > and the Makefile.
>
> Is this something that can benefit from the Multicolor framework patches?
>
> https://lore.kernel.org/patchwork/project/lkml/list/?series=427513
>
> Can you RFC the APA102C driver on top of the Multicolor FW to see how it
> blends?

Sure, the Multicolor framework will probably improve my driver !
I'll send you a new version once I have tested it.

>
> Dan
>

Thanks,

Nicolas

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] drivers: leds: add support for apa102c leds
  2020-02-18 21:13   ` Jacek Anaszewski
@ 2020-02-20 10:25     ` Nicolas Belin
  0 siblings, 0 replies; 14+ messages in thread
From: Nicolas Belin @ 2020-02-20 10:25 UTC (permalink / raw)
  To: Jacek Anaszewski; +Cc: linux-kernel, linux-leds, pavel, dmurphy

Hi Jacek,

Thanks for you feedback.
I am going to use multicolor framework as Dan mentioned, and fix the
issues you pointed out.

Regards,

Nicolas

Le mar. 18 févr. 2020 à 22:13, Jacek Anaszewski
<jacek.anaszewski@gmail.com> a écrit :
>
> Hi Nicolas,
>
> On 2/18/20 10:37 AM, Nicolas Belin wrote:
> > Initilial commit in order to support the apa102c RGB leds.
> >
> > Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
> > ---
> >  drivers/leds/Kconfig        |  11 ++
> >  drivers/leds/Makefile       |   1 +
> >  drivers/leds/leds-apa102c.c | 268 ++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 280 insertions(+)
> >  create mode 100644 drivers/leds/leds-apa102c.c
> >
> > diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> > index d82f1dea3711..4fafeaaf6ee8 100644
> > --- a/drivers/leds/Kconfig
> > +++ b/drivers/leds/Kconfig
> > @@ -69,6 +69,17 @@ config LEDS_AN30259A
> >         To compile this driver as a module, choose M here: the module
> >         will be called leds-an30259a.
> >
> > +config LEDS_APA102C
> > +     tristate "LED Support for Shiji APA102C"
> > +     depends on LEDS_CLASS
> > +     depends on SPI
> > +     help
> > +       This option enables support for the Shiji Lighthing APA102C RGB full color
> > +       LEDs.
> > +
> > +       To compile this driver as a module, choose M here: the module
> > +       will be called leds-apa102c.
> > +
> >  config LEDS_APU
> >       tristate "Front panel LED support for PC Engines APU/APU2/APU3 boards"
> >       depends on LEDS_CLASS
> > diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> > index d7e1107753fb..ab17f90347cb 100644
> > --- a/drivers/leds/Makefile
> > +++ b/drivers/leds/Makefile
> > @@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_TRIGGERS)           += led-triggers.o
> >  # LED Platform Drivers
> >  obj-$(CONFIG_LEDS_88PM860X)          += leds-88pm860x.o
> >  obj-$(CONFIG_LEDS_AAT1290)           += leds-aat1290.o
> > +obj-$(CONFIG_LEDS_APA102C)           += leds-apa102c.o
> >  obj-$(CONFIG_LEDS_APU)                       += leds-apu.o
> >  obj-$(CONFIG_LEDS_AS3645A)           += leds-as3645a.o
> >  obj-$(CONFIG_LEDS_AN30259A)          += leds-an30259a.o
> > diff --git a/drivers/leds/leds-apa102c.c b/drivers/leds/leds-apa102c.c
> > new file mode 100644
> > index 000000000000..e7abe3f5b7c2
> > --- /dev/null
> > +++ b/drivers/leds/leds-apa102c.c
> > @@ -0,0 +1,268 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +/*
> > + * Copyright (C) 2020 BayLibre, SAS
> > + * Author: Nicolas Belin <nbelin@baylibre.com>
> > + */
>
> Please use "//" comment style for all the above lines.
>
> > +
> > +#include <linux/leds.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +#include <linux/spi/spi.h>
> > +#include <uapi/linux/uleds.h>
> > +
> > +/*
> > + *  APA102C SPI protocol description:
> > + *  +------+----------------------------------------+------+
> > + *  |START |               DATA FIELD:              | END  |
> > + *  |FRAME |               N LED FRAMES             |FRAME |
> > + *  +------+------+------+------+------+-----+------+------+
> > + *  | 0*32 | LED1 | LED2 | LED3 | LED4 | --- | LEDN | 1*32 |
> > + *  +------+------+------+------+------+-----+------+------+
> > + *
> > + *  +-----------------------------------+
> > + *  |START FRAME 32bits                 |
> > + *  +--------+--------+--------+--------+
> > + *  |00000000|00000000|00000000|00000000|
> > + *  +--------+--------+--------+--------+
> > + *
> > + *  +------------------------------------+
> > + *  |LED  FRAME 32bits                   |
> > + *  +---+-----+--------+--------+--------+
> > + *  |111|LUMA |  BLUE  | GREEN  |  RED   |
> > + *  +---+-----+--------+--------+--------+
> > + *  |3b |5bits| 8bits  | 8bits  | 8bits  |
> > + *  +---+-----+--------+--------+--------+
> > + *  |MSB   LSB|MSB  LSB|MSB  LSB|MSB  LSB|
> > + *  +---+-----+--------+--------+--------+
> > + *
> > + *  +-----------------------------------+
> > + *  |END FRAME 32bits                   |
> > + *  +--------+--------+--------+--------+
> > + *  |11111111|11111111|11111111|11111111|
> > + *  +--------+--------+--------+--------+
> > + */
> > +
> > +/* apa102c default settings */
> > +#define CR_MAX_BRIGHTNESS    GENMASK(7, 0)
> > +#define LM_MAX_BRIGHTNESS    GENMASK(4, 0)
> > +#define CH_NUM                       4
> > +#define START_BYTE           0
> > +#define END_BYTE             GENMASK(7, 0)
> > +#define LED_FRAME_HEADER     GENMASK(7, 5)
> > +
> > +enum led_channels {
> > +     RED,
> > +     GREEN,
> > +     BLUE,
> > +     LUMA,
> > +};
> > +
> > +struct apa102c_led {
> > +     char                    name[LED_MAX_NAME_SIZE];
> > +     struct apa102c          *priv;
> > +     struct led_classdev     ldev;
> > +     u8                      brightness;
>
> Please drop this one, struct led_classdev already holds brightness
> value.
>
> > +};
> > +
> > +struct apa102c {
> > +     size_t                  led_count;
> > +     struct device           *dev;
> > +     struct mutex            lock;
> > +     struct spi_device       *spi;
> > +     u8                      *buf;
> > +     struct apa102c_led      leds[];
> > +};
> > +
> > +static int apa102c_sync(struct apa102c *priv)
> > +{
> > +     int     ret;
> > +     size_t  i;
> > +     size_t  bytes = 0;
> > +
> > +     for (i = 0; i < 4; i++)
> > +             priv->buf[bytes++] = START_BYTE;
> > +
> > +     for (i = 0; i < priv->led_count; i++) {
> > +             priv->buf[bytes++] = LED_FRAME_HEADER |
> > +                                  priv->leds[i * CH_NUM + LUMA].brightness;
> > +             priv->buf[bytes++] = priv->leds[i * CH_NUM + BLUE].brightness;
> > +             priv->buf[bytes++] = priv->leds[i * CH_NUM + GREEN].brightness;
> > +             priv->buf[bytes++] = priv->leds[i * CH_NUM + RED].brightness;
>
> This is odd. You create separate LED class device for each color anyway,
> so this seems pointless. We have pending LED multi color framework patch
> set, as Dan mentioned, so you could try to use it. If you want to have
> the patch set accepted quicker then just set brightness for one LED at
> a time. You will be able to add LED multicolor class support later when
> it will be ready.
>
> > +     }
> > +
> > +     for (i = 0; i < 4; i++)
> > +             priv->buf[bytes++] = END_BYTE;
> > +
> > +     ret = spi_write(priv->spi, priv->buf, bytes);
> > +
> > +     return ret;
> > +}
> > +
> > +static int apa102c_set_sync(struct led_classdev *ldev,
> > +                        enum led_brightness brightness)
> > +{
> > +     int                     ret;
> > +     struct apa102c_led      *led = container_of(ldev,
> > +                                                 struct apa102c_led,
> > +                                                 ldev);
> > +
> > +     dev_dbg(led->priv->dev, "Set brightness of %s to %d\n",
> > +             led->name, brightness);
> > +
> > +     mutex_lock(&led->priv->lock);
> > +     led->brightness = (u8)brightness;
> > +     ret = apa102c_sync(led->priv);
> > +     mutex_unlock(&led->priv->lock);
> > +
> > +     return ret;
> > +}
> > +
> > +static int apa102c_probe_dt(struct apa102c *priv)
> > +{
> > +     u32                     i = 0;
> > +     int                     j = 0;
> > +     struct apa102c_led      *led;
> > +     struct fwnode_handle    *child;
> > +     struct device_node      *np;
> > +     int                     ret;
> > +     int                     use_index;
> > +     const char              *str;
> > +     static const char       * const rgb_name[] = {"red",
> > +                                                   "green",
> > +                                                   "blue",
> > +                                                   "luma"};
>
> We have LED_COLOR_ID* definitions in dt-bindings/leds/common.h
> for red, green and blue. And regarding "luma" - what is specificity
> of that one? If neither of existing definitions fits for it then
> you are welcome to submit a patch adding LED_COLOR_ID_LUMA.
>
> > +
> > +     device_for_each_child_node(priv->dev, child) {
> > +             np = to_of_node(child);
> > +
> > +             ret = fwnode_property_read_u32(child, "reg", &i);
> > +             if (ret)
> > +                     return ret;
> > +
> > +             if (i >= priv->led_count)
> > +                     return -EINVAL;
> > +
> > +             /* use the index to create the name if the label is not set */
> > +             use_index = fwnode_property_read_string(child, "label", &str);
> > +
> > +             /* for each physical LED, 4 LEDs are created representing
> > +              * the 4 components: red, green, blue and global luma.
> > +              */
> > +             for (j = 0; j < CH_NUM; j++) {
> > +                     led = &priv->leds[i * CH_NUM + j];
> > +
> > +                     if (use_index)
> > +                             snprintf(led->name, sizeof(led->name),
> > +                                      "apa102c:%s:%d", rgb_name[j], i);
> > +                     else
> > +                             snprintf(led->name, sizeof(led->name),
> > +                                      "apa102c:%s:%s", rgb_name[j], str);
>
> LED core already handles LED name composition. Please refer to existing
> LED class drivers that use devm_led_classdev_register_ext() API and use
> it in your driver.
>
> > +
> > +                     fwnode_property_read_string(child,
> > +                                                 "linux,default-trigger",
> > +                                                 &led->ldev.default_trigger);
> > +
> > +                     led->priv                        = priv;
> > +                     led->ldev.name                   = led->name;
> > +                     if (j == LUMA) {
> > +                             led->ldev.brightness     = led->brightness
>
> What do you want to achieve here?
>
> > +                                                      = LM_MAX_BRIGHTNESS;
> > +                             led->ldev.max_brightness = LM_MAX_BRIGHTNESS;
> > +                     } else {
> > +                             led->ldev.brightness     = led->brightness
> > +                                                      = 0;
> > +                             led->ldev.max_brightness = CR_MAX_BRIGHTNESS;
> > +                     }
> > +
> > +                     led->ldev.brightness_set_blocking = apa102c_set_sync;
> > +
> > +                     ret = devm_led_classdev_register(priv->dev, &led->ldev);
>
> As mentioned above - new *ext API will make your life easier.
>
> > +                     if (ret) {
> > +                             dev_err(priv->dev,
> > +                                     "failed to register LED %s, err %d",
> > +                                     led->name, ret);
> > +                             fwnode_handle_put(child);
> > +                             return ret;
> > +                     }
> > +
> > +                     led->ldev.dev->of_node = np;
> > +
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int apa102c_probe(struct spi_device *spi)
> > +{
> > +     struct apa102c  *priv;
> > +     size_t          led_count;
> > +     int             ret;
> > +
> > +     led_count = device_get_child_node_count(&spi->dev);
> > +     if (!led_count) {
> > +             dev_err(&spi->dev, "No LEDs defined in device tree!");
> > +             return -ENODEV;
> > +     }
> > +
> > +     priv = devm_kzalloc(&spi->dev,
> > +                         struct_size(priv, leds, led_count * CH_NUM),
> > +                         GFP_KERNEL);
> > +     if (!priv)
> > +             return -ENOMEM;
> > +
> > +     priv->buf = devm_kzalloc(&spi->dev, led_count * CH_NUM + 8, GFP_KERNEL);
> > +     if (!priv->buf)
> > +             return -ENOMEM;
> > +
> > +     mutex_init(&priv->lock);
> > +     priv->led_count = led_count;
> > +     priv->dev       = &spi->dev;
> > +     priv->spi       = spi;
> > +
> > +     ret = apa102c_probe_dt(priv);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Set the LEDs with default values at start */
> > +     apa102c_sync(priv);
> > +     if (ret)
> > +             return ret;
> > +
> > +     spi_set_drvdata(spi, priv);
> > +
> > +     return 0;
> > +}
> > +
> > +static int apa102c_remove(struct spi_device *spi)
> > +{
> > +     struct apa102c *priv = spi_get_drvdata(spi);
> > +
> > +     mutex_destroy(&priv->lock);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct of_device_id apa102c_dt_ids[] = {
> > +     { .compatible = "shiji,apa102c", },
> > +     {},
> > +};
> > +
> > +MODULE_DEVICE_TABLE(of, apa102c_dt_ids);
> > +
> > +static struct spi_driver apa102c_driver = {
> > +     .probe          = apa102c_probe,
> > +     .remove         = apa102c_remove,
> > +     .driver = {
> > +             .name           = KBUILD_MODNAME,
> > +             .of_match_table = apa102c_dt_ids,
> > +     },
> > +};
> > +
> > +module_spi_driver(apa102c_driver);
> > +
> > +MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>");
> > +MODULE_DESCRIPTION("apa102c LED driver");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_ALIAS("spi:apa102c");
> >
>
> --
> Best regards,
> Jacek Anaszewski

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver
  2020-02-18  9:37 ` [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver Nicolas Belin
  2020-02-18 20:28   ` Jacek Anaszewski
@ 2020-02-20 10:30   ` Geert Uytterhoeven
  2020-02-20 19:41     ` Jacek Anaszewski
  1 sibling, 1 reply; 14+ messages in thread
From: Geert Uytterhoeven @ 2020-02-20 10:30 UTC (permalink / raw)
  To: Nicolas Belin
  Cc: Linux Kernel Mailing List, linux-leds, Jacek Anaszewski,
	Pavel Machek, Dan Murphy,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Lukas Wunner

Hi Nicolas,

CC devicetree, Lukas

On Tue, Feb 18, 2020 at 10:39 AM Nicolas Belin <nbelin@baylibre.com> wrote:
> Document Shiji Lighting APA102C LED driver device tree bindings.
>
> Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
> ---
>  .../devicetree/bindings/leds/leds-apa102c.yaml     | 91 ++++++++++++++++++++++
>  1 file changed, 91 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/leds/leds-apa102c.yaml
>
> diff --git a/Documentation/devicetree/bindings/leds/leds-apa102c.yaml b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
> new file mode 100644
> index 000000000000..24bc2fc19fcb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
> @@ -0,0 +1,91 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/leds/leds-apa102c.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: LED driver for Shiji Lighting - APA102C
> +
> +maintainers:
> +  - Nicolas Belin <nbelin@baylibre.com>
> +
> +description:
> +  Each LED is represented as a sub-node of the leds-apa102c device.  Each LED
> +  is a three color RGB LED with 32 levels brightness adjustment that can be
> +  cascaded so that multiple LEDs can be set with a single command.
> +
> +properties:
> +  compatible:
> +    const: shiji,apa102c
> +
> +  reg:
> +    maxItems: 1
> +
> +  spi-max-frequency:
> +    maximum: 1000000
> +
> +  "#address-cells":
> +    const: 1
> +
> +  "#size-cells":
> +    const: 0
> +
> +required:
> +  - compatible
> +  - reg
> +  - spi-max-frequency
> +  - '#address-cells'
> +  - '#size-cells'
> +
> +patternProperties:
> +  "^led@[0-9]+$":
> +    type: object
> +    description: |
> +      Properties for an array of connected LEDs.
> +
> +    properties:
> +      reg:
> +        description: |
> +          This property corresponds to the led index. It has to be between 0
> +          and the number of managed leds minus 1
> +        maxItems: 1
> +
> +      label:
> +        description: |
> +          This property corresponds to the name of the led. If not set,
> +          the led index will be used to create the led name instead
> +        maxItems: 1
> +
> +      linux,default-trigger: true
> +
> +    required:
> +      - reg
> +
> +examples:
> +  - |
> +    spi {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        led-controller@0 {
> +            compatible = "shiji,apa102c";
> +            reg = <0>;
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +            spi-max-frequency = <1000000>;
> +            led@0 {
> +                reg = <0>;
> +                label = "led1";
> +            };
> +
> +            led@1 {
> +                reg = <1>;
> +                label = "led2";
> +            };
> +
> +            led@2 {
> +                reg = <2>;
> +                label = "led3";
> +            };
> +        };
> +    };

Perhaps this should use "#daisy-chained-devices" instead of listing all LEDs
explicitly?
Or would that cause problems w.r.t. LED labeling?

Documentation/devicetree/bindings/common-properties.txt

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver
  2020-02-20 10:30   ` Geert Uytterhoeven
@ 2020-02-20 19:41     ` Jacek Anaszewski
  0 siblings, 0 replies; 14+ messages in thread
From: Jacek Anaszewski @ 2020-02-20 19:41 UTC (permalink / raw)
  To: Geert Uytterhoeven, Nicolas Belin
  Cc: Linux Kernel Mailing List, linux-leds, Pavel Machek, Dan Murphy,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Lukas Wunner

Hi Geert,

On 2/20/20 11:30 AM, Geert Uytterhoeven wrote:
> Hi Nicolas,
> 
> CC devicetree, Lukas
> 
> On Tue, Feb 18, 2020 at 10:39 AM Nicolas Belin <nbelin@baylibre.com> wrote:
>> Document Shiji Lighting APA102C LED driver device tree bindings.
>>
>> Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
>> ---
>>  .../devicetree/bindings/leds/leds-apa102c.yaml     | 91 ++++++++++++++++++++++
>>  1 file changed, 91 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/leds/leds-apa102c.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/leds/leds-apa102c.yaml b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
>> new file mode 100644
>> index 000000000000..24bc2fc19fcb
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/leds/leds-apa102c.yaml
>> @@ -0,0 +1,91 @@
>> +# SPDX-License-Identifier: GPL-2.0
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/leds/leds-apa102c.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: LED driver for Shiji Lighting - APA102C
>> +
>> +maintainers:
>> +  - Nicolas Belin <nbelin@baylibre.com>
>> +
>> +description:
>> +  Each LED is represented as a sub-node of the leds-apa102c device.  Each LED
>> +  is a three color RGB LED with 32 levels brightness adjustment that can be
>> +  cascaded so that multiple LEDs can be set with a single command.
>> +
>> +properties:
>> +  compatible:
>> +    const: shiji,apa102c
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  spi-max-frequency:
>> +    maximum: 1000000
>> +
>> +  "#address-cells":
>> +    const: 1
>> +
>> +  "#size-cells":
>> +    const: 0
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - spi-max-frequency
>> +  - '#address-cells'
>> +  - '#size-cells'
>> +
>> +patternProperties:
>> +  "^led@[0-9]+$":
>> +    type: object
>> +    description: |
>> +      Properties for an array of connected LEDs.
>> +
>> +    properties:
>> +      reg:
>> +        description: |
>> +          This property corresponds to the led index. It has to be between 0
>> +          and the number of managed leds minus 1
>> +        maxItems: 1
>> +
>> +      label:
>> +        description: |
>> +          This property corresponds to the name of the led. If not set,
>> +          the led index will be used to create the led name instead
>> +        maxItems: 1
>> +
>> +      linux,default-trigger: true
>> +
>> +    required:
>> +      - reg
>> +
>> +examples:
>> +  - |
>> +    spi {
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +
>> +        led-controller@0 {
>> +            compatible = "shiji,apa102c";
>> +            reg = <0>;
>> +            #address-cells = <1>;
>> +            #size-cells = <0>;
>> +            spi-max-frequency = <1000000>;
>> +            led@0 {
>> +                reg = <0>;
>> +                label = "led1";
>> +            };
>> +
>> +            led@1 {
>> +                reg = <1>;
>> +                label = "led2";
>> +            };
>> +
>> +            led@2 {
>> +                reg = <2>;
>> +                label = "led3";
>> +            };
>> +        };
>> +    };
> 
> Perhaps this should use "#daisy-chained-devices" instead of listing all LEDs
> explicitly?
> Or would that cause problems w.r.t. LED labeling?

It would be against common LED bindings.

Besides, this daisy-chain-devices property is not well documented.
I.e. I don't see how it facilitates conveying information on output
ID (here reg is used for that), and as you already mentioned
- LED labeling.

Generally speaking, I don't think it is applicable to the LED subsystem.

> Documentation/devicetree/bindings/common-properties.txt
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 

-- 
Best regards,
Jacek Anaszewski

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/3] leds: add support for apa102c leds
  2020-02-20 10:19   ` Nicolas Belin
@ 2020-02-26 14:19     ` Pavel Machek
  0 siblings, 0 replies; 14+ messages in thread
From: Pavel Machek @ 2020-02-26 14:19 UTC (permalink / raw)
  To: Nicolas Belin; +Cc: Dan Murphy, linux-kernel, linux-leds, jacek.anaszewski

[-- Attachment #1: Type: text/plain, Size: 684 bytes --]

Hi!

> > Is this something that can benefit from the Multicolor framework patches?
> >
> > https://lore.kernel.org/patchwork/project/lkml/list/?series=427513
> >
> > Can you RFC the APA102C driver on top of the Multicolor FW to see how it
> > blends?
> 
> Sure, the Multicolor framework will probably improve my driver !
> I'll send you a new version once I have tested it.

If you want to submit basic version of your driver that does _not_
support RGB, that may help get the driver merged early.

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2020-02-26 14:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-18  9:37 [PATCH 0/3] leds: add support for apa102c leds Nicolas Belin
2020-02-18  9:37 ` [PATCH 1/3] dt-bindings: Document shiji vendor-prefix Nicolas Belin
2020-02-18 12:40   ` Dan Murphy
2020-02-18  9:37 ` [PATCH 2/3] dt-bindings: leds: Shiji Lighting APA102C LED driver Nicolas Belin
2020-02-18 20:28   ` Jacek Anaszewski
2020-02-20 10:30   ` Geert Uytterhoeven
2020-02-20 19:41     ` Jacek Anaszewski
2020-02-18  9:37 ` [PATCH 3/3] drivers: leds: add support for apa102c leds Nicolas Belin
2020-02-18 21:13   ` Jacek Anaszewski
2020-02-20 10:25     ` Nicolas Belin
2020-02-18 12:43 ` [PATCH 0/3] " Dan Murphy
2020-02-18 21:26   ` Jacek Anaszewski
2020-02-20 10:19   ` Nicolas Belin
2020-02-26 14:19     ` Pavel Machek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).