mbox series

[v12,00/16] Multicolor Framework v12

Message ID 20191011130657.4713-1-dmurphy@ti.com
Headers show
Series Multicolor Framework v12 | expand

Message

Dan Murphy Oct. 11, 2019, 1:06 p.m. UTC
Hello

Minor changes per review comments.
https://lore.kernel.org/patchwork/project/lkml/list/?series=413385

Rebased the series on top of Pavel's next branch.

Multicolor changes:
Rename led_mc_calc_brightness to led_mc_calc_color_components
Updated the binding example for the function from STATUS to CHARGING

LP50xx changes:
None

LP55xx changes:
Changed color_component array allocation from COLOR_MAX_ID to MAX_GROUPED_CHANNELS
Updated MC API to call led_mc_calc_color_components

Dan

Dan Murphy (16):
  dt: bindings: Add multicolor class dt bindings documention
  dt-bindings: leds: Add multicolor ID to the color ID list
  leds: Add multicolor ID to the color ID list
  leds: multicolor: Introduce a multicolor class definition
  dt: bindings: lp50xx: Introduce the lp50xx family of RGB drivers
  leds: lp50xx: Add the LP50XX family of the RGB LED driver
  dt: bindings: lp55xx: Be consistent in the document with LED acronym
  dt: bindings: lp55xx: Update binding for Multicolor Framework
  ARM: dts: n900: Add reg property to the LP5523 channel node
  ARM: dts: imx6dl-yapp4: Add reg property to the lp5562 channel node
  ARM: dts: ste-href: Add reg property to the LP5521 channel nodes
  leds: lp55xx: Add multicolor framework support to lp55xx
  leds: lp5523: Update the lp5523 code to add intensity function
  leds: lp5521: Add multicolor framework intensity support
  leds: lp55xx: Fix checkpatch file permissions issues
  leds: lp5523: Fix checkpatch issues in the code

 .../ABI/testing/sysfs-class-led-multicolor    |  36 +
 .../bindings/leds/leds-class-multicolor.txt   |  98 +++
 .../devicetree/bindings/leds/leds-lp50xx.txt  | 148 ++++
 .../devicetree/bindings/leds/leds-lp55xx.txt  | 155 +++-
 Documentation/leds/index.rst                  |   1 +
 Documentation/leds/leds-class-multicolor.rst  |  96 +++
 arch/arm/boot/dts/imx6dl-yapp4-common.dtsi    |  14 +-
 arch/arm/boot/dts/omap3-n900.dts              |  29 +-
 arch/arm/boot/dts/ste-href.dtsi               |  22 +-
 drivers/leds/Kconfig                          |  22 +
 drivers/leds/Makefile                         |   2 +
 drivers/leds/led-class-multicolor.c           | 271 ++++++
 drivers/leds/led-core.c                       |   1 +
 drivers/leds/leds-lp50xx.c                    | 799 ++++++++++++++++++
 drivers/leds/leds-lp5521.c                    |  20 +
 drivers/leds/leds-lp5523.c                    |  39 +-
 drivers/leds/leds-lp55xx-common.c             | 198 ++++-
 drivers/leds/leds-lp55xx-common.h             |   9 +
 include/dt-bindings/leds/common.h             |   3 +-
 include/linux/led-class-multicolor.h          | 143 ++++
 include/linux/platform_data/leds-lp55xx.h     |   7 +
 21 files changed, 2020 insertions(+), 93 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-class-led-multicolor
 create mode 100644 Documentation/devicetree/bindings/leds/leds-class-multicolor.txt
 create mode 100644 Documentation/devicetree/bindings/leds/leds-lp50xx.txt
 create mode 100644 Documentation/leds/leds-class-multicolor.rst
 create mode 100644 drivers/leds/led-class-multicolor.c
 create mode 100644 drivers/leds/leds-lp50xx.c
 create mode 100644 include/linux/led-class-multicolor.h

-- 
2.22.0.214.g8dca754b1e

Comments

Jacek Anaszewski Oct. 11, 2019, 7:53 p.m. UTC | #1
Dan,

On 10/11/19 3:06 PM, Dan Murphy wrote:
> Introduce a multicolor class that groups colored LEDs

> within a LED node.

> 

> The multi color class groups monochrome LEDs and allows controlling two

> aspects of the final combined color: hue and lightness. The former is

> controlled via <color>_intensity files and the latter is controlled

> via brightness file.

> 

> Signed-off-by: Dan Murphy <dmurphy@ti.com>

> ---

>  .../ABI/testing/sysfs-class-led-multicolor    |  36 +++

>  .../bindings/leds/leds-class-multicolor.txt   |   4 +-

>  Documentation/leds/index.rst                  |   1 +

>  Documentation/leds/leds-class-multicolor.rst  |  96 +++++++

>  drivers/leds/Kconfig                          |  10 +

>  drivers/leds/Makefile                         |   1 +

>  drivers/leds/led-class-multicolor.c           | 271 ++++++++++++++++++

>  include/linux/led-class-multicolor.h          | 143 +++++++++

>  8 files changed, 560 insertions(+), 2 deletions(-)

>  create mode 100644 Documentation/ABI/testing/sysfs-class-led-multicolor

>  create mode 100644 Documentation/leds/leds-class-multicolor.rst

>  create mode 100644 drivers/leds/led-class-multicolor.c

>  create mode 100644 include/linux/led-class-multicolor.h

> 

> diff --git a/Documentation/ABI/testing/sysfs-class-led-multicolor b/Documentation/ABI/testing/sysfs-class-led-multicolor

> new file mode 100644

> index 000000000000..3d1f9d726c70

> --- /dev/null

> +++ b/Documentation/ABI/testing/sysfs-class-led-multicolor

> @@ -0,0 +1,36 @@

> +What:		/sys/class/leds/<led>/brightness

> +Date:		Sept 2019

> +KernelVersion:	5.5

> +Contact:	Dan Murphy <dmurphy@ti.com>

> +Description:	read/write

> +		Writing to this file will update all LEDs within the group to a

> +		calculated percentage of what each color LED intensity is set

> +		to. The percentage is calculated for each grouped LED via the

> +		equation below:

> +

> +		led_brightness = brightness * <color>_intensity/<color>_max_intensity

> +

> +		For additional details please refer to

> +		Documentation/leds/leds-class-multicolor.rst.

> +

> +		The value of the color is from 0 to

> +		/sys/class/leds/<led>/max_brightness.

> +

> +What:		/sys/class/leds/<led>/colors/<color>_intensity

> +Date:		Sept 2019

> +KernelVersion:	5.5

> +Contact:	Dan Murphy <dmurphy@ti.com>

> +Description:	read/write

> +		The <color>_intensity file is created based on the color

> +		defined by the registrar of the class.

> +		There is one file per color presented.

> +

> +		The value of the color is from 0 to

> +		/sys/class/leds/<led>/colors/<color>_max_intensity.

> +

> +What:		/sys/class/leds/<led>/colors/<color>_max_intensity

> +Date:		Sept 2019

> +KernelVersion:	5.5

> +Contact:	Dan Murphy <dmurphy@ti.com>

> +Description:	read only

> +		Maximum intensity level for the LED color.

> diff --git a/Documentation/devicetree/bindings/leds/leds-class-multicolor.txt b/Documentation/devicetree/bindings/leds/leds-class-multicolor.txt

> index 8619c9bf1811..4b1bd82f2a42 100644

> --- a/Documentation/devicetree/bindings/leds/leds-class-multicolor.txt

> +++ b/Documentation/devicetree/bindings/leds/leds-class-multicolor.txt

> @@ -10,7 +10,7 @@ The nodes and properties defined in this document are unique to the multicolor

>  LED class.  Common LED nodes and properties are inherited from the common.txt

>  within this documentation directory.

>  

> -Required LED Child properties:

> +Required LED child properties:

>  	- color : For multicolor LED support this property should be defined as

>  		  LED_COLOR_ID_MULTI and further definition can be found in

>  		  include/linux/leds/common.h.

> @@ -26,7 +26,7 @@ led-controller@30 {

>  		#size-cells = <0>;

>  		reg = <1>;

>  		color = <LED_COLOR_ID_MULTI>;

> -		function = LED_FUNCTION_STATUS;

> +		function = LED_FUNCTION_CHARGING;

>  


So this went to wrong patch.

-- 
Best regards,
Jacek Anaszewski
Jacek Anaszewski Oct. 11, 2019, 8:15 p.m. UTC | #2
Dan,

On 10/11/19 3:06 PM, Dan Murphy wrote:
> Update the DT binding to include the properties to use the

> multicolor framework for the devices that use the LP55xx

> framework.

> 

> Signed-off-by: Dan Murphy <dmurphy@ti.com>

> CC: Tony Lindgren <tony@atomide.com>

> CC: "Benoît Cousson" <bcousson@baylibre.com>

> CC: Linus Walleij <linus.walleij@linaro.org>

> CC: Shawn Guo <shawnguo@kernel.org>

> CC: Sascha Hauer <s.hauer@pengutronix.de>

> CC: Pengutronix Kernel Team <kernel@pengutronix.de>

> CC: Fabio Estevam <festevam@gmail.com>

> CC: NXP Linux Team <linux-imx@nxp.com>

> ---

>  .../devicetree/bindings/leds/leds-lp55xx.txt  | 149 +++++++++++++++---

>  1 file changed, 124 insertions(+), 25 deletions(-)

> 

> diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

> index bfe2805c5534..736a2e1538be 100644

> --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

> +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

> @@ -1,6 +1,8 @@

>  Binding for TI/National Semiconductor LP55xx LED Drivers

>  

>  Required properties:

> +- #address-cells: 1

> +- #size-cells: 0

>  - compatible: one of

>  	national,lp5521

>  	national,lp5523

> @@ -14,6 +16,18 @@ Required properties:

>  Each child has own specific current settings

>  - led-cur: Current setting at each LED channel (mA x10, 0 if LED is not connected)

>  - max-cur: Maximun current at each LED channel.

> +- reg: Output channel for the LED.  This is zero based channel identifier and

> +	the data sheet is a one based channel identifier.

> +	reg value to output to LED output number

> +	D1 = reg value is 0

> +	D2 = reg value is 1

> +	D3 = reg value is 2

> +	D4 = reg value is 3

> +	D5 = reg value is 4

> +	D6 = reg value is 5

> +	D7 = reg value is 6

> +	D8 = reg value is 7

> +	D9 = reg value is 8

>  

>  Optional properties:

>  - enable-gpio: GPIO attached to the chip's enable pin

> @@ -35,23 +49,28 @@ example 1) LP5521

>  on channel 0.

>  

>  lp5521@32 {


While at it let's fix node prefix to led-controller.
It will not break anyone and yet it will adapt the node naming
to what is now recommended.

> +	#address-cells = <1>;

> +	#size-cells = <0>;

>  	compatible = "national,lp5521";

>  	reg = <0x32>;

>  	label = "lp5521_pri";

>  	clock-mode = /bits/ 8 <2>;

>  

> -	chan0 {

> +	chan@0 {


Similarly in case of every child node:

s/chan/led/

> +		reg = <0>;

>  		led-cur = /bits/ 8 <0x2f>;

>  		max-cur = /bits/ 8 <0x5f>;

>  		linux,default-trigger = "heartbeat";

>  	};

>  

> -	chan1 {

> +	chan@1 {

> +		reg = <1>;

>  		led-cur = /bits/ 8 <0x2f>;

>  		max-cur = /bits/ 8 <0x5f>;

>  	};

>  

> -	chan2 {

> +	chan@2 {

> +		reg = <2>;

>  		led-cur = /bits/ 8 <0x2f>;

>  		max-cur = /bits/ 8 <0x5f>;

>  	};

> @@ -70,59 +89,70 @@ ASEL1    ASEL0    Address

>   VEN      VEN       35h

>  

>  lp5523@32 {


s/lp5523/led-controller/

> +	#address-cells = <1>;

> +	#size-cells = <0>;

>  	compatible = "national,lp5523";

>  	reg = <0x32>;

>  	clock-mode = /bits/ 8 <1>;

>  

> -	chan0 {

> +	chan@0 {

> +		reg = <0>;

>  		chan-name = "d1";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan1 {

> +	chan@1 {

> +		reg = <1>;

>  		chan-name = "d2";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan2 {

> +	chan@2 {

> +		reg = <2>;

>  		chan-name = "d3";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan3 {

> +	chan@3 {

> +		reg = <3>;

>  		chan-name = "d4";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan4 {

> +	chan@4 {

> +		reg = <4>;

>  		chan-name = "d5";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan5 {

> +	chan@5 {

> +		reg = <5>;

>  		chan-name = "d6";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan6 {

> +	chan@6 {

> +		reg = <6>;

>  		chan-name = "d7";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan7 {

> +	chan@7 {

> +		reg = <7>;

>  		chan-name = "d8";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan8 {

> +	chan@8 {

> +		reg = <8>;

>  		chan-name = "d9";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

> @@ -133,29 +163,35 @@ example 3) LP5562

>  4 channels are defined.

>  

>  lp5562@30 {


s/lp5562/led-controller/

> +	#address-cells = <1>;

> +	#size-cells = <0>;

>  	compatible = "ti,lp5562";

>  	reg = <0x30>;

>  	clock-mode = /bits/8 <2>;

>  

> -	chan0 {

> +	chan@0 {

> +		reg = <0>;

>  		chan-name = "R";

>  		led-cur = /bits/ 8 <0x20>;

>  		max-cur = /bits/ 8 <0x60>;

>  	};

>  

> -	chan1 {

> +	chan@1 {

> +		reg = <1>;

>  		chan-name = "G";

>  		led-cur = /bits/ 8 <0x20>;

>  		max-cur = /bits/ 8 <0x60>;

>  	};

>  

> -	chan2 {

> +	chan@2 {

> +		reg = <2>;

>  		chan-name = "B";

>  		led-cur = /bits/ 8 <0x20>;

>  		max-cur = /bits/ 8 <0x60>;

>  	};

>  

> -	chan3 {

> +	chan@3 {

> +		reg = <3>;

>  		chan-name = "W";

>  		led-cur = /bits/ 8 <0x20>;

>  		max-cur = /bits/ 8 <0x60>;

> @@ -167,62 +203,125 @@ example 4) LP8501

>  Others are same as LP5523.

>  

>  lp8501@32 {


s/lp8501/led-controller/

> +	#address-cells = <1>;

> +	#size-cells = <0>;

>  	compatible = "ti,lp8501";

>  	reg = <0x32>;

>  	clock-mode = /bits/ 8 <2>;

>  	pwr-sel = /bits/ 8 <3>;	/* D1~9 connected to VOUT */

>  

> -	chan0 {

> +	chan@0 {

> +		reg = <0>;

>  		chan-name = "d1";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan1 {

> +	chan@1 {

> +		reg = <1>;

>  		chan-name = "d2";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan2 {

> +	chan@2 {

> +		reg = <2>;

>  		chan-name = "d3";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan3 {

> +	chan@3 {

> +		reg = <3>;

>  		chan-name = "d4";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan4 {

> +	chan@4 {

> +		reg = <4>;

>  		chan-name = "d5";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan5 {

> +	chan@5 {

> +		reg = <5>;

>  		chan-name = "d6";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan6 {

> +	chan@6 {

> +		reg = <6>;

>  		chan-name = "d7";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan7 {

> +	chan@7 {

> +		reg = <7>;

>  		chan-name = "d8";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  

> -	chan8 {

> +	chan@8 {

> +		reg = <8>;

>  		chan-name = "d9";

>  		led-cur = /bits/ 8 <0x14>;

>  		max-cur = /bits/ 8 <0x20>;

>  	};

>  };

> +

> +Multicolor Framework Support

> +In addition to the nodes and properties defined above for device support the

> +properties below are needed for multicolor framework support as defined in

> +Documentation/devicetree/bindings/leds/leds-class-multicolor.txt

> +

> +Required child properties for multicolor framework

> +	- color : Must be LED_COLOR_ID_MULTI

> +	- function : see Documentation/devicetree/bindings/leds/common.txt

> +

> +Required grandchildren properties

> +	- reg : This is the LED output of the device

> +	- color : see Documentation/devicetree/bindings/leds/common.txt

> +

> +Multicolor LED example:

> +lp5523: lp5523@32 {


Do you really need "lp5523:" node label ?

Besides:

s/lp5523@32/led-controller@32/

> +	#address-cells = <1>;

> +	#size-cells = <0>;

> +	compatible = "national,lp5523";

> +	reg = <0x32>;

> +	clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */

> +

> +	multi-led@2 {

> +		#address-cells = <1>;

> +		#size-cells = <0>;

> +		reg = <2>;

> +		color = <LED_COLOR_ID_MULTI>;

> +		function = LED_FUNCTION_STANDBY;

> +		linux,default-trigger = "heartbeat";

> +

> +		led@0 {

> +			led-cur = /bits/ 8 <50>;

> +			max-cur = /bits/ 8 <100>;

> +			reg = <0x0>;

> +			color = <LED_COLOR_ID_GREEN>;

> +		};

> +

> +		led@1 {

> +			led-cur = /bits/ 8 <50>;

> +			max-cur = /bits/ 8 <100>;

> +			reg = <0x1>;

> +			color = <LED_COLOR_ID_BLUE>;

> +		};

> +

> +		led@6 {

> +			led-cur = /bits/ 8 <50>;

> +			max-cur = /bits/ 8 <100>;

> +			reg = <0x6>;

> +			color = <LED_COLOR_ID_RED>;

> +		};

> +	};

> +};

> 


-- 
Best regards,
Jacek Anaszewski
Jacek Anaszewski Oct. 11, 2019, 8:36 p.m. UTC | #3
Dan,

On 10/11/19 3:06 PM, Dan Murphy wrote:
> Add multicolor framework support for the lp55xx family.

> 

> Signed-off-by: Dan Murphy <dmurphy@ti.com>

> ---

>  drivers/leds/Kconfig                      |   1 +

>  drivers/leds/leds-lp55xx-common.c         | 176 +++++++++++++++++++---

>  drivers/leds/leds-lp55xx-common.h         |   9 ++

>  include/linux/platform_data/leds-lp55xx.h |   7 +

>  4 files changed, 169 insertions(+), 24 deletions(-)

> 

> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig

> index fb614a6b9afa..5706bf8d8bd1 100644

> --- a/drivers/leds/Kconfig

> +++ b/drivers/leds/Kconfig

> @@ -377,6 +377,7 @@ config LEDS_LP50XX

>  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

> +	depends on OF

>  	select FW_LOADER

>  	select FW_LOADER_USER_HELPER

>  	help

> diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c

> index 44ced02b49f9..1417df6df8a7 100644

> --- a/drivers/leds/leds-lp55xx-common.c

> +++ b/drivers/leds/leds-lp55xx-common.c

> @@ -131,14 +131,54 @@ static struct attribute *lp55xx_led_attrs[] = {

>  };

>  ATTRIBUTE_GROUPS(lp55xx_led);

>  

> +static int lp55xx_map_channel(struct lp55xx_led *led, int color_id,

> +			      enum led_brightness brightness)

> +{

> +	int i;

> +

> +	for (i = 0; i < led->mc_cdev.num_leds; i++) {

> +		if (led->color_component[i].color_id == color_id) {

> +			led->color_component[i].brightness = brightness;

> +			return 0;

> +		}

> +	}

> +

> +	return -EINVAL;

> +}

> +

>  static int lp55xx_set_brightness(struct led_classdev *cdev,

>  			     enum led_brightness brightness)

>  {

> +	struct led_mc_color_conversion color_component[LP55XX_MAX_GROUPED_CHAN];

>  	struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);

>  	struct lp55xx_device_config *cfg = led->chip->cfg;

> +	int ret;

> +	int i;

>  

> -	led->brightness = (u8)brightness;

> -	return cfg->brightness_fn(led);

> +	if (led->mc_cdev.num_leds > 1) {

> +		if (!cfg->color_intensity_fn)

> +			return -EINVAL;

> +

> +		led_mc_calc_color_components(&led->mc_cdev, brightness,

> +					     color_component);

> +

> +		for (i = 0; i < led->mc_cdev.num_leds; i++) {

> +			ret = lp55xx_map_channel(led,

> +						color_component[i].color_id,

> +						color_component[i].brightness);

> +			if (ret)

> +				return ret;

> +		}

> +

> +		ret = cfg->color_intensity_fn(led);

> +		if (ret)

> +			return ret;

> +	} else {

> +		led->brightness = (u8)brightness;

> +		ret = cfg->brightness_fn(led);

> +	}

> +

> +	return ret;

>  }

>  

>  static int lp55xx_init_led(struct lp55xx_led *led,

> @@ -147,9 +187,9 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>  	struct lp55xx_platform_data *pdata = chip->pdata;

>  	struct lp55xx_device_config *cfg = chip->cfg;

>  	struct device *dev = &chip->cl->dev;

> +	int max_channel = cfg->max_channel;

>  	char name[32];

>  	int ret;

> -	int max_channel = cfg->max_channel;

>  

>  	if (chan >= max_channel) {

>  		dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);

> @@ -159,10 +199,34 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>  	if (pdata->led_config[chan].led_current == 0)

>  		return 0;

>  

> +	if (pdata->led_config[chan].name) {

> +		led->cdev.name = pdata->led_config[chan].name;

> +	} else {

> +		snprintf(name, sizeof(name), "%s:channel%d",

> +			pdata->label ? : chip->cl->name, chan);

> +		led->cdev.name = name;

> +	}

> +

> +	if (pdata->led_config[chan].num_colors > 1) {

> +		led->mc_cdev.led_cdev = &led->cdev;

> +		led->cdev.brightness_set_blocking = lp55xx_set_brightness;

> +		led->cdev.groups = lp55xx_led_groups;

> +		led->mc_cdev.num_leds = pdata->led_config[chan].num_colors;

> +		led->mc_cdev.available_colors =

> +			pdata->led_config[chan].available_colors;

> +		memcpy(led->color_component,

> +		       pdata->led_config[chan].color_component,

> +		       sizeof(led->color_component));

> +	} else {

> +

> +		led->cdev.default_trigger =

> +			pdata->led_config[chan].default_trigger;

> +		led->cdev.brightness_set_blocking = lp55xx_set_brightness;

> +	}	led->cdev.groups = lp55xx_led_groups;

> +

>  	led->led_current = pdata->led_config[chan].led_current;

>  	led->max_current = pdata->led_config[chan].max_current;

>  	led->chan_nr = pdata->led_config[chan].chan_nr;

> -	led->cdev.default_trigger = pdata->led_config[chan].default_trigger;

>  

>  	if (led->chan_nr >= max_channel) {

>  		dev_err(dev, "Use channel numbers between 0 and %d\n",

> @@ -170,18 +234,11 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>  		return -EINVAL;

>  	}

>  

> -	led->cdev.brightness_set_blocking = lp55xx_set_brightness;

> -	led->cdev.groups = lp55xx_led_groups;

> -

> -	if (pdata->led_config[chan].name) {

> -		led->cdev.name = pdata->led_config[chan].name;

> -	} else {

> -		snprintf(name, sizeof(name), "%s:channel%d",

> -			pdata->label ? : chip->cl->name, chan);

> -		led->cdev.name = name;

> -	}

> +	if (pdata->led_config[chan].num_colors > 1)

> +		ret = led_classdev_multicolor_register(dev, &led->mc_cdev);

> +	else

> +		ret = led_classdev_register(dev, &led->cdev);


Why not devm versions?

> -	ret = led_classdev_register(dev, &led->cdev);

>  	if (ret) {

>  		dev_err(dev, "led register err: %d\n", ret);

>  		return ret;

> @@ -466,7 +523,6 @@ int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)

>  		dev_err(&chip->cl->dev, "empty brightness configuration\n");

>  		return -EINVAL;

>  	}

> -


This empty line removal was not intended I suppose.

>  	for (i = 0; i < num_channels; i++) {

>  

>  		/* do not initialize channels that are not connected */

> @@ -538,6 +594,82 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)

>  }

>  EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);

>  

> +static int lp5xx_parse_common_child(struct device_node *np,

> +				    struct lp55xx_led_config *cfg,

> +				    int chan_num, bool is_multicolor,

> +				    int color_num)

> +{

> +	u32 led_number;

> +	int ret;

> +

> +	of_property_read_string(np, "chan-name",

> +				&cfg[chan_num].name);

> +	of_property_read_u8(np, "led-cur",

> +			    &cfg[chan_num].led_current);

> +	of_property_read_u8(np, "max-cur",

> +			    &cfg[chan_num].max_current);

> +

> +	ret = of_property_read_u32(np, "reg", &led_number);

> +	if (ret)

> +		return ret;

> +

> +	if (led_number < 0 || led_number > 6)

> +		return -EINVAL;

> +

> +	if (is_multicolor)

> +		cfg[chan_num].color_component[color_num].output_num =

> +								led_number;

> +	else

> +		cfg[chan_num].chan_nr = led_number;

> +

> +	return 0;

> +}

> +

> +static int lp5xx_parse_channel_child(struct device_node *np,

> +				     struct lp55xx_led_config *cfg,

> +				     int child_number)

> +{

> +	struct device_node *child;

> +	int channel_color;

> +	int num_colors = 0;

> +	u32 color_id;

> +	int ret;

> +

> +	cfg[child_number].default_trigger =

> +			of_get_property(np, "linux,default-trigger", NULL);

> +

> +	ret = of_property_read_u32(np, "color", &channel_color);

> +	if (ret)

> +		channel_color = ret;

> +

> +

> +	if (channel_color == LED_COLOR_ID_MULTI) {

> +		for_each_child_of_node(np, child) {

> +			ret = lp5xx_parse_common_child(child, cfg,

> +						       child_number, true,

> +						       num_colors);

> +			if (ret)

> +				return ret;

> +

> +			ret = of_property_read_u32(child, "color", &color_id);

> +			if (ret)

> +				return ret;

> +

> +			cfg[child_number].color_component[num_colors].color_id =

> +						color_id;

> +			set_bit(color_id, &cfg[child_number].available_colors);

> +			num_colors++;

> +		}

> +

> +		cfg[child_number].num_colors = num_colors;

> +	} else {

> +		return lp5xx_parse_common_child(np, cfg, child_number, false,

> +						num_colors);

> +	}

> +

> +	return 0;

> +}

> +

>  struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,

>  						      struct device_node *np)

>  {

> @@ -546,6 +678,7 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,

>  	struct lp55xx_led_config *cfg;

>  	int num_channels;

>  	int i = 0;

> +	int ret;

>  

>  	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);

>  	if (!pdata)

> @@ -565,14 +698,9 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,

>  	pdata->num_channels = num_channels;

>  

>  	for_each_child_of_node(np, child) {

> -		cfg[i].chan_nr = i;

> -

> -		of_property_read_string(child, "chan-name", &cfg[i].name);

> -		of_property_read_u8(child, "led-cur", &cfg[i].led_current);

> -		of_property_read_u8(child, "max-cur", &cfg[i].max_current);

> -		cfg[i].default_trigger =

> -			of_get_property(child, "linux,default-trigger", NULL);

> -

> +		ret = lp5xx_parse_channel_child(child, cfg, i);

> +		if (ret)

> +			return ERR_PTR(-EINVAL);

>  		i++;

>  	}

>  

> diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h

> index 783ed5103ce5..75d57fb835c3 100644

> --- a/drivers/leds/leds-lp55xx-common.h

> +++ b/drivers/leds/leds-lp55xx-common.h

> @@ -12,6 +12,8 @@

>  #ifndef _LEDS_LP55XX_COMMON_H

>  #define _LEDS_LP55XX_COMMON_H

>  

> +#include <linux/led-class-multicolor.h>

> +

>  enum lp55xx_engine_index {

>  	LP55XX_ENGINE_INVALID,

>  	LP55XX_ENGINE_1,

> @@ -109,6 +111,9 @@ struct lp55xx_device_config {

>  	/* access brightness register */

>  	int (*brightness_fn)(struct lp55xx_led *led);

>  

> +	/* access specific brightness register */

> +	int (*color_intensity_fn)(struct lp55xx_led *led);


Wouldn't multicolor_brightness_fn be more accurate now ?

It is vital to reduce possibility of confusing mc framework
intensity with brightness level that is set on each grouped
monochrome LED channel.

> +

>  	/* current setting function */

>  	void (*set_led_current) (struct lp55xx_led *led, u8 led_current);

>  

> @@ -159,6 +164,8 @@ struct lp55xx_chip {

>   * struct lp55xx_led

>   * @chan_nr         : Channel number

>   * @cdev            : LED class device

> + * @mc_cdev	    : Multi color class device

> + * @color_component : Multi color LED map information

>   * @led_current     : Current setting at each led channel

>   * @max_current     : Maximun current at each led channel

>   * @brightness      : Brightness value

> @@ -167,6 +174,8 @@ struct lp55xx_chip {

>  struct lp55xx_led {

>  	int chan_nr;

>  	struct led_classdev cdev;

> +	struct led_classdev_mc mc_cdev;

> +	struct led_mc_color_conversion color_component[LP55XX_MAX_GROUPED_CHAN];

>  	u8 led_current;

>  	u8 max_current;

>  	u8 brightness;

> diff --git a/include/linux/platform_data/leds-lp55xx.h b/include/linux/platform_data/leds-lp55xx.h

> index 96a787100fda..0f9b88019c18 100644

> --- a/include/linux/platform_data/leds-lp55xx.h

> +++ b/include/linux/platform_data/leds-lp55xx.h

> @@ -12,17 +12,24 @@

>  #ifndef _LEDS_LP55XX_H

>  #define _LEDS_LP55XX_H

>  

> +#include <linux/led-class-multicolor.h>

> +

>  /* Clock configuration */

>  #define LP55XX_CLOCK_AUTO	0

>  #define LP55XX_CLOCK_INT	1

>  #define LP55XX_CLOCK_EXT	2

>  

> +#define LP55XX_MAX_GROUPED_CHAN	4

> +

>  struct lp55xx_led_config {

>  	const char *name;

>  	const char *default_trigger;

>  	u8 chan_nr;

>  	u8 led_current; /* mA x10, 0 if led is not connected */

>  	u8 max_current;

> +	int num_colors;

> +	unsigned long available_colors;

> +	struct led_mc_color_conversion color_component[LP55XX_MAX_GROUPED_CHAN];

>  };

>  

>  struct lp55xx_predef_pattern {

> 


-- 
Best regards,
Jacek Anaszewski
Dan Murphy Oct. 12, 2019, 12:50 a.m. UTC | #4
Jacek

On 10/11/19 3:36 PM, Jacek Anaszewski wrote:
> Dan,

>

> On 10/11/19 3:06 PM, Dan Murphy wrote:

>> Add multicolor framework support for the lp55xx family.

>>

>> Signed-off-by: Dan Murphy <dmurphy@ti.com>

>> ---

>>   drivers/leds/Kconfig                      |   1 +

>>   drivers/leds/leds-lp55xx-common.c         | 176 +++++++++++++++++++---

>>   drivers/leds/leds-lp55xx-common.h         |   9 ++

>>   include/linux/platform_data/leds-lp55xx.h |   7 +

>>   4 files changed, 169 insertions(+), 24 deletions(-)

>>

>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig

>> index fb614a6b9afa..5706bf8d8bd1 100644

>> --- a/drivers/leds/Kconfig

>> +++ b/drivers/leds/Kconfig

>> @@ -377,6 +377,7 @@ config LEDS_LP50XX

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

>> +	depends on OF

>>   	select FW_LOADER

>>   	select FW_LOADER_USER_HELPER

>>   	help

>> diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c

>> index 44ced02b49f9..1417df6df8a7 100644

>> --- a/drivers/leds/leds-lp55xx-common.c

>> +++ b/drivers/leds/leds-lp55xx-common.c

>> @@ -131,14 +131,54 @@ static struct attribute *lp55xx_led_attrs[] = {

>>   };

>>   ATTRIBUTE_GROUPS(lp55xx_led);

>>   

>> +static int lp55xx_map_channel(struct lp55xx_led *led, int color_id,

>> +			      enum led_brightness brightness)

>> +{

>> +	int i;

>> +

>> +	for (i = 0; i < led->mc_cdev.num_leds; i++) {

>> +		if (led->color_component[i].color_id == color_id) {

>> +			led->color_component[i].brightness = brightness;

>> +			return 0;

>> +		}

>> +	}

>> +

>> +	return -EINVAL;

>> +}

>> +

>>   static int lp55xx_set_brightness(struct led_classdev *cdev,

>>   			     enum led_brightness brightness)

>>   {

>> +	struct led_mc_color_conversion color_component[LP55XX_MAX_GROUPED_CHAN];

>>   	struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);

>>   	struct lp55xx_device_config *cfg = led->chip->cfg;

>> +	int ret;

>> +	int i;

>>   

>> -	led->brightness = (u8)brightness;

>> -	return cfg->brightness_fn(led);

>> +	if (led->mc_cdev.num_leds > 1) {

>> +		if (!cfg->color_intensity_fn)

>> +			return -EINVAL;

>> +

>> +		led_mc_calc_color_components(&led->mc_cdev, brightness,

>> +					     color_component);

>> +

>> +		for (i = 0; i < led->mc_cdev.num_leds; i++) {

>> +			ret = lp55xx_map_channel(led,

>> +						color_component[i].color_id,

>> +						color_component[i].brightness);

>> +			if (ret)

>> +				return ret;

>> +		}

>> +

>> +		ret = cfg->color_intensity_fn(led);

>> +		if (ret)

>> +			return ret;

>> +	} else {

>> +		led->brightness = (u8)brightness;

>> +		ret = cfg->brightness_fn(led);

>> +	}

>> +

>> +	return ret;

>>   }

>>   

>>   static int lp55xx_init_led(struct lp55xx_led *led,

>> @@ -147,9 +187,9 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>>   	struct lp55xx_platform_data *pdata = chip->pdata;

>>   	struct lp55xx_device_config *cfg = chip->cfg;

>>   	struct device *dev = &chip->cl->dev;

>> +	int max_channel = cfg->max_channel;

>>   	char name[32];

>>   	int ret;

>> -	int max_channel = cfg->max_channel;

>>   

>>   	if (chan >= max_channel) {

>>   		dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);

>> @@ -159,10 +199,34 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>>   	if (pdata->led_config[chan].led_current == 0)

>>   		return 0;

>>   

>> +	if (pdata->led_config[chan].name) {

>> +		led->cdev.name = pdata->led_config[chan].name;

>> +	} else {

>> +		snprintf(name, sizeof(name), "%s:channel%d",

>> +			pdata->label ? : chip->cl->name, chan);

>> +		led->cdev.name = name;

>> +	}

>> +

>> +	if (pdata->led_config[chan].num_colors > 1) {

>> +		led->mc_cdev.led_cdev = &led->cdev;

>> +		led->cdev.brightness_set_blocking = lp55xx_set_brightness;

>> +		led->cdev.groups = lp55xx_led_groups;

>> +		led->mc_cdev.num_leds = pdata->led_config[chan].num_colors;

>> +		led->mc_cdev.available_colors =

>> +			pdata->led_config[chan].available_colors;

>> +		memcpy(led->color_component,

>> +		       pdata->led_config[chan].color_component,

>> +		       sizeof(led->color_component));

>> +	} else {

>> +

>> +		led->cdev.default_trigger =

>> +			pdata->led_config[chan].default_trigger;

>> +		led->cdev.brightness_set_blocking = lp55xx_set_brightness;

>> +	}	led->cdev.groups = lp55xx_led_groups;

>> +

>>   	led->led_current = pdata->led_config[chan].led_current;

>>   	led->max_current = pdata->led_config[chan].max_current;

>>   	led->chan_nr = pdata->led_config[chan].chan_nr;

>> -	led->cdev.default_trigger = pdata->led_config[chan].default_trigger;

>>   

>>   	if (led->chan_nr >= max_channel) {

>>   		dev_err(dev, "Use channel numbers between 0 and %d\n",

>> @@ -170,18 +234,11 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>>   		return -EINVAL;

>>   	}

>>   

>> -	led->cdev.brightness_set_blocking = lp55xx_set_brightness;

>> -	led->cdev.groups = lp55xx_led_groups;

>> -

>> -	if (pdata->led_config[chan].name) {

>> -		led->cdev.name = pdata->led_config[chan].name;

>> -	} else {

>> -		snprintf(name, sizeof(name), "%s:channel%d",

>> -			pdata->label ? : chip->cl->name, chan);

>> -		led->cdev.name = name;

>> -	}

>> +	if (pdata->led_config[chan].num_colors > 1)

>> +		ret = led_classdev_multicolor_register(dev, &led->mc_cdev);

>> +	else

>> +		ret = led_classdev_register(dev, &led->cdev);

> Why not devm versions?


I will change the multicolor but not the led_classdev


>

>> -	ret = led_classdev_register(dev, &led->cdev);

>>   	if (ret) {

>>   		dev_err(dev, "led register err: %d\n", ret);

>>   		return ret;

>> @@ -466,7 +523,6 @@ int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)

>>   		dev_err(&chip->cl->dev, "empty brightness configuration\n");

>>   		return -EINVAL;

>>   	}

>> -

> This empty line removal was not intended I suppose.


I can put it back


>

>>   	for (i = 0; i < num_channels; i++) {

>>   

>>   		/* do not initialize channels that are not connected */

>> @@ -538,6 +594,82 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)

>>   }

>>   EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);

>>   

>> +static int lp5xx_parse_common_child(struct device_node *np,

>> +				    struct lp55xx_led_config *cfg,

>> +				    int chan_num, bool is_multicolor,

>> +				    int color_num)

>> +{

>> +	u32 led_number;

>> +	int ret;

>> +

>> +	of_property_read_string(np, "chan-name",

>> +				&cfg[chan_num].name);

>> +	of_property_read_u8(np, "led-cur",

>> +			    &cfg[chan_num].led_current);

>> +	of_property_read_u8(np, "max-cur",

>> +			    &cfg[chan_num].max_current);

>> +

>> +	ret = of_property_read_u32(np, "reg", &led_number);

>> +	if (ret)

>> +		return ret;

>> +

>> +	if (led_number < 0 || led_number > 6)

>> +		return -EINVAL;

>> +

>> +	if (is_multicolor)

>> +		cfg[chan_num].color_component[color_num].output_num =

>> +								led_number;

>> +	else

>> +		cfg[chan_num].chan_nr = led_number;

>> +

>> +	return 0;

>> +}

>> +

>> +static int lp5xx_parse_channel_child(struct device_node *np,

>> +				     struct lp55xx_led_config *cfg,

>> +				     int child_number)

>> +{

>> +	struct device_node *child;

>> +	int channel_color;

>> +	int num_colors = 0;

>> +	u32 color_id;

>> +	int ret;

>> +

>> +	cfg[child_number].default_trigger =

>> +			of_get_property(np, "linux,default-trigger", NULL);

>> +

>> +	ret = of_property_read_u32(np, "color", &channel_color);

>> +	if (ret)

>> +		channel_color = ret;

>> +

>> +

>> +	if (channel_color == LED_COLOR_ID_MULTI) {

>> +		for_each_child_of_node(np, child) {

>> +			ret = lp5xx_parse_common_child(child, cfg,

>> +						       child_number, true,

>> +						       num_colors);

>> +			if (ret)

>> +				return ret;

>> +

>> +			ret = of_property_read_u32(child, "color", &color_id);

>> +			if (ret)

>> +				return ret;

>> +

>> +			cfg[child_number].color_component[num_colors].color_id =

>> +						color_id;

>> +			set_bit(color_id, &cfg[child_number].available_colors);

>> +			num_colors++;

>> +		}

>> +

>> +		cfg[child_number].num_colors = num_colors;

>> +	} else {

>> +		return lp5xx_parse_common_child(np, cfg, child_number, false,

>> +						num_colors);

>> +	}

>> +

>> +	return 0;

>> +}

>> +

>>   struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,

>>   						      struct device_node *np)

>>   {

>> @@ -546,6 +678,7 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,

>>   	struct lp55xx_led_config *cfg;

>>   	int num_channels;

>>   	int i = 0;

>> +	int ret;

>>   

>>   	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);

>>   	if (!pdata)

>> @@ -565,14 +698,9 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,

>>   	pdata->num_channels = num_channels;

>>   

>>   	for_each_child_of_node(np, child) {

>> -		cfg[i].chan_nr = i;

>> -

>> -		of_property_read_string(child, "chan-name", &cfg[i].name);

>> -		of_property_read_u8(child, "led-cur", &cfg[i].led_current);

>> -		of_property_read_u8(child, "max-cur", &cfg[i].max_current);

>> -		cfg[i].default_trigger =

>> -			of_get_property(child, "linux,default-trigger", NULL);

>> -

>> +		ret = lp5xx_parse_channel_child(child, cfg, i);

>> +		if (ret)

>> +			return ERR_PTR(-EINVAL);

>>   		i++;

>>   	}

>>   

>> diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h

>> index 783ed5103ce5..75d57fb835c3 100644

>> --- a/drivers/leds/leds-lp55xx-common.h

>> +++ b/drivers/leds/leds-lp55xx-common.h

>> @@ -12,6 +12,8 @@

>>   #ifndef _LEDS_LP55XX_COMMON_H

>>   #define _LEDS_LP55XX_COMMON_H

>>   

>> +#include <linux/led-class-multicolor.h>

>> +

>>   enum lp55xx_engine_index {

>>   	LP55XX_ENGINE_INVALID,

>>   	LP55XX_ENGINE_1,

>> @@ -109,6 +111,9 @@ struct lp55xx_device_config {

>>   	/* access brightness register */

>>   	int (*brightness_fn)(struct lp55xx_led *led);

>>   

>> +	/* access specific brightness register */

>> +	int (*color_intensity_fn)(struct lp55xx_led *led);

> Wouldn't multicolor_brightness_fn be more accurate now ?


So just change the name to multicolor_brightness_fn?

Dan
Dan Murphy Oct. 12, 2019, 12:54 a.m. UTC | #5
Jacek

On 10/11/19 3:15 PM, Jacek Anaszewski wrote:
> Dan,

>

> On 10/11/19 3:06 PM, Dan Murphy wrote:

>> Update the DT binding to include the properties to use the

>> multicolor framework for the devices that use the LP55xx

>> framework.

>>

>> Signed-off-by: Dan Murphy <dmurphy@ti.com>

>> CC: Tony Lindgren <tony@atomide.com>

>> CC: "Benoît Cousson" <bcousson@baylibre.com>

>> CC: Linus Walleij <linus.walleij@linaro.org>

>> CC: Shawn Guo <shawnguo@kernel.org>

>> CC: Sascha Hauer <s.hauer@pengutronix.de>

>> CC: Pengutronix Kernel Team <kernel@pengutronix.de>

>> CC: Fabio Estevam <festevam@gmail.com>

>> CC: NXP Linux Team <linux-imx@nxp.com>

>> ---

>>   .../devicetree/bindings/leds/leds-lp55xx.txt  | 149 +++++++++++++++---

>>   1 file changed, 124 insertions(+), 25 deletions(-)

>>

>> diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>> index bfe2805c5534..736a2e1538be 100644

>> --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>> +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>> @@ -1,6 +1,8 @@

>>   Binding for TI/National Semiconductor LP55xx LED Drivers

>>   

>>   Required properties:

>> +- #address-cells: 1

>> +- #size-cells: 0

>>   - compatible: one of

>>   	national,lp5521

>>   	national,lp5523

>> @@ -14,6 +16,18 @@ Required properties:

>>   Each child has own specific current settings

>>   - led-cur: Current setting at each LED channel (mA x10, 0 if LED is not connected)

>>   - max-cur: Maximun current at each LED channel.

>> +- reg: Output channel for the LED.  This is zero based channel identifier and

>> +	the data sheet is a one based channel identifier.

>> +	reg value to output to LED output number

>> +	D1 = reg value is 0

>> +	D2 = reg value is 1

>> +	D3 = reg value is 2

>> +	D4 = reg value is 3

>> +	D5 = reg value is 4

>> +	D6 = reg value is 5

>> +	D7 = reg value is 6

>> +	D8 = reg value is 7

>> +	D9 = reg value is 8

>>   

>>   Optional properties:

>>   - enable-gpio: GPIO attached to the chip's enable pin

>> @@ -35,23 +49,28 @@ example 1) LP5521

>>   on channel 0.

>>   

>>   lp5521@32 {

> While at it let's fix node prefix to led-controller.

> It will not break anyone and yet it will adapt the node naming

> to what is now recommended.


I would love to do that but honestly I prefer to fix that in a different 
patch series and not add more changes to this patch review.


>

>> +	#address-cells = <1>;

>> +	#size-cells = <0>;

>>   	compatible = "national,lp5521";

>>   	reg = <0x32>;

>>   	label = "lp5521_pri";

>>   	clock-mode = /bits/ 8 <2>;

>>   

>> -	chan0 {

>> +	chan@0 {

> Similarly in case of every child node:

>

> s/chan/led/

>

>> +		reg = <0>;

>>   		led-cur = /bits/ 8 <0x2f>;

>>   		max-cur = /bits/ 8 <0x5f>;

>>   		linux,default-trigger = "heartbeat";

>>   	};

>>   

>> -	chan1 {

>> +	chan@1 {

>> +		reg = <1>;

>>   		led-cur = /bits/ 8 <0x2f>;

>>   		max-cur = /bits/ 8 <0x5f>;

>>   	};

>>   

>> -	chan2 {

>> +	chan@2 {

>> +		reg = <2>;

>>   		led-cur = /bits/ 8 <0x2f>;

>>   		max-cur = /bits/ 8 <0x5f>;

>>   	};

>> @@ -70,59 +89,70 @@ ASEL1    ASEL0    Address

>>    VEN      VEN       35h

>>   

>>   lp5523@32 {

> s/lp5523/led-controller/

>

>> +	#address-cells = <1>;

>> +	#size-cells = <0>;

>>   	compatible = "national,lp5523";

>>   	reg = <0x32>;

>>   	clock-mode = /bits/ 8 <1>;

>>   

>> -	chan0 {

>> +	chan@0 {

>> +		reg = <0>;

>>   		chan-name = "d1";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan1 {

>> +	chan@1 {

>> +		reg = <1>;

>>   		chan-name = "d2";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan2 {

>> +	chan@2 {

>> +		reg = <2>;

>>   		chan-name = "d3";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan3 {

>> +	chan@3 {

>> +		reg = <3>;

>>   		chan-name = "d4";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan4 {

>> +	chan@4 {

>> +		reg = <4>;

>>   		chan-name = "d5";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan5 {

>> +	chan@5 {

>> +		reg = <5>;

>>   		chan-name = "d6";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan6 {

>> +	chan@6 {

>> +		reg = <6>;

>>   		chan-name = "d7";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan7 {

>> +	chan@7 {

>> +		reg = <7>;

>>   		chan-name = "d8";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan8 {

>> +	chan@8 {

>> +		reg = <8>;

>>   		chan-name = "d9";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>> @@ -133,29 +163,35 @@ example 3) LP5562

>>   4 channels are defined.

>>   

>>   lp5562@30 {

> s/lp5562/led-controller/

>

>> +	#address-cells = <1>;

>> +	#size-cells = <0>;

>>   	compatible = "ti,lp5562";

>>   	reg = <0x30>;

>>   	clock-mode = /bits/8 <2>;

>>   

>> -	chan0 {

>> +	chan@0 {

>> +		reg = <0>;

>>   		chan-name = "R";

>>   		led-cur = /bits/ 8 <0x20>;

>>   		max-cur = /bits/ 8 <0x60>;

>>   	};

>>   

>> -	chan1 {

>> +	chan@1 {

>> +		reg = <1>;

>>   		chan-name = "G";

>>   		led-cur = /bits/ 8 <0x20>;

>>   		max-cur = /bits/ 8 <0x60>;

>>   	};

>>   

>> -	chan2 {

>> +	chan@2 {

>> +		reg = <2>;

>>   		chan-name = "B";

>>   		led-cur = /bits/ 8 <0x20>;

>>   		max-cur = /bits/ 8 <0x60>;

>>   	};

>>   

>> -	chan3 {

>> +	chan@3 {

>> +		reg = <3>;

>>   		chan-name = "W";

>>   		led-cur = /bits/ 8 <0x20>;

>>   		max-cur = /bits/ 8 <0x60>;

>> @@ -167,62 +203,125 @@ example 4) LP8501

>>   Others are same as LP5523.

>>   

>>   lp8501@32 {

> s/lp8501/led-controller/

>

>> +	#address-cells = <1>;

>> +	#size-cells = <0>;

>>   	compatible = "ti,lp8501";

>>   	reg = <0x32>;

>>   	clock-mode = /bits/ 8 <2>;

>>   	pwr-sel = /bits/ 8 <3>;	/* D1~9 connected to VOUT */

>>   

>> -	chan0 {

>> +	chan@0 {

>> +		reg = <0>;

>>   		chan-name = "d1";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan1 {

>> +	chan@1 {

>> +		reg = <1>;

>>   		chan-name = "d2";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan2 {

>> +	chan@2 {

>> +		reg = <2>;

>>   		chan-name = "d3";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan3 {

>> +	chan@3 {

>> +		reg = <3>;

>>   		chan-name = "d4";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan4 {

>> +	chan@4 {

>> +		reg = <4>;

>>   		chan-name = "d5";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan5 {

>> +	chan@5 {

>> +		reg = <5>;

>>   		chan-name = "d6";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan6 {

>> +	chan@6 {

>> +		reg = <6>;

>>   		chan-name = "d7";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan7 {

>> +	chan@7 {

>> +		reg = <7>;

>>   		chan-name = "d8";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   

>> -	chan8 {

>> +	chan@8 {

>> +		reg = <8>;

>>   		chan-name = "d9";

>>   		led-cur = /bits/ 8 <0x14>;

>>   		max-cur = /bits/ 8 <0x20>;

>>   	};

>>   };

>> +

>> +Multicolor Framework Support

>> +In addition to the nodes and properties defined above for device support the

>> +properties below are needed for multicolor framework support as defined in

>> +Documentation/devicetree/bindings/leds/leds-class-multicolor.txt

>> +

>> +Required child properties for multicolor framework

>> +	- color : Must be LED_COLOR_ID_MULTI

>> +	- function : see Documentation/devicetree/bindings/leds/common.txt

>> +

>> +Required grandchildren properties

>> +	- reg : This is the LED output of the device

>> +	- color : see Documentation/devicetree/bindings/leds/common.txt

>> +

>> +Multicolor LED example:

>> +lp5523: lp5523@32 {

> Do you really need "lp5523:" node label ?

>

> Besides:

>

> s/lp5523@32/led-controller@32/


This change I will make since I added this.

Dan
Jacek Anaszewski Oct. 12, 2019, 1:27 p.m. UTC | #6
Dan,

On 10/12/19 2:50 AM, Dan Murphy wrote:
> Jacek

> 

> On 10/11/19 3:36 PM, Jacek Anaszewski wrote:

>> Dan,

>>

>> On 10/11/19 3:06 PM, Dan Murphy wrote:

>>> Add multicolor framework support for the lp55xx family.

>>>

>>> Signed-off-by: Dan Murphy <dmurphy@ti.com>

>>> ---

>>>   drivers/leds/Kconfig                      |   1 +

>>>   drivers/leds/leds-lp55xx-common.c         | 176 +++++++++++++++++++---

>>>   drivers/leds/leds-lp55xx-common.h         |   9 ++

>>>   include/linux/platform_data/leds-lp55xx.h |   7 +

>>>   4 files changed, 169 insertions(+), 24 deletions(-)

>>>

>>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig

>>> index fb614a6b9afa..5706bf8d8bd1 100644

>>> --- a/drivers/leds/Kconfig

>>> +++ b/drivers/leds/Kconfig

>>> @@ -377,6 +377,7 @@ config LEDS_LP50XX

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

>>> +    depends on OF

>>>       select FW_LOADER

>>>       select FW_LOADER_USER_HELPER

>>>       help

>>> diff --git a/drivers/leds/leds-lp55xx-common.c

>>> b/drivers/leds/leds-lp55xx-common.c

>>> index 44ced02b49f9..1417df6df8a7 100644

>>> --- a/drivers/leds/leds-lp55xx-common.c

>>> +++ b/drivers/leds/leds-lp55xx-common.c

>>> @@ -131,14 +131,54 @@ static struct attribute *lp55xx_led_attrs[] = {

>>>   };

>>>   ATTRIBUTE_GROUPS(lp55xx_led);

>>>   +static int lp55xx_map_channel(struct lp55xx_led *led, int color_id,

>>> +                  enum led_brightness brightness)

>>> +{

>>> +    int i;

>>> +

>>> +    for (i = 0; i < led->mc_cdev.num_leds; i++) {

>>> +        if (led->color_component[i].color_id == color_id) {

>>> +            led->color_component[i].brightness = brightness;

>>> +            return 0;

>>> +        }

>>> +    }

>>> +

>>> +    return -EINVAL;

>>> +}

>>> +

>>>   static int lp55xx_set_brightness(struct led_classdev *cdev,

>>>                    enum led_brightness brightness)

>>>   {

>>> +    struct led_mc_color_conversion

>>> color_component[LP55XX_MAX_GROUPED_CHAN];

>>>       struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);

>>>       struct lp55xx_device_config *cfg = led->chip->cfg;

>>> +    int ret;

>>> +    int i;

>>>   -    led->brightness = (u8)brightness;

>>> -    return cfg->brightness_fn(led);

>>> +    if (led->mc_cdev.num_leds > 1) {

>>> +        if (!cfg->color_intensity_fn)

>>> +            return -EINVAL;

>>> +

>>> +        led_mc_calc_color_components(&led->mc_cdev, brightness,

>>> +                         color_component);

>>> +

>>> +        for (i = 0; i < led->mc_cdev.num_leds; i++) {

>>> +            ret = lp55xx_map_channel(led,

>>> +                        color_component[i].color_id,

>>> +                        color_component[i].brightness);

>>> +            if (ret)

>>> +                return ret;

>>> +        }

>>> +

>>> +        ret = cfg->color_intensity_fn(led);

>>> +        if (ret)

>>> +            return ret;

>>> +    } else {

>>> +        led->brightness = (u8)brightness;

>>> +        ret = cfg->brightness_fn(led);

>>> +    }

>>> +

>>> +    return ret;

>>>   }

>>>     static int lp55xx_init_led(struct lp55xx_led *led,

>>> @@ -147,9 +187,9 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>>>       struct lp55xx_platform_data *pdata = chip->pdata;

>>>       struct lp55xx_device_config *cfg = chip->cfg;

>>>       struct device *dev = &chip->cl->dev;

>>> +    int max_channel = cfg->max_channel;

>>>       char name[32];

>>>       int ret;

>>> -    int max_channel = cfg->max_channel;

>>>         if (chan >= max_channel) {

>>>           dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);

>>> @@ -159,10 +199,34 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>>>       if (pdata->led_config[chan].led_current == 0)

>>>           return 0;

>>>   +    if (pdata->led_config[chan].name) {

>>> +        led->cdev.name = pdata->led_config[chan].name;

>>> +    } else {

>>> +        snprintf(name, sizeof(name), "%s:channel%d",

>>> +            pdata->label ? : chip->cl->name, chan);

>>> +        led->cdev.name = name;

>>> +    }

>>> +

>>> +    if (pdata->led_config[chan].num_colors > 1) {

>>> +        led->mc_cdev.led_cdev = &led->cdev;

>>> +        led->cdev.brightness_set_blocking = lp55xx_set_brightness;

>>> +        led->cdev.groups = lp55xx_led_groups;

>>> +        led->mc_cdev.num_leds = pdata->led_config[chan].num_colors;

>>> +        led->mc_cdev.available_colors =

>>> +            pdata->led_config[chan].available_colors;

>>> +        memcpy(led->color_component,

>>> +               pdata->led_config[chan].color_component,

>>> +               sizeof(led->color_component));

>>> +    } else {

>>> +

>>> +        led->cdev.default_trigger =

>>> +            pdata->led_config[chan].default_trigger;

>>> +        led->cdev.brightness_set_blocking = lp55xx_set_brightness;

>>> +    }    led->cdev.groups = lp55xx_led_groups;

>>> +

>>>       led->led_current = pdata->led_config[chan].led_current;

>>>       led->max_current = pdata->led_config[chan].max_current;

>>>       led->chan_nr = pdata->led_config[chan].chan_nr;

>>> -    led->cdev.default_trigger =

>>> pdata->led_config[chan].default_trigger;

>>>         if (led->chan_nr >= max_channel) {

>>>           dev_err(dev, "Use channel numbers between 0 and %d\n",

>>> @@ -170,18 +234,11 @@ static int lp55xx_init_led(struct lp55xx_led *led,

>>>           return -EINVAL;

>>>       }

>>>   -    led->cdev.brightness_set_blocking = lp55xx_set_brightness;

>>> -    led->cdev.groups = lp55xx_led_groups;

>>> -

>>> -    if (pdata->led_config[chan].name) {

>>> -        led->cdev.name = pdata->led_config[chan].name;

>>> -    } else {

>>> -        snprintf(name, sizeof(name), "%s:channel%d",

>>> -            pdata->label ? : chip->cl->name, chan);

>>> -        led->cdev.name = name;

>>> -    }

>>> +    if (pdata->led_config[chan].num_colors > 1)

>>> +        ret = led_classdev_multicolor_register(dev, &led->mc_cdev);

>>> +    else

>>> +        ret = led_classdev_register(dev, &led->cdev);

>> Why not devm versions?

> 

> I will change the multicolor but not the led_classdev


Having one devm and the other not will look awkward.
This does not seem to be a big effort. I propose to add a preceding
patch that will first switch monochrome led_classdev_register to devm,
and of course clean up error paths (remove lp55xx_unregister_leds()),
and update error paths in all callers which will be just removing
the calls to lp55xx_unregister_leds().

>>

>>> -    ret = led_classdev_register(dev, &led->cdev);

>>>       if (ret) {

>>>           dev_err(dev, "led register err: %d\n", ret);

>>>           return ret;

>>> @@ -466,7 +523,6 @@ int lp55xx_register_leds(struct lp55xx_led *led,

>>> struct lp55xx_chip *chip)

>>>           dev_err(&chip->cl->dev, "empty brightness configuration\n");

>>>           return -EINVAL;

>>>       }

>>> -

>> This empty line removal was not intended I suppose.

> 

> I can put it back

> 

> 

>>

>>>       for (i = 0; i < num_channels; i++) {

>>>             /* do not initialize channels that are not connected */

>>> @@ -538,6 +594,82 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip

>>> *chip)

>>>   }

>>>   EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);

>>>   +static int lp5xx_parse_common_child(struct device_node *np,

>>> +                    struct lp55xx_led_config *cfg,

>>> +                    int chan_num, bool is_multicolor,

>>> +                    int color_num)

>>> +{

>>> +    u32 led_number;

>>> +    int ret;

>>> +

>>> +    of_property_read_string(np, "chan-name",

>>> +                &cfg[chan_num].name);

>>> +    of_property_read_u8(np, "led-cur",

>>> +                &cfg[chan_num].led_current);

>>> +    of_property_read_u8(np, "max-cur",

>>> +                &cfg[chan_num].max_current);

>>> +

>>> +    ret = of_property_read_u32(np, "reg", &led_number);

>>> +    if (ret)

>>> +        return ret;

>>> +

>>> +    if (led_number < 0 || led_number > 6)

>>> +        return -EINVAL;

>>> +

>>> +    if (is_multicolor)

>>> +        cfg[chan_num].color_component[color_num].output_num =

>>> +                                led_number;

>>> +    else

>>> +        cfg[chan_num].chan_nr = led_number;

>>> +

>>> +    return 0;

>>> +}

>>> +

>>> +static int lp5xx_parse_channel_child(struct device_node *np,

>>> +                     struct lp55xx_led_config *cfg,

>>> +                     int child_number)

>>> +{

>>> +    struct device_node *child;

>>> +    int channel_color;

>>> +    int num_colors = 0;

>>> +    u32 color_id;

>>> +    int ret;

>>> +

>>> +    cfg[child_number].default_trigger =

>>> +            of_get_property(np, "linux,default-trigger", NULL);

>>> +

>>> +    ret = of_property_read_u32(np, "color", &channel_color);

>>> +    if (ret)

>>> +        channel_color = ret;

>>> +

>>> +

>>> +    if (channel_color == LED_COLOR_ID_MULTI) {

>>> +        for_each_child_of_node(np, child) {

>>> +            ret = lp5xx_parse_common_child(child, cfg,

>>> +                               child_number, true,

>>> +                               num_colors);

>>> +            if (ret)

>>> +                return ret;

>>> +

>>> +            ret = of_property_read_u32(child, "color", &color_id);

>>> +            if (ret)

>>> +                return ret;

>>> +

>>> +            cfg[child_number].color_component[num_colors].color_id =

>>> +                        color_id;

>>> +            set_bit(color_id, &cfg[child_number].available_colors);

>>> +            num_colors++;

>>> +        }

>>> +

>>> +        cfg[child_number].num_colors = num_colors;

>>> +    } else {

>>> +        return lp5xx_parse_common_child(np, cfg, child_number, false,

>>> +                        num_colors);

>>> +    }

>>> +

>>> +    return 0;

>>> +}

>>> +

>>>   struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device

>>> *dev,

>>>                                 struct device_node *np)

>>>   {

>>> @@ -546,6 +678,7 @@ struct lp55xx_platform_data

>>> *lp55xx_of_populate_pdata(struct device *dev,

>>>       struct lp55xx_led_config *cfg;

>>>       int num_channels;

>>>       int i = 0;

>>> +    int ret;

>>>         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);

>>>       if (!pdata)

>>> @@ -565,14 +698,9 @@ struct lp55xx_platform_data

>>> *lp55xx_of_populate_pdata(struct device *dev,

>>>       pdata->num_channels = num_channels;

>>>         for_each_child_of_node(np, child) {

>>> -        cfg[i].chan_nr = i;

>>> -

>>> -        of_property_read_string(child, "chan-name", &cfg[i].name);

>>> -        of_property_read_u8(child, "led-cur", &cfg[i].led_current);

>>> -        of_property_read_u8(child, "max-cur", &cfg[i].max_current);

>>> -        cfg[i].default_trigger =

>>> -            of_get_property(child, "linux,default-trigger", NULL);

>>> -

>>> +        ret = lp5xx_parse_channel_child(child, cfg, i);

>>> +        if (ret)

>>> +            return ERR_PTR(-EINVAL);

>>>           i++;

>>>       }

>>>   diff --git a/drivers/leds/leds-lp55xx-common.h

>>> b/drivers/leds/leds-lp55xx-common.h

>>> index 783ed5103ce5..75d57fb835c3 100644

>>> --- a/drivers/leds/leds-lp55xx-common.h

>>> +++ b/drivers/leds/leds-lp55xx-common.h

>>> @@ -12,6 +12,8 @@

>>>   #ifndef _LEDS_LP55XX_COMMON_H

>>>   #define _LEDS_LP55XX_COMMON_H

>>>   +#include <linux/led-class-multicolor.h>

>>> +

>>>   enum lp55xx_engine_index {

>>>       LP55XX_ENGINE_INVALID,

>>>       LP55XX_ENGINE_1,

>>> @@ -109,6 +111,9 @@ struct lp55xx_device_config {

>>>       /* access brightness register */

>>>       int (*brightness_fn)(struct lp55xx_led *led);

>>>   +    /* access specific brightness register */

>>> +    int (*color_intensity_fn)(struct lp55xx_led *led);

>> Wouldn't multicolor_brightness_fn be more accurate now ?

> 

> So just change the name to multicolor_brightness_fn?


And the op implementations in the clients, like:

s/lp5521_led_intensity/lp5521_led_mc_brightness/

-- 
Best regards,
Jacek Anaszewski
Jacek Anaszewski Oct. 12, 2019, 1:32 p.m. UTC | #7
Dan,

On 10/12/19 2:54 AM, Dan Murphy wrote:
> Jacek

> 

> On 10/11/19 3:15 PM, Jacek Anaszewski wrote:

>> Dan,

>>

>> On 10/11/19 3:06 PM, Dan Murphy wrote:

>>> Update the DT binding to include the properties to use the

>>> multicolor framework for the devices that use the LP55xx

>>> framework.

>>>

>>> Signed-off-by: Dan Murphy <dmurphy@ti.com>

>>> CC: Tony Lindgren <tony@atomide.com>

>>> CC: "Benoît Cousson" <bcousson@baylibre.com>

>>> CC: Linus Walleij <linus.walleij@linaro.org>

>>> CC: Shawn Guo <shawnguo@kernel.org>

>>> CC: Sascha Hauer <s.hauer@pengutronix.de>

>>> CC: Pengutronix Kernel Team <kernel@pengutronix.de>

>>> CC: Fabio Estevam <festevam@gmail.com>

>>> CC: NXP Linux Team <linux-imx@nxp.com>

>>> ---

>>>   .../devicetree/bindings/leds/leds-lp55xx.txt  | 149 +++++++++++++++---

>>>   1 file changed, 124 insertions(+), 25 deletions(-)

>>>

>>> diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>>> b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>>> index bfe2805c5534..736a2e1538be 100644

>>> --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>>> +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt

>>> @@ -1,6 +1,8 @@

>>>   Binding for TI/National Semiconductor LP55xx LED Drivers

>>>     Required properties:

>>> +- #address-cells: 1

>>> +- #size-cells: 0

>>>   - compatible: one of

>>>       national,lp5521

>>>       national,lp5523

>>> @@ -14,6 +16,18 @@ Required properties:

>>>   Each child has own specific current settings

>>>   - led-cur: Current setting at each LED channel (mA x10, 0 if LED is

>>> not connected)

>>>   - max-cur: Maximun current at each LED channel.

>>> +- reg: Output channel for the LED.  This is zero based channel

>>> identifier and

>>> +    the data sheet is a one based channel identifier.

>>> +    reg value to output to LED output number

>>> +    D1 = reg value is 0

>>> +    D2 = reg value is 1

>>> +    D3 = reg value is 2

>>> +    D4 = reg value is 3

>>> +    D5 = reg value is 4

>>> +    D6 = reg value is 5

>>> +    D7 = reg value is 6

>>> +    D8 = reg value is 7

>>> +    D9 = reg value is 8

>>>     Optional properties:

>>>   - enable-gpio: GPIO attached to the chip's enable pin

>>> @@ -35,23 +49,28 @@ example 1) LP5521

>>>   on channel 0.

>>>     lp5521@32 {

>> While at it let's fix node prefix to led-controller.

>> It will not break anyone and yet it will adapt the node naming

>> to what is now recommended.

> 

> I would love to do that but honestly I prefer to fix that in a different

> patch series and not add more changes to this patch review.


ack

>>> +    #address-cells = <1>;

>>> +    #size-cells = <0>;

>>>       compatible = "national,lp5521";

>>>       reg = <0x32>;

>>>       label = "lp5521_pri";

>>>       clock-mode = /bits/ 8 <2>;

>>>   -    chan0 {

>>> +    chan@0 {

>> Similarly in case of every child node:

>>


>>> +Multicolor LED example:

>>> +lp5523: lp5523@32 {

>> Do you really need "lp5523:" node label ?

>>

>> Besides:

>>

>> s/lp5523@32/led-controller@32/

> 

> This change I will make since I added this.


Good, it was the first thing that struck me - if we're
adding new bindings they should conform to the current
standards.

-- 
Best regards,
Jacek Anaszewski