All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
@ 2019-03-21 14:28 ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Add the lm3532 device tree documentation.
Remove lm3532 device tree reference from the ti_lmu devicetree
documentation.

With the addition of the dedicated lm3532 documentation the device
can be removed from the ti_lmu.txt.

The reason for this is that the lm3532 dt documentation now defines
the ability to control LED output strings against different control
banks or groups multiple strings to be controlled by a single control
bank.

Another addition was for ALS lighting control and configuration.  The
LM3532 has a feature that can take in the ALS reading from 2 separate
ALS devices and adjust the brightness on the strings that are configured
to support this feature.

Finally the device specific properties were moved to the parent node as these
properties are not control bank configurable.  These include the runtime ramp
and the ALS configuration.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Dan Murphy <dmurphy@ti.com>
---

v5 - Moved ramping range to below property definition, updated keyboard label -
https://lore.kernel.org/patchwork/patch/1050412/

v4 - Appended "ti," to TI specific properties, add enable gpio documentation,
removed an example, moved ramp to optional parent properties - https://lore.kernel.org/patchwork/patch/1050122/
v3 - No changes - https://lore.kernel.org/patchwork/patch/1049026/
v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
added ranges for variable properties, I did not change the label - https://lore.kernel.org/patchwork/patch/1048805/

 .../devicetree/bindings/leds/leds-lm3532.txt  | 101 ++++++++++++++++++
 .../devicetree/bindings/mfd/ti-lmu.txt        |  20 ----
 2 files changed, 101 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-lm3532.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-lm3532.txt b/Documentation/devicetree/bindings/leds/leds-lm3532.txt
new file mode 100644
index 000000000000..5bd0c025850f
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lm3532.txt
@@ -0,0 +1,101 @@
+* Texas Instruments - lm3532 White LED driver with ambient light sensing
+capability.
+
+The LM3532 provides the 3 high-voltage, low-side current sinks. The device is
+programmable over an I2C-compatible interface and has independent
+current control for all three channels. The adaptive current regulation
+method allows for different LED currents in each current sink thus allowing
+for a wide variety of backlight and keypad applications.
+
+The main features of the LM3532 include dual ambient light sensor inputs
+each with 32 internal voltage setting resistors, 8-bit logarithmic and linear
+brightness control, dual external PWM brightness control inputs, and up to
+1000:1 dimming ratio with programmable fade in and fade out settings.
+
+Required properties:
+	- compatible : "ti,lm3532"
+	- reg : I2C slave address
+	- #address-cells : 1
+	- #size-cells : 0
+
+Optional properties:
+	- enable-gpios : gpio pin to enable (active high)/disable the device.
+	- ramp-up-us - The Run time ramp rates/step are from one current
+		       set-point to another after the device has reached its
+		       initial target set point from turn-on
+	- ramp-down-us - The Run time ramp rates/step are from one current
+			 set-point to another after the device has reached its
+			 initial target set point from turn-on
+	Range for ramp settings: 8us - 65536us
+
+Optional properties if ALS mode is used:
+	- ti,als-vmin - Minimum ALS voltage defined in Volts
+	- ti,als-vmax - Maximum ALS voltage defined in Volts
+	Per the data sheet the max ALS voltage is 2V and the min is 0V
+
+	- ti,als1-imp-sel - ALS1 impedance resistor selection in Ohms
+	- ti,als2-imp-sel - ALS2 impedance resistor selection in Ohms
+	Range for impedance select: 37000 Ohms - 1190 Ohms
+	Values above 37kohms will be set to the "High Impedance" setting
+
+	- ti,als-avrg-time-us - Determines the length of time the device needs to
+			  average the two ALS inputs.  This is only used if
+			  the input mode is LM3532_ALS_INPUT_AVRG.
+			     Range: 17920us - 2293760us
+	- ti,als-input-mode - Determines how the device uses the attached ALS
+			   devices.
+			   0x00 - ALS1 and ALS2 input average
+			   0x01 - ALS1 Input
+			   0x02 - ALS2 Input
+			   0x03 - Max of ALS1 and ALS2
+
+Required child properties:
+	- reg : Indicates control bank the LED string is controlled by
+	- led-sources : see Documentation/devicetree/bindings/leds/common.txt
+	- ti,led-mode : Defines if the LED strings are manually controlled or
+			if the LED strings are controlled by the ALS.
+			0x00 - LED strings are I2C controlled via full scale
+			       brightness control register
+			0x01 - LED strings are ALS controlled
+
+Optional LED child properties:
+	- label : see Documentation/devicetree/bindings/leds/common.txt
+	- linux,default-trigger :
+	   see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+led-controller@38 {
+	compatible = "ti,lm3532";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x38>;
+
+	enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+	ramp-up-us = <1024>;
+	ramp-down-us = <65536>;
+
+	ti,als-vmin = <0>;
+	ti,als-vmax = <2000>;
+	ti,als1-imp-sel = <4110>;
+	ti,als2-imp-sel = <2180>;
+	ti,als-avrg-time-us = <17920>;
+	ti,als-input-mode = <0x00>;
+
+	lcd_backlight: led@0 {
+		reg = <0>;
+		led-sources = <2>;
+		ti,led-mode = <1>;
+		label = "backlight";
+		linux,default-trigger = "backlight";
+	};
+
+	led@1 {
+		reg = <1>;
+		led-sources = <1>;
+		ti,led-mode = <0>;
+		label = "platform::kbd_backlight";
+	};
+};
+
+For more product information please see the links below:
+http://www.ti.com/product/LM3532
diff --git a/Documentation/devicetree/bindings/mfd/ti-lmu.txt b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
index c885cf89b8ce..980394d701a7 100644
--- a/Documentation/devicetree/bindings/mfd/ti-lmu.txt
+++ b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
@@ -4,7 +4,6 @@ TI LMU driver supports lighting devices below.
 
    Name                  Child nodes
   ------      ---------------------------------
-  LM3532       Backlight
   LM3631       Backlight and regulator
   LM3632       Backlight and regulator
   LM3633       Backlight, LED and fault monitor
@@ -13,7 +12,6 @@ TI LMU driver supports lighting devices below.
 
 Required properties:
   - compatible: Should be one of:
-                "ti,lm3532"
                 "ti,lm3631"
                 "ti,lm3632"
                 "ti,lm3633"
@@ -23,7 +21,6 @@ Required properties:
          0x11 for LM3632
          0x29 for LM3631
          0x36 for LM3633, LM3697
-         0x38 for LM3532
          0x63 for LM3695
 
 Optional property:
@@ -47,23 +44,6 @@ Optional nodes:
 [2] ../leds/leds-lm3633.txt
 [3] ../regulator/lm363x-regulator.txt
 
-lm3532@38 {
-	compatible = "ti,lm3532";
-	reg = <0x38>;
-
-	enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>;
-
-	backlight {
-		compatible = "ti,lm3532-backlight";
-
-		lcd {
-			led-sources = <0 1 2>;
-			ramp-up-msec = <30>;
-			ramp-down-msec = <0>;
-		};
-	};
-};
-
 lm3631@29 {
 	compatible = "ti,lm3631";
 	reg = <0x29>;
-- 
2.21.0.5.gaeb582a983

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

* [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
@ 2019-03-21 14:28 ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Add the lm3532 device tree documentation.
Remove lm3532 device tree reference from the ti_lmu devicetree
documentation.

With the addition of the dedicated lm3532 documentation the device
can be removed from the ti_lmu.txt.

The reason for this is that the lm3532 dt documentation now defines
the ability to control LED output strings against different control
banks or groups multiple strings to be controlled by a single control
bank.

Another addition was for ALS lighting control and configuration.  The
LM3532 has a feature that can take in the ALS reading from 2 separate
ALS devices and adjust the brightness on the strings that are configured
to support this feature.

Finally the device specific properties were moved to the parent node as these
properties are not control bank configurable.  These include the runtime ramp
and the ALS configuration.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Dan Murphy <dmurphy@ti.com>
---

v5 - Moved ramping range to below property definition, updated keyboard label -
https://lore.kernel.org/patchwork/patch/1050412/

v4 - Appended "ti," to TI specific properties, add enable gpio documentation,
removed an example, moved ramp to optional parent properties - https://lore.kernel.org/patchwork/patch/1050122/
v3 - No changes - https://lore.kernel.org/patchwork/patch/1049026/
v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
added ranges for variable properties, I did not change the label - https://lore.kernel.org/patchwork/patch/1048805/

 .../devicetree/bindings/leds/leds-lm3532.txt  | 101 ++++++++++++++++++
 .../devicetree/bindings/mfd/ti-lmu.txt        |  20 ----
 2 files changed, 101 insertions(+), 20 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/leds/leds-lm3532.txt

diff --git a/Documentation/devicetree/bindings/leds/leds-lm3532.txt b/Documentation/devicetree/bindings/leds/leds-lm3532.txt
new file mode 100644
index 000000000000..5bd0c025850f
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-lm3532.txt
@@ -0,0 +1,101 @@
+* Texas Instruments - lm3532 White LED driver with ambient light sensing
+capability.
+
+The LM3532 provides the 3 high-voltage, low-side current sinks. The device is
+programmable over an I2C-compatible interface and has independent
+current control for all three channels. The adaptive current regulation
+method allows for different LED currents in each current sink thus allowing
+for a wide variety of backlight and keypad applications.
+
+The main features of the LM3532 include dual ambient light sensor inputs
+each with 32 internal voltage setting resistors, 8-bit logarithmic and linear
+brightness control, dual external PWM brightness control inputs, and up to
+1000:1 dimming ratio with programmable fade in and fade out settings.
+
+Required properties:
+	- compatible : "ti,lm3532"
+	- reg : I2C slave address
+	- #address-cells : 1
+	- #size-cells : 0
+
+Optional properties:
+	- enable-gpios : gpio pin to enable (active high)/disable the device.
+	- ramp-up-us - The Run time ramp rates/step are from one current
+		       set-point to another after the device has reached its
+		       initial target set point from turn-on
+	- ramp-down-us - The Run time ramp rates/step are from one current
+			 set-point to another after the device has reached its
+			 initial target set point from turn-on
+	Range for ramp settings: 8us - 65536us
+
+Optional properties if ALS mode is used:
+	- ti,als-vmin - Minimum ALS voltage defined in Volts
+	- ti,als-vmax - Maximum ALS voltage defined in Volts
+	Per the data sheet the max ALS voltage is 2V and the min is 0V
+
+	- ti,als1-imp-sel - ALS1 impedance resistor selection in Ohms
+	- ti,als2-imp-sel - ALS2 impedance resistor selection in Ohms
+	Range for impedance select: 37000 Ohms - 1190 Ohms
+	Values above 37kohms will be set to the "High Impedance" setting
+
+	- ti,als-avrg-time-us - Determines the length of time the device needs to
+			  average the two ALS inputs.  This is only used if
+			  the input mode is LM3532_ALS_INPUT_AVRG.
+			     Range: 17920us - 2293760us
+	- ti,als-input-mode - Determines how the device uses the attached ALS
+			   devices.
+			   0x00 - ALS1 and ALS2 input average
+			   0x01 - ALS1 Input
+			   0x02 - ALS2 Input
+			   0x03 - Max of ALS1 and ALS2
+
+Required child properties:
+	- reg : Indicates control bank the LED string is controlled by
+	- led-sources : see Documentation/devicetree/bindings/leds/common.txt
+	- ti,led-mode : Defines if the LED strings are manually controlled or
+			if the LED strings are controlled by the ALS.
+			0x00 - LED strings are I2C controlled via full scale
+			       brightness control register
+			0x01 - LED strings are ALS controlled
+
+Optional LED child properties:
+	- label : see Documentation/devicetree/bindings/leds/common.txt
+	- linux,default-trigger :
+	   see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+led-controller@38 {
+	compatible = "ti,lm3532";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x38>;
+
+	enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+	ramp-up-us = <1024>;
+	ramp-down-us = <65536>;
+
+	ti,als-vmin = <0>;
+	ti,als-vmax = <2000>;
+	ti,als1-imp-sel = <4110>;
+	ti,als2-imp-sel = <2180>;
+	ti,als-avrg-time-us = <17920>;
+	ti,als-input-mode = <0x00>;
+
+	lcd_backlight: led@0 {
+		reg = <0>;
+		led-sources = <2>;
+		ti,led-mode = <1>;
+		label = "backlight";
+		linux,default-trigger = "backlight";
+	};
+
+	led@1 {
+		reg = <1>;
+		led-sources = <1>;
+		ti,led-mode = <0>;
+		label = "platform::kbd_backlight";
+	};
+};
+
+For more product information please see the links below:
+http://www.ti.com/product/LM3532
diff --git a/Documentation/devicetree/bindings/mfd/ti-lmu.txt b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
index c885cf89b8ce..980394d701a7 100644
--- a/Documentation/devicetree/bindings/mfd/ti-lmu.txt
+++ b/Documentation/devicetree/bindings/mfd/ti-lmu.txt
@@ -4,7 +4,6 @@ TI LMU driver supports lighting devices below.
 
    Name                  Child nodes
   ------      ---------------------------------
-  LM3532       Backlight
   LM3631       Backlight and regulator
   LM3632       Backlight and regulator
   LM3633       Backlight, LED and fault monitor
@@ -13,7 +12,6 @@ TI LMU driver supports lighting devices below.
 
 Required properties:
   - compatible: Should be one of:
-                "ti,lm3532"
                 "ti,lm3631"
                 "ti,lm3632"
                 "ti,lm3633"
@@ -23,7 +21,6 @@ Required properties:
          0x11 for LM3632
          0x29 for LM3631
          0x36 for LM3633, LM3697
-         0x38 for LM3532
          0x63 for LM3695
 
 Optional property:
@@ -47,23 +44,6 @@ Optional nodes:
 [2] ../leds/leds-lm3633.txt
 [3] ../regulator/lm363x-regulator.txt
 
-lm3532@38 {
-	compatible = "ti,lm3532";
-	reg = <0x38>;
-
-	enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>;
-
-	backlight {
-		compatible = "ti,lm3532-backlight";
-
-		lcd {
-			led-sources = <0 1 2>;
-			ramp-up-msec = <30>;
-			ramp-down-msec = <0>;
-		};
-	};
-};
-
 lm3631@29 {
 	compatible = "ti,lm3631";
 	reg = <0x29>;
-- 
2.21.0.5.gaeb582a983


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

* [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties
  2019-03-21 14:28 ` Dan Murphy
@ 2019-03-21 14:28   ` Dan Murphy
  -1 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Update the properties for the lm3532 device node for droid4.
With this change the backlight LED string and the keypad
LED strings will be controlled separately.

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

v5 - No change - https://lore.kernel.org/patchwork/patch/1050409/

v4 - No change - https://lore.kernel.org/patchwork/patch/1050125/
v3 - updated keypad label on v1 comment - https://lore.kernel.org/patchwork/patch/1049023/
v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
I did not change the label as it is undecided what it could be - https://lore.kernel.org/patchwork/patch/1048806/

 arch/arm/boot/dts/omap4-droid4-xt894.dts | 26 ++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
index e21ec929f096..aea206f04f76 100644
--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
+++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
@@ -383,20 +383,30 @@
 };
 
 &i2c1 {
-	lm3532@38 {
+	led-controller@38 {
 		compatible = "ti,lm3532";
+		#address-cells = <1>;
+		#size-cells = <0>;
 		reg = <0x38>;
 
 		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
 
-		lcd_backlight: backlight {
-			compatible = "ti,lm3532-backlight";
+		ramp-up-us = <1024>;
+		ramp-down-us = <8193>;
 
-			lcd {
-				led-sources = <0 1 2>;
-				ramp-up-msec = <1>;
-				ramp-down-msec = <0>;
-			};
+		lcd_backlight: led@0 {
+			reg = <0>;
+			led-sources = <2>;
+			ti,led-mode = <0>;
+			label = "backlight";
+			linux,default-trigger = "backlight";
+		};
+
+		led@1 {
+			reg = <1>;
+			led-sources = <1>;
+			ti,led-mode = <0>;
+			label = "platform::kbd_backlight";
 		};
 	};
 };
-- 
2.21.0.5.gaeb582a983

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

* [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties
@ 2019-03-21 14:28   ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Update the properties for the lm3532 device node for droid4.
With this change the backlight LED string and the keypad
LED strings will be controlled separately.

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

v5 - No change - https://lore.kernel.org/patchwork/patch/1050409/

v4 - No change - https://lore.kernel.org/patchwork/patch/1050125/
v3 - updated keypad label on v1 comment - https://lore.kernel.org/patchwork/patch/1049023/
v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
I did not change the label as it is undecided what it could be - https://lore.kernel.org/patchwork/patch/1048806/

 arch/arm/boot/dts/omap4-droid4-xt894.dts | 26 ++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
index e21ec929f096..aea206f04f76 100644
--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
+++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
@@ -383,20 +383,30 @@
 };
 
 &i2c1 {
-	lm3532@38 {
+	led-controller@38 {
 		compatible = "ti,lm3532";
+		#address-cells = <1>;
+		#size-cells = <0>;
 		reg = <0x38>;
 
 		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
 
-		lcd_backlight: backlight {
-			compatible = "ti,lm3532-backlight";
+		ramp-up-us = <1024>;
+		ramp-down-us = <8193>;
 
-			lcd {
-				led-sources = <0 1 2>;
-				ramp-up-msec = <1>;
-				ramp-down-msec = <0>;
-			};
+		lcd_backlight: led@0 {
+			reg = <0>;
+			led-sources = <2>;
+			ti,led-mode = <0>;
+			label = "backlight";
+			linux,default-trigger = "backlight";
+		};
+
+		led@1 {
+			reg = <1>;
+			led-sources = <1>;
+			ti,led-mode = <0>;
+			label = "platform::kbd_backlight";
 		};
 	};
 };
-- 
2.21.0.5.gaeb582a983


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

* [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-03-21 14:28 ` Dan Murphy
@ 2019-03-21 14:28   ` Dan Murphy
  -1 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Remove the LM3532 backlight driver references from the ti-lmu
code as dedicated driver support is available.

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

v5 - No changes - https://lore.kernel.org/patchwork/patch/1050411/

v4 - No changes - https://lore.kernel.org/patchwork/patch/1050123/
v3 - No changes - https://lore.kernel.org/patchwork/patch/1049025/
v2 - Removed LM3532 register definitions from ti-lmu-register - https://lore.kernel.org/patchwork/patch/1048808/

 drivers/mfd/ti-lmu.c                | 11 --------
 include/linux/mfd/ti-lmu-register.h | 44 -----------------------------
 include/linux/mfd/ti-lmu.h          |  1 -
 3 files changed, 56 deletions(-)

diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c
index 37d0bdb291c3..b06cb908d1aa 100644
--- a/drivers/mfd/ti-lmu.c
+++ b/drivers/mfd/ti-lmu.c
@@ -54,14 +54,6 @@ static void ti_lmu_disable_hw(void *data)
 		gpiod_set_value(lmu->en_gpio, 0);
 }
 
-static const struct mfd_cell lm3532_devices[] = {
-	{
-		.name          = "ti-lmu-backlight",
-		.id            = LM3532,
-		.of_compatible = "ti,lm3532-backlight",
-	},
-};
-
 #define LM363X_REGULATOR(_id)			\
 {						\
 	.name          = "lm363x-regulator",	\
@@ -141,7 +133,6 @@ static const struct ti_lmu_data chip##_data =	\
 	.max_register = max_reg,		\
 }						\
 
-TI_LMU_DATA(lm3532, LM3532_MAX_REG);
 TI_LMU_DATA(lm3631, LM3631_MAX_REG);
 TI_LMU_DATA(lm3632, LM3632_MAX_REG);
 TI_LMU_DATA(lm3633, LM3633_MAX_REG);
@@ -211,7 +202,6 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 }
 
 static const struct of_device_id ti_lmu_of_match[] = {
-	{ .compatible = "ti,lm3532", .data = &lm3532_data },
 	{ .compatible = "ti,lm3631", .data = &lm3631_data },
 	{ .compatible = "ti,lm3632", .data = &lm3632_data },
 	{ .compatible = "ti,lm3633", .data = &lm3633_data },
@@ -222,7 +212,6 @@ static const struct of_device_id ti_lmu_of_match[] = {
 MODULE_DEVICE_TABLE(of, ti_lmu_of_match);
 
 static const struct i2c_device_id ti_lmu_ids[] = {
-	{ "lm3532", LM3532 },
 	{ "lm3631", LM3631 },
 	{ "lm3632", LM3632 },
 	{ "lm3633", LM3633 },
diff --git a/include/linux/mfd/ti-lmu-register.h b/include/linux/mfd/ti-lmu-register.h
index 2125c7c02818..f09510561a55 100644
--- a/include/linux/mfd/ti-lmu-register.h
+++ b/include/linux/mfd/ti-lmu-register.h
@@ -15,50 +15,6 @@
 
 #include <linux/bitops.h>
 
-/* LM3532 */
-#define LM3532_REG_OUTPUT_CFG			0x10
-#define LM3532_ILED1_CFG_MASK			0x03
-#define LM3532_ILED2_CFG_MASK			0x0C
-#define LM3532_ILED3_CFG_MASK			0x30
-#define LM3532_ILED1_CFG_SHIFT			0
-#define LM3532_ILED2_CFG_SHIFT			2
-#define LM3532_ILED3_CFG_SHIFT			4
-
-#define LM3532_REG_RAMPUP			0x12
-#define LM3532_REG_RAMPDN			LM3532_REG_RAMPUP
-#define LM3532_RAMPUP_MASK			0x07
-#define LM3532_RAMPUP_SHIFT			0
-#define LM3532_RAMPDN_MASK			0x38
-#define LM3532_RAMPDN_SHIFT			3
-
-#define LM3532_REG_ENABLE			0x1D
-
-#define LM3532_REG_PWM_A_CFG			0x13
-#define LM3532_PWM_A_MASK			0x05	/* zone 0 */
-#define LM3532_PWM_ZONE_0			BIT(2)
-
-#define LM3532_REG_PWM_B_CFG			0x14
-#define LM3532_PWM_B_MASK			0x09	/* zone 1 */
-#define LM3532_PWM_ZONE_1			BIT(3)
-
-#define LM3532_REG_PWM_C_CFG			0x15
-#define LM3532_PWM_C_MASK			0x11	/* zone 2 */
-#define LM3532_PWM_ZONE_2			BIT(4)
-
-#define LM3532_REG_ZONE_CFG_A			0x16
-#define LM3532_REG_ZONE_CFG_B			0x18
-#define LM3532_REG_ZONE_CFG_C			0x1A
-#define LM3532_ZONE_MASK			(BIT(2) | BIT(3) | BIT(4))
-#define LM3532_ZONE_0				0
-#define LM3532_ZONE_1				BIT(2)
-#define LM3532_ZONE_2				BIT(3)
-
-#define LM3532_REG_BRT_A			0x70	/* zone 0 */
-#define LM3532_REG_BRT_B			0x76	/* zone 1 */
-#define LM3532_REG_BRT_C			0x7C	/* zone 2 */
-
-#define LM3532_MAX_REG				0x7E
-
 /* LM3631 */
 #define LM3631_REG_DEVCTRL			0x00
 #define LM3631_LCD_EN_MASK			BIT(1)
diff --git a/include/linux/mfd/ti-lmu.h b/include/linux/mfd/ti-lmu.h
index 1ef51ed36be5..7762c1bce55d 100644
--- a/include/linux/mfd/ti-lmu.h
+++ b/include/linux/mfd/ti-lmu.h
@@ -22,7 +22,6 @@
 #define LMU_EVENT_MONITOR_DONE		0x01
 
 enum ti_lmu_id {
-	LM3532,
 	LM3631,
 	LM3632,
 	LM3633,
-- 
2.21.0.5.gaeb582a983

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

* [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
@ 2019-03-21 14:28   ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Remove the LM3532 backlight driver references from the ti-lmu
code as dedicated driver support is available.

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

v5 - No changes - https://lore.kernel.org/patchwork/patch/1050411/

v4 - No changes - https://lore.kernel.org/patchwork/patch/1050123/
v3 - No changes - https://lore.kernel.org/patchwork/patch/1049025/
v2 - Removed LM3532 register definitions from ti-lmu-register - https://lore.kernel.org/patchwork/patch/1048808/

 drivers/mfd/ti-lmu.c                | 11 --------
 include/linux/mfd/ti-lmu-register.h | 44 -----------------------------
 include/linux/mfd/ti-lmu.h          |  1 -
 3 files changed, 56 deletions(-)

diff --git a/drivers/mfd/ti-lmu.c b/drivers/mfd/ti-lmu.c
index 37d0bdb291c3..b06cb908d1aa 100644
--- a/drivers/mfd/ti-lmu.c
+++ b/drivers/mfd/ti-lmu.c
@@ -54,14 +54,6 @@ static void ti_lmu_disable_hw(void *data)
 		gpiod_set_value(lmu->en_gpio, 0);
 }
 
-static const struct mfd_cell lm3532_devices[] = {
-	{
-		.name          = "ti-lmu-backlight",
-		.id            = LM3532,
-		.of_compatible = "ti,lm3532-backlight",
-	},
-};
-
 #define LM363X_REGULATOR(_id)			\
 {						\
 	.name          = "lm363x-regulator",	\
@@ -141,7 +133,6 @@ static const struct ti_lmu_data chip##_data =	\
 	.max_register = max_reg,		\
 }						\
 
-TI_LMU_DATA(lm3532, LM3532_MAX_REG);
 TI_LMU_DATA(lm3631, LM3631_MAX_REG);
 TI_LMU_DATA(lm3632, LM3632_MAX_REG);
 TI_LMU_DATA(lm3633, LM3633_MAX_REG);
@@ -211,7 +202,6 @@ static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 }
 
 static const struct of_device_id ti_lmu_of_match[] = {
-	{ .compatible = "ti,lm3532", .data = &lm3532_data },
 	{ .compatible = "ti,lm3631", .data = &lm3631_data },
 	{ .compatible = "ti,lm3632", .data = &lm3632_data },
 	{ .compatible = "ti,lm3633", .data = &lm3633_data },
@@ -222,7 +212,6 @@ static const struct of_device_id ti_lmu_of_match[] = {
 MODULE_DEVICE_TABLE(of, ti_lmu_of_match);
 
 static const struct i2c_device_id ti_lmu_ids[] = {
-	{ "lm3532", LM3532 },
 	{ "lm3631", LM3631 },
 	{ "lm3632", LM3632 },
 	{ "lm3633", LM3633 },
diff --git a/include/linux/mfd/ti-lmu-register.h b/include/linux/mfd/ti-lmu-register.h
index 2125c7c02818..f09510561a55 100644
--- a/include/linux/mfd/ti-lmu-register.h
+++ b/include/linux/mfd/ti-lmu-register.h
@@ -15,50 +15,6 @@
 
 #include <linux/bitops.h>
 
-/* LM3532 */
-#define LM3532_REG_OUTPUT_CFG			0x10
-#define LM3532_ILED1_CFG_MASK			0x03
-#define LM3532_ILED2_CFG_MASK			0x0C
-#define LM3532_ILED3_CFG_MASK			0x30
-#define LM3532_ILED1_CFG_SHIFT			0
-#define LM3532_ILED2_CFG_SHIFT			2
-#define LM3532_ILED3_CFG_SHIFT			4
-
-#define LM3532_REG_RAMPUP			0x12
-#define LM3532_REG_RAMPDN			LM3532_REG_RAMPUP
-#define LM3532_RAMPUP_MASK			0x07
-#define LM3532_RAMPUP_SHIFT			0
-#define LM3532_RAMPDN_MASK			0x38
-#define LM3532_RAMPDN_SHIFT			3
-
-#define LM3532_REG_ENABLE			0x1D
-
-#define LM3532_REG_PWM_A_CFG			0x13
-#define LM3532_PWM_A_MASK			0x05	/* zone 0 */
-#define LM3532_PWM_ZONE_0			BIT(2)
-
-#define LM3532_REG_PWM_B_CFG			0x14
-#define LM3532_PWM_B_MASK			0x09	/* zone 1 */
-#define LM3532_PWM_ZONE_1			BIT(3)
-
-#define LM3532_REG_PWM_C_CFG			0x15
-#define LM3532_PWM_C_MASK			0x11	/* zone 2 */
-#define LM3532_PWM_ZONE_2			BIT(4)
-
-#define LM3532_REG_ZONE_CFG_A			0x16
-#define LM3532_REG_ZONE_CFG_B			0x18
-#define LM3532_REG_ZONE_CFG_C			0x1A
-#define LM3532_ZONE_MASK			(BIT(2) | BIT(3) | BIT(4))
-#define LM3532_ZONE_0				0
-#define LM3532_ZONE_1				BIT(2)
-#define LM3532_ZONE_2				BIT(3)
-
-#define LM3532_REG_BRT_A			0x70	/* zone 0 */
-#define LM3532_REG_BRT_B			0x76	/* zone 1 */
-#define LM3532_REG_BRT_C			0x7C	/* zone 2 */
-
-#define LM3532_MAX_REG				0x7E
-
 /* LM3631 */
 #define LM3631_REG_DEVCTRL			0x00
 #define LM3631_LCD_EN_MASK			BIT(1)
diff --git a/include/linux/mfd/ti-lmu.h b/include/linux/mfd/ti-lmu.h
index 1ef51ed36be5..7762c1bce55d 100644
--- a/include/linux/mfd/ti-lmu.h
+++ b/include/linux/mfd/ti-lmu.h
@@ -22,7 +22,6 @@
 #define LMU_EVENT_MONITOR_DONE		0x01
 
 enum ti_lmu_id {
-	LM3532,
 	LM3631,
 	LM3632,
 	LM3633,
-- 
2.21.0.5.gaeb582a983


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

* [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-21 14:28 ` Dan Murphy
@ 2019-03-21 14:28   ` Dan Murphy
  -1 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Introduce the Texas Instruments LM3532 White LED driver.
The driver supports ALS configurability or manual brightness
control.

The driver also supports associating LED strings with specific
control banks in a group or as individually controlled strings.

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

v5 - Added mutex_destroy in remove - https://lore.kernel.org/patchwork/patch/1050410/

v4 - Updated code to DT doc changes appending "ti," to TI specific properties -
https://lore.kernel.org/patchwork/patch/1050124/
v3 - Removed switch case for register setting in favor of an algorithim (v1 comment),
https://lore.kernel.org/patchwork/patch/1049024/
v2 - Added look up tables for als_avg, als_imp and ramp times, fixed brightness
control when ALS is in control, added property value checks to ensure the values
are not out of bounds - https://lore.kernel.org/patchwork/patch/1048807/

 drivers/leds/Kconfig       |  10 +
 drivers/leds/Makefile      |   1 +
 drivers/leds/leds-lm3532.c | 683 +++++++++++++++++++++++++++++++++++++
 3 files changed, 694 insertions(+)
 create mode 100644 drivers/leds/leds-lm3532.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a72f97fca57b..da00b9ed5a5c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -138,6 +138,16 @@ config LEDS_LM3530
 	  controlled manually or using PWM input or using ambient
 	  light automatically.
 
+config LEDS_LM3532
+	tristate "LCD Backlight driver for LM3532"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for the LCD backlight using
+	  LM3532 ambient light sensor chip. This ALS chip can be
+	  controlled manually or using PWM input or using ambient
+	  light automatically.
+
 config LEDS_LM3533
 	tristate "LED support for LM3533"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 4c1b0054f379..7a8b1f55d459 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_CPCAP)		+= leds-cpcap.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
+obj-$(CONFIG_LEDS_LM3532)		+= leds-lm3532.o
 obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
 obj-$(CONFIG_LEDS_LM3642)		+= leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
new file mode 100644
index 000000000000..180895b83b88
--- /dev/null
+++ b/drivers/leds/leds-lm3532.c
@@ -0,0 +1,683 @@
+// SPDX-License-Identifier: GPL-2.0
+// TI LM3532 LED driver
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <uapi/linux/uleds.h>
+#include <linux/gpio/consumer.h>
+
+#define LM3532_NAME "lm3532-led"
+#define LM3532_BL_MODE_MANUAL	0x00
+#define LM3532_BL_MODE_ALS	0x01
+
+#define LM3532_REG_OUTPUT_CFG	0x10
+#define LM3532_REG_STARTSHUT_RAMP	0x11
+#define LM3532_REG_RT_RAMP	0x12
+#define LM3532_REG_PWM_A_CFG	0x13
+#define LM3532_REG_PWM_B_CFG	0x14
+#define LM3532_REG_PWM_C_CFG	0x15
+#define LM3532_REG_ZONE_CFG_A	0x16
+#define LM3532_REG_CTRL_A_BRT	0x17
+#define LM3532_REG_ZONE_CFG_B	0x18
+#define LM3532_REG_CTRL_B_BRT	0x19
+#define LM3532_REG_ZONE_CFG_C	0x1a
+#define LM3532_REG_CTRL_C_BRT	0x1b
+#define LM3532_REG_ENABLE	0x1d
+#define LM3532_ALS_CONFIG	0x23
+#define LM3532_REG_ZN_0_HI	0x60
+#define LM3532_REG_ZN_0_LO	0x61
+#define LM3532_REG_ZN_1_HI	0x62
+#define LM3532_REG_ZN_1_LO	0x63
+#define LM3532_REG_ZN_2_HI	0x64
+#define LM3532_REG_ZN_2_LO	0x65
+#define LM3532_REG_ZN_3_HI	0x66
+#define LM3532_REG_ZN_3_LO	0x67
+#define LM3532_REG_MAX		0x7e
+
+/* Contorl Enable */
+#define LM3532_CTRL_A_ENABLE	BIT(0)
+#define LM3532_CTRL_B_ENABLE	BIT(1)
+#define LM3532_CTRL_C_ENABLE	BIT(2)
+
+/* PWM Zone Control */
+#define LM3532_PWM_ZONE_MASK	0x7c
+#define LM3532_PWM_ZONE_0_EN	BIT(2)
+#define LM3532_PWM_ZONE_1_EN	BIT(3)
+#define LM3532_PWM_ZONE_2_EN	BIT(4)
+#define LM3532_PWM_ZONE_3_EN	BIT(5)
+#define LM3532_PWM_ZONE_4_EN	BIT(6)
+
+/* Brightness Configuration */
+#define LM3532_I2C_CTRL		BIT(0)
+#define LM3532_ALS_CTRL		0
+#define LM3532_LINEAR_MAP	BIT(1)
+#define LM3532_ZONE_MASK	(BIT(2) | BIT(3) | BIT(4))
+#define LM3532_ZONE_0		0
+#define LM3532_ZONE_1		BIT(2)
+#define LM3532_ZONE_2		BIT(3)
+#define LM3532_ZONE_3		(BIT(2) | BIT(3))
+#define LM3532_ZONE_4		BIT(4)
+
+#define LM3532_ENABLE_ALS	BIT(3)
+#define LM3532_ALS_SEL_SHIFT	6
+
+/* Zone Boundary Register */
+#define LM3532_ALS_WINDOW_mV	2000
+#define LM3532_ALS_ZB_MAX	4
+#define LM3532_ALS_OFFSET_mV	2
+
+#define LM3532_CONTROL_A	0
+#define LM3532_CONTROL_B	1
+#define LM3532_CONTROL_C	2
+#define LM3532_MAX_CONTROL_BANKS 3
+#define LM3532_MAX_LED_STRINGS	3
+
+#define LM3532_OUTPUT_CFG_MASK	0x3
+#define LM3532_BRT_VAL_ADJUST	8
+#define LM3532_RAMP_DOWN_SHIFT	3
+
+#define LM3532_NUM_RAMP_VALS	8
+#define LM3532_NUM_AVG_VALS	8
+#define LM3532_NUM_IMP_VALS	32
+
+/*
+ * struct lm3532_als_data
+ * @config - value of ALS configuration register
+ * @als1_imp_sel - value of ALS1 resistor select register
+ * @als2_imp_sel - value of ALS2 resistor select register
+ * @als_avrg_time - ALS averaging time
+ * @als_input_mode - ALS input mode for brightness control
+ * @als_vmin - Minimum ALS voltage
+ * @als_vmax - Maximum ALS voltage
+ * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
+ * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
+ */
+struct lm3532_als_data {
+	u8 config;
+	u8 als1_imp_sel;
+	u8 als2_imp_sel;
+	u8 als_avrg_time;
+	u8 als_input_mode;
+	u32 als_vmin;
+	u32 als_vmax;
+	u8 zones_lo[LM3532_ALS_ZB_MAX];
+	u8 zones_hi[LM3532_ALS_ZB_MAX];
+};
+
+/**
+ * struct lm3532_led
+ * @led_dev: led class device
+ * @priv - Pointer the device data structure
+ * @control_bank - Control bank the LED is associated to
+ * @mode - Mode of the LED string
+ * @num_leds - Number of LED strings are supported in this array
+ * @led_strings - The LED strings supported in this array
+ * @label - LED label
+ */
+struct lm3532_led {
+	struct led_classdev led_dev;
+	struct lm3532_data *priv;
+
+	int control_bank;
+	int mode;
+	int num_leds;
+	u32 led_strings[LM3532_MAX_CONTROL_BANKS];
+	char label[LED_MAX_NAME_SIZE];
+};
+
+/**
+ * struct lm3532_data
+ * @enable_gpio - Hardware enable gpio
+ * @regulator: regulator
+ * @client: i2c client
+ * @regmap - Devices register map
+ * @dev - Pointer to the devices device struct
+ * @lock - Lock for reading/writing the device
+ * @als_data - Pointer to the als data struct
+ * @runtime_ramp_up - Runtime ramp up setting
+ * @runtime_ramp_down - Runtime ramp down setting
+ * @leds - Array of LED strings
+ */
+struct lm3532_data {
+	struct gpio_desc *enable_gpio;
+	struct regulator *regulator;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct device *dev;
+	struct mutex lock;
+
+	struct lm3532_als_data *als_data;
+
+	u32 runtime_ramp_up;
+	u32 runtime_ramp_down;
+
+	struct lm3532_led leds[];
+};
+
+static const struct reg_default lm3532_reg_defs[] = {
+	{LM3532_REG_OUTPUT_CFG, 0xe4},
+	{LM3532_REG_STARTSHUT_RAMP, 0xc0},
+	{LM3532_REG_RT_RAMP, 0xc0},
+	{LM3532_REG_PWM_A_CFG, 0x82},
+	{LM3532_REG_PWM_B_CFG, 0x82},
+	{LM3532_REG_PWM_C_CFG, 0x82},
+	{LM3532_REG_ZONE_CFG_A, 0xf1},
+	{LM3532_REG_CTRL_A_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_B, 0xf1},
+	{LM3532_REG_CTRL_B_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_C, 0xf1},
+	{LM3532_REG_CTRL_C_BRT, 0xf3},
+	{LM3532_REG_ENABLE, 0xf8},
+	{LM3532_ALS_CONFIG, 0x44},
+	{LM3532_REG_ZN_0_HI, 0x35},
+	{LM3532_REG_ZN_0_LO, 0x33},
+	{LM3532_REG_ZN_1_HI, 0x6a},
+	{LM3532_REG_ZN_1_LO, 0x66},
+	{LM3532_REG_ZN_2_HI, 0xa1},
+	{LM3532_REG_ZN_2_LO, 0x99},
+	{LM3532_REG_ZN_3_HI, 0xdc},
+	{LM3532_REG_ZN_3_LO, 0xcc},
+};
+
+static const struct regmap_config lm3532_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = LM3532_REG_MAX,
+	.reg_defaults = lm3532_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
+	.cache_type = REGCACHE_FLAT,
+};
+
+const static int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330,
+						       92500, 7400, 6170, 5290,
+						       4630, 4110, 3700, 3360,
+						       3080, 2850, 2640, 2440,
+						       2310, 2180, 2060, 1950,
+						       1850, 1760, 1680, 1610,
+						       1540, 1480, 1420, 1370,
+						       1320, 1280, 1230, 1190};
+static int lm3532_get_als_imp_index(int als_imped)
+{
+	int i;
+
+	if (als_imped > als_imp_table[1])
+		return 0;
+
+	if (als_imped < als_imp_table[LM3532_NUM_IMP_VALS - 1])
+		return LM3532_NUM_IMP_VALS - 1;
+
+	for (i = 1; i < LM3532_NUM_IMP_VALS; i++) {
+		if (als_imped == als_imp_table[i])
+			return i;
+
+		/* Find an approximate index by looking up the table */
+		if (als_imped < als_imp_table[i - 1] &&
+		    als_imped > als_imp_table[i]) {
+			if (als_imped - als_imp_table[i - 1] <
+			    als_imp_table[i] - als_imped)
+				return i + 1;
+			else
+				return i;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int lm3532_get_index(const int table[], int size, int value)
+{
+	int i;
+
+	for (i = 1; i < size; i++) {
+		if (value == table[i])
+			return i;
+
+		/* Find an approximate index by looking up the table */
+		if (value > table[i - 1] &&
+		    value < table[i]) {
+			if (value - table[i - 1] < table[i] - value)
+				return i - 1;
+			else
+				return i;
+		}
+	}
+
+	return -EINVAL;
+}
+
+const static int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680,
+							1433360, 286720, 573440,
+							1146880, 2293760};
+static int lm3532_get_als_avg_index(int avg_time)
+{
+	if (avg_time <= als_avrg_table[0])
+		return 0;
+
+	if (avg_time > als_avrg_table[LM3532_NUM_AVG_VALS - 1])
+		return LM3532_NUM_AVG_VALS - 1;
+
+	return lm3532_get_index(&als_avrg_table[0], LM3532_NUM_AVG_VALS,
+				avg_time);
+}
+
+const static int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192,
+						     16384, 32768, 65536};
+static int lm3532_get_ramp_index(int ramp_time)
+{
+	if (ramp_time <= ramp_table[0])
+		return 0;
+
+	if (ramp_time > ramp_table[LM3532_NUM_RAMP_VALS - 1])
+		return LM3532_NUM_RAMP_VALS - 1;
+
+	return lm3532_get_index(&ramp_table[0], LM3532_NUM_RAMP_VALS,
+				ramp_time);
+}
+
+static int lm3532_led_enable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val = BIT(led_data->control_bank);
+	int ret;
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_enable(led_data->priv->regulator);
+}
+
+static int lm3532_led_disable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val = BIT(led_data->control_bank);
+	int ret;
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ~ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_disable(led_data->priv->regulator);
+}
+
+static int lm3532_brightness_set(struct led_classdev *led_cdev,
+				 enum led_brightness brt_val)
+{
+	struct lm3532_led *led =
+			container_of(led_cdev, struct lm3532_led, led_dev);
+	u8 brightness_reg;
+	int ret;
+
+	mutex_lock(&led->priv->lock);
+
+	if (led->mode == LM3532_BL_MODE_ALS) {
+		if (brt_val > LED_OFF)
+			ret = lm3532_led_enable(led);
+		else
+			ret = lm3532_led_disable(led);
+
+		goto unlock;
+	}
+
+	if (brt_val == LED_OFF) {
+		ret = lm3532_led_disable(led);
+		goto unlock;
+	}
+
+	ret = lm3532_led_enable(led);
+	if (ret)
+		goto unlock;
+
+	brightness_reg = LM3532_REG_CTRL_A_BRT + led->control_bank * 2;
+	brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
+
+	ret = regmap_write(led->priv->regmap, brightness_reg, brt_val);
+
+unlock:
+	mutex_unlock(&led->priv->lock);
+	return ret;
+}
+
+static int lm3532_init_registers(struct lm3532_led *led)
+{
+	struct lm3532_data *drvdata = led->priv;
+	unsigned int runtime_ramp_val;
+	unsigned int output_cfg_val = 0;
+	unsigned int output_cfg_shift = 0;
+	unsigned int output_cfg_mask = 0;
+	int ret, i;
+
+	for (i = 0; i < led->num_leds; i++) {
+		output_cfg_shift = led->led_strings[i] * 2;
+		output_cfg_val |= (led->control_bank << output_cfg_shift);
+		output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
+	}
+
+	ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
+				 output_cfg_mask, output_cfg_val);
+	if (ret)
+		return ret;
+
+	runtime_ramp_val = drvdata->runtime_ramp_up |
+			 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
+
+	return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
+			    runtime_ramp_val);
+}
+
+static int lm3532_als_configure(struct lm3532_data *priv,
+				struct lm3532_led *led)
+{
+	struct lm3532_als_data *als = priv->als_data;
+	u32 als_vmin, als_vmax, als_vstep;
+	int zone_reg = LM3532_REG_ZN_0_HI;
+	int brightnes_config_reg;
+	int ret;
+	int i;
+
+	als_vmin = als->als_vmin;
+	als_vmax = als->als_vmax;
+
+	als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
+
+	for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
+		als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
+				LED_FULL) / 1000;
+		als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
+				als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
+
+		zone_reg = LM3532_REG_ZN_0_HI + i * 2;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
+		if (ret)
+			return ret;
+
+		zone_reg += 1;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
+		if (ret)
+			return ret;
+	}
+
+	als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
+		(als->als_input_mode << LM3532_ALS_SEL_SHIFT));
+
+	ret = regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
+	if (ret)
+		return ret;
+
+	brightnes_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2;
+
+	return regmap_update_bits(priv->regmap, brightnes_config_reg,
+				  LM3532_I2C_CTRL, LM3532_ALS_CTRL);
+}
+
+static int lm3532_parse_als(struct lm3532_data *priv)
+{
+	struct lm3532_als_data *als;
+	int als_avg_time;
+	int als_impedance;
+	int ret;
+
+	als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
+	if (als == NULL)
+		return -ENOMEM;
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als-vmin",
+				       &als->als_vmin);
+	if (ret)
+		als->als_vmin = 0;
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als-vmax",
+				       &als->als_vmax);
+	if (ret)
+		als->als_vmax = LM3532_ALS_WINDOW_mV;
+
+	if (als->als_vmax > LM3532_ALS_WINDOW_mV) {
+		ret = -EINVAL;
+		return ret;
+	}
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als1-imp-sel",
+				      &als_impedance);
+	if (ret)
+		als->als1_imp_sel = 0;
+	else
+		als->als1_imp_sel = lm3532_get_als_imp_index(als_impedance);
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als2-imp-sel",
+				      &als_impedance);
+	if (ret)
+		als->als2_imp_sel = 0;
+	else
+		als->als2_imp_sel = lm3532_get_als_imp_index(als_impedance);
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als-avrg-time-us",
+				      &als_avg_time);
+	if (ret)
+		als->als_avrg_time = 0;
+	else
+		als->als_avrg_time = lm3532_get_als_avg_index(als_avg_time);
+
+	ret = device_property_read_u8(&priv->client->dev, "ti,als-input-mode",
+				      &als->als_input_mode);
+	if (ret)
+		als->als_input_mode = 0;
+
+	if (als->als_input_mode > LM3532_BL_MODE_ALS) {
+		ret = -EINVAL;
+		return ret;
+	}
+
+	priv->als_data = als;
+
+	return ret;
+}
+
+static int lm3532_parse_node(struct lm3532_data *priv)
+{
+	struct fwnode_handle *child = NULL;
+	struct lm3532_led *led;
+	const char *name;
+	int control_bank;
+	u32 ramp_time;
+	size_t i = 0;
+	int ret;
+
+	priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
+						   "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->enable_gpio))
+		priv->enable_gpio = NULL;
+
+	priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
+	if (IS_ERR(priv->regulator))
+		priv->regulator = NULL;
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-up-us",
+				       &ramp_time);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-up-ms property missing\n");
+	else
+		priv->runtime_ramp_up = lm3532_get_ramp_index(ramp_time);
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-down-us",
+				       &ramp_time);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+	else
+		priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time);
+
+	device_for_each_child_node(priv->dev, child) {
+		led = &priv->leds[i];
+
+		ret = fwnode_property_read_u32(child, "reg", &control_bank);
+		if (ret) {
+			dev_err(&priv->client->dev, "reg property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (control_bank > LM3532_CONTROL_C) {
+			dev_err(&priv->client->dev, "Control bank invalid\n");
+			continue;
+		}
+
+		led->control_bank = control_bank;
+
+		ret = fwnode_property_read_u32(child, "ti,led-mode",
+					       &led->mode);
+		if (ret) {
+			dev_err(&priv->client->dev, "ti,led-mode property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (led->mode == LM3532_BL_MODE_ALS) {
+			ret = lm3532_parse_als(priv);
+			if (ret)
+				dev_err(&priv->client->dev, "Failed to parse als\n");
+			else
+				lm3532_als_configure(priv, led);
+		}
+
+		led->num_leds = fwnode_property_read_u32_array(child,
+							       "led-sources",
+							       NULL, 0);
+
+		if (led->num_leds > LM3532_MAX_LED_STRINGS) {
+			dev_err(&priv->client->dev, "To many LED string defined\n");
+			continue;
+		}
+
+		ret = fwnode_property_read_u32_array(child, "led-sources",
+						    led->led_strings,
+						    led->num_leds);
+		if (ret) {
+			dev_err(&priv->client->dev, "led-sources property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		fwnode_property_read_string(child, "linux,default-trigger",
+					    &led->led_dev.default_trigger);
+
+		ret = fwnode_property_read_string(child, "label", &name);
+		if (ret)
+			snprintf(led->label, sizeof(led->label),
+				"%s::", priv->client->name);
+		else
+			snprintf(led->label, sizeof(led->label),
+				 "%s:%s", priv->client->name, name);
+
+		led->priv = priv;
+		led->led_dev.name = led->label;
+		led->led_dev.brightness_set_blocking = lm3532_brightness_set;
+
+		ret = devm_led_classdev_register(priv->dev, &led->led_dev);
+		if (ret) {
+			dev_err(&priv->client->dev, "led register err: %d\n",
+				ret);
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		lm3532_init_registers(led);
+
+		i++;
+	}
+
+child_out:
+	return ret;
+}
+
+static int lm3532_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct lm3532_data *drvdata;
+	int ret = 0;
+	int count;
+
+	count = device_get_child_node_count(&client->dev);
+	if (!count) {
+		dev_err(&client->dev, "LEDs are not defined in device tree!");
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
+			   GFP_KERNEL);
+	if (drvdata == NULL)
+		return -ENOMEM;
+
+	drvdata->client = client;
+	drvdata->dev = &client->dev;
+
+	drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
+	if (IS_ERR(drvdata->regmap)) {
+		ret = PTR_ERR(drvdata->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	mutex_init(&drvdata->lock);
+	i2c_set_clientdata(client, drvdata);
+
+	ret = lm3532_parse_node(drvdata);
+	if (ret) {
+		dev_err(&client->dev, "Failed to parse node\n");
+		return ret;
+	}
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 1);
+
+	return ret;
+}
+
+static int lm3532_remove(struct i2c_client *client)
+{
+	struct lm3532_data *drvdata = i2c_get_clientdata(client);
+
+	mutex_destroy(&drvdata->lock);
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 0);
+
+	return 0;
+}
+
+static const struct of_device_id of_lm3532_leds_match[] = {
+	{ .compatible = "ti,lm3532", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
+
+static const struct i2c_device_id lm3532_id[] = {
+	{LM3532_NAME, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, lm3532_id);
+
+static struct i2c_driver lm3532_i2c_driver = {
+	.probe = lm3532_probe,
+	.remove = lm3532_remove,
+	.id_table = lm3532_id,
+	.driver = {
+		.name = LM3532_NAME,
+		.of_match_table = of_lm3532_leds_match,
+	},
+};
+module_i2c_driver(lm3532_i2c_driver);
+
+MODULE_DESCRIPTION("Back Light driver for LM3532");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
-- 
2.21.0.5.gaeb582a983

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

* [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-21 14:28   ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Introduce the Texas Instruments LM3532 White LED driver.
The driver supports ALS configurability or manual brightness
control.

The driver also supports associating LED strings with specific
control banks in a group or as individually controlled strings.

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

v5 - Added mutex_destroy in remove - https://lore.kernel.org/patchwork/patch/1050410/

v4 - Updated code to DT doc changes appending "ti," to TI specific properties -
https://lore.kernel.org/patchwork/patch/1050124/
v3 - Removed switch case for register setting in favor of an algorithim (v1 comment),
https://lore.kernel.org/patchwork/patch/1049024/
v2 - Added look up tables for als_avg, als_imp and ramp times, fixed brightness
control when ALS is in control, added property value checks to ensure the values
are not out of bounds - https://lore.kernel.org/patchwork/patch/1048807/

 drivers/leds/Kconfig       |  10 +
 drivers/leds/Makefile      |   1 +
 drivers/leds/leds-lm3532.c | 683 +++++++++++++++++++++++++++++++++++++
 3 files changed, 694 insertions(+)
 create mode 100644 drivers/leds/leds-lm3532.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a72f97fca57b..da00b9ed5a5c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -138,6 +138,16 @@ config LEDS_LM3530
 	  controlled manually or using PWM input or using ambient
 	  light automatically.
 
+config LEDS_LM3532
+	tristate "LCD Backlight driver for LM3532"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for the LCD backlight using
+	  LM3532 ambient light sensor chip. This ALS chip can be
+	  controlled manually or using PWM input or using ambient
+	  light automatically.
+
 config LEDS_LM3533
 	tristate "LED support for LM3533"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 4c1b0054f379..7a8b1f55d459 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_CPCAP)		+= leds-cpcap.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
+obj-$(CONFIG_LEDS_LM3532)		+= leds-lm3532.o
 obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
 obj-$(CONFIG_LEDS_LM3642)		+= leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
new file mode 100644
index 000000000000..180895b83b88
--- /dev/null
+++ b/drivers/leds/leds-lm3532.c
@@ -0,0 +1,683 @@
+// SPDX-License-Identifier: GPL-2.0
+// TI LM3532 LED driver
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <uapi/linux/uleds.h>
+#include <linux/gpio/consumer.h>
+
+#define LM3532_NAME "lm3532-led"
+#define LM3532_BL_MODE_MANUAL	0x00
+#define LM3532_BL_MODE_ALS	0x01
+
+#define LM3532_REG_OUTPUT_CFG	0x10
+#define LM3532_REG_STARTSHUT_RAMP	0x11
+#define LM3532_REG_RT_RAMP	0x12
+#define LM3532_REG_PWM_A_CFG	0x13
+#define LM3532_REG_PWM_B_CFG	0x14
+#define LM3532_REG_PWM_C_CFG	0x15
+#define LM3532_REG_ZONE_CFG_A	0x16
+#define LM3532_REG_CTRL_A_BRT	0x17
+#define LM3532_REG_ZONE_CFG_B	0x18
+#define LM3532_REG_CTRL_B_BRT	0x19
+#define LM3532_REG_ZONE_CFG_C	0x1a
+#define LM3532_REG_CTRL_C_BRT	0x1b
+#define LM3532_REG_ENABLE	0x1d
+#define LM3532_ALS_CONFIG	0x23
+#define LM3532_REG_ZN_0_HI	0x60
+#define LM3532_REG_ZN_0_LO	0x61
+#define LM3532_REG_ZN_1_HI	0x62
+#define LM3532_REG_ZN_1_LO	0x63
+#define LM3532_REG_ZN_2_HI	0x64
+#define LM3532_REG_ZN_2_LO	0x65
+#define LM3532_REG_ZN_3_HI	0x66
+#define LM3532_REG_ZN_3_LO	0x67
+#define LM3532_REG_MAX		0x7e
+
+/* Contorl Enable */
+#define LM3532_CTRL_A_ENABLE	BIT(0)
+#define LM3532_CTRL_B_ENABLE	BIT(1)
+#define LM3532_CTRL_C_ENABLE	BIT(2)
+
+/* PWM Zone Control */
+#define LM3532_PWM_ZONE_MASK	0x7c
+#define LM3532_PWM_ZONE_0_EN	BIT(2)
+#define LM3532_PWM_ZONE_1_EN	BIT(3)
+#define LM3532_PWM_ZONE_2_EN	BIT(4)
+#define LM3532_PWM_ZONE_3_EN	BIT(5)
+#define LM3532_PWM_ZONE_4_EN	BIT(6)
+
+/* Brightness Configuration */
+#define LM3532_I2C_CTRL		BIT(0)
+#define LM3532_ALS_CTRL		0
+#define LM3532_LINEAR_MAP	BIT(1)
+#define LM3532_ZONE_MASK	(BIT(2) | BIT(3) | BIT(4))
+#define LM3532_ZONE_0		0
+#define LM3532_ZONE_1		BIT(2)
+#define LM3532_ZONE_2		BIT(3)
+#define LM3532_ZONE_3		(BIT(2) | BIT(3))
+#define LM3532_ZONE_4		BIT(4)
+
+#define LM3532_ENABLE_ALS	BIT(3)
+#define LM3532_ALS_SEL_SHIFT	6
+
+/* Zone Boundary Register */
+#define LM3532_ALS_WINDOW_mV	2000
+#define LM3532_ALS_ZB_MAX	4
+#define LM3532_ALS_OFFSET_mV	2
+
+#define LM3532_CONTROL_A	0
+#define LM3532_CONTROL_B	1
+#define LM3532_CONTROL_C	2
+#define LM3532_MAX_CONTROL_BANKS 3
+#define LM3532_MAX_LED_STRINGS	3
+
+#define LM3532_OUTPUT_CFG_MASK	0x3
+#define LM3532_BRT_VAL_ADJUST	8
+#define LM3532_RAMP_DOWN_SHIFT	3
+
+#define LM3532_NUM_RAMP_VALS	8
+#define LM3532_NUM_AVG_VALS	8
+#define LM3532_NUM_IMP_VALS	32
+
+/*
+ * struct lm3532_als_data
+ * @config - value of ALS configuration register
+ * @als1_imp_sel - value of ALS1 resistor select register
+ * @als2_imp_sel - value of ALS2 resistor select register
+ * @als_avrg_time - ALS averaging time
+ * @als_input_mode - ALS input mode for brightness control
+ * @als_vmin - Minimum ALS voltage
+ * @als_vmax - Maximum ALS voltage
+ * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
+ * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
+ */
+struct lm3532_als_data {
+	u8 config;
+	u8 als1_imp_sel;
+	u8 als2_imp_sel;
+	u8 als_avrg_time;
+	u8 als_input_mode;
+	u32 als_vmin;
+	u32 als_vmax;
+	u8 zones_lo[LM3532_ALS_ZB_MAX];
+	u8 zones_hi[LM3532_ALS_ZB_MAX];
+};
+
+/**
+ * struct lm3532_led
+ * @led_dev: led class device
+ * @priv - Pointer the device data structure
+ * @control_bank - Control bank the LED is associated to
+ * @mode - Mode of the LED string
+ * @num_leds - Number of LED strings are supported in this array
+ * @led_strings - The LED strings supported in this array
+ * @label - LED label
+ */
+struct lm3532_led {
+	struct led_classdev led_dev;
+	struct lm3532_data *priv;
+
+	int control_bank;
+	int mode;
+	int num_leds;
+	u32 led_strings[LM3532_MAX_CONTROL_BANKS];
+	char label[LED_MAX_NAME_SIZE];
+};
+
+/**
+ * struct lm3532_data
+ * @enable_gpio - Hardware enable gpio
+ * @regulator: regulator
+ * @client: i2c client
+ * @regmap - Devices register map
+ * @dev - Pointer to the devices device struct
+ * @lock - Lock for reading/writing the device
+ * @als_data - Pointer to the als data struct
+ * @runtime_ramp_up - Runtime ramp up setting
+ * @runtime_ramp_down - Runtime ramp down setting
+ * @leds - Array of LED strings
+ */
+struct lm3532_data {
+	struct gpio_desc *enable_gpio;
+	struct regulator *regulator;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct device *dev;
+	struct mutex lock;
+
+	struct lm3532_als_data *als_data;
+
+	u32 runtime_ramp_up;
+	u32 runtime_ramp_down;
+
+	struct lm3532_led leds[];
+};
+
+static const struct reg_default lm3532_reg_defs[] = {
+	{LM3532_REG_OUTPUT_CFG, 0xe4},
+	{LM3532_REG_STARTSHUT_RAMP, 0xc0},
+	{LM3532_REG_RT_RAMP, 0xc0},
+	{LM3532_REG_PWM_A_CFG, 0x82},
+	{LM3532_REG_PWM_B_CFG, 0x82},
+	{LM3532_REG_PWM_C_CFG, 0x82},
+	{LM3532_REG_ZONE_CFG_A, 0xf1},
+	{LM3532_REG_CTRL_A_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_B, 0xf1},
+	{LM3532_REG_CTRL_B_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_C, 0xf1},
+	{LM3532_REG_CTRL_C_BRT, 0xf3},
+	{LM3532_REG_ENABLE, 0xf8},
+	{LM3532_ALS_CONFIG, 0x44},
+	{LM3532_REG_ZN_0_HI, 0x35},
+	{LM3532_REG_ZN_0_LO, 0x33},
+	{LM3532_REG_ZN_1_HI, 0x6a},
+	{LM3532_REG_ZN_1_LO, 0x66},
+	{LM3532_REG_ZN_2_HI, 0xa1},
+	{LM3532_REG_ZN_2_LO, 0x99},
+	{LM3532_REG_ZN_3_HI, 0xdc},
+	{LM3532_REG_ZN_3_LO, 0xcc},
+};
+
+static const struct regmap_config lm3532_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = LM3532_REG_MAX,
+	.reg_defaults = lm3532_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
+	.cache_type = REGCACHE_FLAT,
+};
+
+const static int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330,
+						       92500, 7400, 6170, 5290,
+						       4630, 4110, 3700, 3360,
+						       3080, 2850, 2640, 2440,
+						       2310, 2180, 2060, 1950,
+						       1850, 1760, 1680, 1610,
+						       1540, 1480, 1420, 1370,
+						       1320, 1280, 1230, 1190};
+static int lm3532_get_als_imp_index(int als_imped)
+{
+	int i;
+
+	if (als_imped > als_imp_table[1])
+		return 0;
+
+	if (als_imped < als_imp_table[LM3532_NUM_IMP_VALS - 1])
+		return LM3532_NUM_IMP_VALS - 1;
+
+	for (i = 1; i < LM3532_NUM_IMP_VALS; i++) {
+		if (als_imped == als_imp_table[i])
+			return i;
+
+		/* Find an approximate index by looking up the table */
+		if (als_imped < als_imp_table[i - 1] &&
+		    als_imped > als_imp_table[i]) {
+			if (als_imped - als_imp_table[i - 1] <
+			    als_imp_table[i] - als_imped)
+				return i + 1;
+			else
+				return i;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int lm3532_get_index(const int table[], int size, int value)
+{
+	int i;
+
+	for (i = 1; i < size; i++) {
+		if (value == table[i])
+			return i;
+
+		/* Find an approximate index by looking up the table */
+		if (value > table[i - 1] &&
+		    value < table[i]) {
+			if (value - table[i - 1] < table[i] - value)
+				return i - 1;
+			else
+				return i;
+		}
+	}
+
+	return -EINVAL;
+}
+
+const static int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680,
+							1433360, 286720, 573440,
+							1146880, 2293760};
+static int lm3532_get_als_avg_index(int avg_time)
+{
+	if (avg_time <= als_avrg_table[0])
+		return 0;
+
+	if (avg_time > als_avrg_table[LM3532_NUM_AVG_VALS - 1])
+		return LM3532_NUM_AVG_VALS - 1;
+
+	return lm3532_get_index(&als_avrg_table[0], LM3532_NUM_AVG_VALS,
+				avg_time);
+}
+
+const static int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192,
+						     16384, 32768, 65536};
+static int lm3532_get_ramp_index(int ramp_time)
+{
+	if (ramp_time <= ramp_table[0])
+		return 0;
+
+	if (ramp_time > ramp_table[LM3532_NUM_RAMP_VALS - 1])
+		return LM3532_NUM_RAMP_VALS - 1;
+
+	return lm3532_get_index(&ramp_table[0], LM3532_NUM_RAMP_VALS,
+				ramp_time);
+}
+
+static int lm3532_led_enable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val = BIT(led_data->control_bank);
+	int ret;
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_enable(led_data->priv->regulator);
+}
+
+static int lm3532_led_disable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val = BIT(led_data->control_bank);
+	int ret;
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ~ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_disable(led_data->priv->regulator);
+}
+
+static int lm3532_brightness_set(struct led_classdev *led_cdev,
+				 enum led_brightness brt_val)
+{
+	struct lm3532_led *led =
+			container_of(led_cdev, struct lm3532_led, led_dev);
+	u8 brightness_reg;
+	int ret;
+
+	mutex_lock(&led->priv->lock);
+
+	if (led->mode == LM3532_BL_MODE_ALS) {
+		if (brt_val > LED_OFF)
+			ret = lm3532_led_enable(led);
+		else
+			ret = lm3532_led_disable(led);
+
+		goto unlock;
+	}
+
+	if (brt_val == LED_OFF) {
+		ret = lm3532_led_disable(led);
+		goto unlock;
+	}
+
+	ret = lm3532_led_enable(led);
+	if (ret)
+		goto unlock;
+
+	brightness_reg = LM3532_REG_CTRL_A_BRT + led->control_bank * 2;
+	brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
+
+	ret = regmap_write(led->priv->regmap, brightness_reg, brt_val);
+
+unlock:
+	mutex_unlock(&led->priv->lock);
+	return ret;
+}
+
+static int lm3532_init_registers(struct lm3532_led *led)
+{
+	struct lm3532_data *drvdata = led->priv;
+	unsigned int runtime_ramp_val;
+	unsigned int output_cfg_val = 0;
+	unsigned int output_cfg_shift = 0;
+	unsigned int output_cfg_mask = 0;
+	int ret, i;
+
+	for (i = 0; i < led->num_leds; i++) {
+		output_cfg_shift = led->led_strings[i] * 2;
+		output_cfg_val |= (led->control_bank << output_cfg_shift);
+		output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
+	}
+
+	ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
+				 output_cfg_mask, output_cfg_val);
+	if (ret)
+		return ret;
+
+	runtime_ramp_val = drvdata->runtime_ramp_up |
+			 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
+
+	return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
+			    runtime_ramp_val);
+}
+
+static int lm3532_als_configure(struct lm3532_data *priv,
+				struct lm3532_led *led)
+{
+	struct lm3532_als_data *als = priv->als_data;
+	u32 als_vmin, als_vmax, als_vstep;
+	int zone_reg = LM3532_REG_ZN_0_HI;
+	int brightnes_config_reg;
+	int ret;
+	int i;
+
+	als_vmin = als->als_vmin;
+	als_vmax = als->als_vmax;
+
+	als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
+
+	for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
+		als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
+				LED_FULL) / 1000;
+		als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
+				als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
+
+		zone_reg = LM3532_REG_ZN_0_HI + i * 2;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
+		if (ret)
+			return ret;
+
+		zone_reg += 1;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
+		if (ret)
+			return ret;
+	}
+
+	als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
+		(als->als_input_mode << LM3532_ALS_SEL_SHIFT));
+
+	ret = regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
+	if (ret)
+		return ret;
+
+	brightnes_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2;
+
+	return regmap_update_bits(priv->regmap, brightnes_config_reg,
+				  LM3532_I2C_CTRL, LM3532_ALS_CTRL);
+}
+
+static int lm3532_parse_als(struct lm3532_data *priv)
+{
+	struct lm3532_als_data *als;
+	int als_avg_time;
+	int als_impedance;
+	int ret;
+
+	als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
+	if (als == NULL)
+		return -ENOMEM;
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als-vmin",
+				       &als->als_vmin);
+	if (ret)
+		als->als_vmin = 0;
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als-vmax",
+				       &als->als_vmax);
+	if (ret)
+		als->als_vmax = LM3532_ALS_WINDOW_mV;
+
+	if (als->als_vmax > LM3532_ALS_WINDOW_mV) {
+		ret = -EINVAL;
+		return ret;
+	}
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als1-imp-sel",
+				      &als_impedance);
+	if (ret)
+		als->als1_imp_sel = 0;
+	else
+		als->als1_imp_sel = lm3532_get_als_imp_index(als_impedance);
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als2-imp-sel",
+				      &als_impedance);
+	if (ret)
+		als->als2_imp_sel = 0;
+	else
+		als->als2_imp_sel = lm3532_get_als_imp_index(als_impedance);
+
+	ret = device_property_read_u32(&priv->client->dev, "ti,als-avrg-time-us",
+				      &als_avg_time);
+	if (ret)
+		als->als_avrg_time = 0;
+	else
+		als->als_avrg_time = lm3532_get_als_avg_index(als_avg_time);
+
+	ret = device_property_read_u8(&priv->client->dev, "ti,als-input-mode",
+				      &als->als_input_mode);
+	if (ret)
+		als->als_input_mode = 0;
+
+	if (als->als_input_mode > LM3532_BL_MODE_ALS) {
+		ret = -EINVAL;
+		return ret;
+	}
+
+	priv->als_data = als;
+
+	return ret;
+}
+
+static int lm3532_parse_node(struct lm3532_data *priv)
+{
+	struct fwnode_handle *child = NULL;
+	struct lm3532_led *led;
+	const char *name;
+	int control_bank;
+	u32 ramp_time;
+	size_t i = 0;
+	int ret;
+
+	priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
+						   "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->enable_gpio))
+		priv->enable_gpio = NULL;
+
+	priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
+	if (IS_ERR(priv->regulator))
+		priv->regulator = NULL;
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-up-us",
+				       &ramp_time);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-up-ms property missing\n");
+	else
+		priv->runtime_ramp_up = lm3532_get_ramp_index(ramp_time);
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-down-us",
+				       &ramp_time);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+	else
+		priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time);
+
+	device_for_each_child_node(priv->dev, child) {
+		led = &priv->leds[i];
+
+		ret = fwnode_property_read_u32(child, "reg", &control_bank);
+		if (ret) {
+			dev_err(&priv->client->dev, "reg property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (control_bank > LM3532_CONTROL_C) {
+			dev_err(&priv->client->dev, "Control bank invalid\n");
+			continue;
+		}
+
+		led->control_bank = control_bank;
+
+		ret = fwnode_property_read_u32(child, "ti,led-mode",
+					       &led->mode);
+		if (ret) {
+			dev_err(&priv->client->dev, "ti,led-mode property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (led->mode == LM3532_BL_MODE_ALS) {
+			ret = lm3532_parse_als(priv);
+			if (ret)
+				dev_err(&priv->client->dev, "Failed to parse als\n");
+			else
+				lm3532_als_configure(priv, led);
+		}
+
+		led->num_leds = fwnode_property_read_u32_array(child,
+							       "led-sources",
+							       NULL, 0);
+
+		if (led->num_leds > LM3532_MAX_LED_STRINGS) {
+			dev_err(&priv->client->dev, "To many LED string defined\n");
+			continue;
+		}
+
+		ret = fwnode_property_read_u32_array(child, "led-sources",
+						    led->led_strings,
+						    led->num_leds);
+		if (ret) {
+			dev_err(&priv->client->dev, "led-sources property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		fwnode_property_read_string(child, "linux,default-trigger",
+					    &led->led_dev.default_trigger);
+
+		ret = fwnode_property_read_string(child, "label", &name);
+		if (ret)
+			snprintf(led->label, sizeof(led->label),
+				"%s::", priv->client->name);
+		else
+			snprintf(led->label, sizeof(led->label),
+				 "%s:%s", priv->client->name, name);
+
+		led->priv = priv;
+		led->led_dev.name = led->label;
+		led->led_dev.brightness_set_blocking = lm3532_brightness_set;
+
+		ret = devm_led_classdev_register(priv->dev, &led->led_dev);
+		if (ret) {
+			dev_err(&priv->client->dev, "led register err: %d\n",
+				ret);
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		lm3532_init_registers(led);
+
+		i++;
+	}
+
+child_out:
+	return ret;
+}
+
+static int lm3532_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct lm3532_data *drvdata;
+	int ret = 0;
+	int count;
+
+	count = device_get_child_node_count(&client->dev);
+	if (!count) {
+		dev_err(&client->dev, "LEDs are not defined in device tree!");
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
+			   GFP_KERNEL);
+	if (drvdata == NULL)
+		return -ENOMEM;
+
+	drvdata->client = client;
+	drvdata->dev = &client->dev;
+
+	drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
+	if (IS_ERR(drvdata->regmap)) {
+		ret = PTR_ERR(drvdata->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	mutex_init(&drvdata->lock);
+	i2c_set_clientdata(client, drvdata);
+
+	ret = lm3532_parse_node(drvdata);
+	if (ret) {
+		dev_err(&client->dev, "Failed to parse node\n");
+		return ret;
+	}
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 1);
+
+	return ret;
+}
+
+static int lm3532_remove(struct i2c_client *client)
+{
+	struct lm3532_data *drvdata = i2c_get_clientdata(client);
+
+	mutex_destroy(&drvdata->lock);
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 0);
+
+	return 0;
+}
+
+static const struct of_device_id of_lm3532_leds_match[] = {
+	{ .compatible = "ti,lm3532", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
+
+static const struct i2c_device_id lm3532_id[] = {
+	{LM3532_NAME, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, lm3532_id);
+
+static struct i2c_driver lm3532_i2c_driver = {
+	.probe = lm3532_probe,
+	.remove = lm3532_remove,
+	.id_table = lm3532_id,
+	.driver = {
+		.name = LM3532_NAME,
+		.of_match_table = of_lm3532_leds_match,
+	},
+};
+module_i2c_driver(lm3532_i2c_driver);
+
+MODULE_DESCRIPTION("Back Light driver for LM3532");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
-- 
2.21.0.5.gaeb582a983


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

* Re: [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
  2019-03-21 14:28 ` Dan Murphy
@ 2019-03-21 14:30   ` Dan Murphy
  -1 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:30 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

All

On 3/21/19 9:28 AM, Dan Murphy wrote:
> Add the lm3532 device tree documentation.
> Remove lm3532 device tree reference from the ti_lmu devicetree
> documentation.
> 
> With the addition of the dedicated lm3532 documentation the device
> can be removed from the ti_lmu.txt.
> 
> The reason for this is that the lm3532 dt documentation now defines
> the ability to control LED output strings against different control
> banks or groups multiple strings to be controlled by a single control
> bank.
> 
> Another addition was for ALS lighting control and configuration.  The
> LM3532 has a feature that can take in the ALS reading from 2 separate
> ALS devices and adjust the brightness on the strings that are configured
> to support this feature.
> 
> Finally the device specific properties were moved to the parent node as these
> properties are not control bank configurable.  These include the runtime ramp
> and the ALS configuration.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v5 - Moved ramping range to below property definition, updated keyboard label -
> https://lore.kernel.org/patchwork/patch/1050412/
> 
<snip>

I missed the v5 in $subject

But this patch set is v5

Dan
-- 
------------------
Dan Murphy

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

* Re: [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
@ 2019-03-21 14:30   ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-21 14:30 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

All

On 3/21/19 9:28 AM, Dan Murphy wrote:
> Add the lm3532 device tree documentation.
> Remove lm3532 device tree reference from the ti_lmu devicetree
> documentation.
> 
> With the addition of the dedicated lm3532 documentation the device
> can be removed from the ti_lmu.txt.
> 
> The reason for this is that the lm3532 dt documentation now defines
> the ability to control LED output strings against different control
> banks or groups multiple strings to be controlled by a single control
> bank.
> 
> Another addition was for ALS lighting control and configuration.  The
> LM3532 has a feature that can take in the ALS reading from 2 separate
> ALS devices and adjust the brightness on the strings that are configured
> to support this feature.
> 
> Finally the device specific properties were moved to the parent node as these
> properties are not control bank configurable.  These include the runtime ramp
> and the ALS configuration.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v5 - Moved ramping range to below property definition, updated keyboard label -
> https://lore.kernel.org/patchwork/patch/1050412/
> 
<snip>

I missed the v5 in $subject

But this patch set is v5

Dan
-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-21 14:28   ` Dan Murphy
  (?)
@ 2019-03-22 22:16   ` Tony Lindgren
  2019-03-25 12:35       ` Dan Murphy
  -1 siblings, 1 reply; 51+ messages in thread
From: Tony Lindgren @ 2019-03-22 22:16 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

Hi,

* Dan Murphy <dmurphy@ti.com> [190321 14:29]:
> Introduce the Texas Instruments LM3532 White LED driver.
> The driver supports ALS configurability or manual brightness
> control.
> 
> The driver also supports associating LED strings with specific
> control banks in a group or as individually controlled strings.

Thanks for getting this driver done. I need help a bit using
this though.. What's the glue to the drm driver?

I can control the backlight brightness just fine via /sys, and
backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
but /sys/class/backlight is empty and looks like drm can't find it.

Do I need to enable some additional driver(s) to get this to work
with the drm driver?

Regards,

Tony

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-03-21 14:28   ` Dan Murphy
  (?)
@ 2019-03-23 16:47   ` Jacek Anaszewski
  2019-03-25  7:53     ` Lee Jones
  -1 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-03-23 16:47 UTC (permalink / raw)
  To: lee.jones
  Cc: Dan Murphy, robh+dt, pavel, tony, devicetree, linux-kernel, linux-leds

Hi Lee,

Can we have your ack for this going via LED tree, please?

Best regards,
Jacek Anaszewski

On 3/21/19 3:28 PM, Dan Murphy wrote:
> Remove the LM3532 backlight driver references from the ti-lmu
> code as dedicated driver support is available.
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v5 - No changes - https://lore.kernel.org/patchwork/patch/1050411/
> 
> v4 - No changes - https://lore.kernel.org/patchwork/patch/1050123/
> v3 - No changes - https://lore.kernel.org/patchwork/patch/1049025/
> v2 - Removed LM3532 register definitions from ti-lmu-register - https://lore.kernel.org/patchwork/patch/1048808/
> 
>   drivers/mfd/ti-lmu.c                | 11 --------
>   include/linux/mfd/ti-lmu-register.h | 44 -----------------------------
>   include/linux/mfd/ti-lmu.h          |  1 -
>   3 files changed, 56 deletions(-)
[...]

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-03-23 16:47   ` Jacek Anaszewski
@ 2019-03-25  7:53     ` Lee Jones
  2019-03-25 21:11       ` Jacek Anaszewski
  0 siblings, 1 reply; 51+ messages in thread
From: Lee Jones @ 2019-03-25  7:53 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Dan Murphy, robh+dt, pavel, tony, devicetree, linux-kernel, linux-leds

On Sat, 23 Mar 2019, Jacek Anaszewski wrote:

> Hi Lee,
> 
> Can we have your ack for this going via LED tree, please?

Patch looks okay.

You can take it through the LED, but if you do I will need you to send
me a pull-request to a minimised immutable branch please.

If you cannot do this, I can apply the set and provide the same to
you.

If you choose the former:

  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

Please let me know what you decide

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
  2019-03-21 14:28 ` Dan Murphy
                   ` (4 preceding siblings ...)
  (?)
@ 2019-03-25  7:54 ` Lee Jones
  -1 siblings, 0 replies; 51+ messages in thread
From: Lee Jones @ 2019-03-25  7:54 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, tony, devicetree, linux-kernel,
	linux-leds

On Thu, 21 Mar 2019, Dan Murphy wrote:

> Add the lm3532 device tree documentation.
> Remove lm3532 device tree reference from the ti_lmu devicetree
> documentation.
> 
> With the addition of the dedicated lm3532 documentation the device
> can be removed from the ti_lmu.txt.
> 
> The reason for this is that the lm3532 dt documentation now defines
> the ability to control LED output strings against different control
> banks or groups multiple strings to be controlled by a single control
> bank.
> 
> Another addition was for ALS lighting control and configuration.  The
> LM3532 has a feature that can take in the ALS reading from 2 separate
> ALS devices and adjust the brightness on the strings that are configured
> to support this feature.
> 
> Finally the device specific properties were moved to the parent node as these
> properties are not control bank configurable.  These include the runtime ramp
> and the ALS configuration.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v5 - Moved ramping range to below property definition, updated keyboard label -
> https://lore.kernel.org/patchwork/patch/1050412/
> 
> v4 - Appended "ti," to TI specific properties, add enable gpio documentation,
> removed an example, moved ramp to optional parent properties - https://lore.kernel.org/patchwork/patch/1050122/
> v3 - No changes - https://lore.kernel.org/patchwork/patch/1049026/
> v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
> added ranges for variable properties, I did not change the label - https://lore.kernel.org/patchwork/patch/1048805/
> 
>  .../devicetree/bindings/leds/leds-lm3532.txt  | 101 ++++++++++++++++++
>  .../devicetree/bindings/mfd/ti-lmu.txt        |  20 ----
>  2 files changed, 101 insertions(+), 20 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/leds/leds-lm3532.txt

Same for this patch:

  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-22 22:16   ` Tony Lindgren
@ 2019-03-25 12:35       ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-25 12:35 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

Tony

On 3/22/19 5:16 PM, Tony Lindgren wrote:
> Hi,
> 
> * Dan Murphy <dmurphy@ti.com> [190321 14:29]:
>> Introduce the Texas Instruments LM3532 White LED driver.
>> The driver supports ALS configurability or manual brightness
>> control.
>>
>> The driver also supports associating LED strings with specific
>> control banks in a group or as individually controlled strings.
> 
> Thanks for getting this driver done. I need help a bit using
> this though.. What's the glue to the drm driver?
> 
> I can control the backlight brightness just fine via /sys, and
> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
> but /sys/class/backlight is empty and looks like drm can't find it.
> 
> Do I need to enable some additional driver(s) to get this to work
> with the drm driver?
> 

Can you dump or point to the defconfig?

Dan

> Regards,
> 
> Tony
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-25 12:35       ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-25 12:35 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

Tony

On 3/22/19 5:16 PM, Tony Lindgren wrote:
> Hi,
> 
> * Dan Murphy <dmurphy@ti.com> [190321 14:29]:
>> Introduce the Texas Instruments LM3532 White LED driver.
>> The driver supports ALS configurability or manual brightness
>> control.
>>
>> The driver also supports associating LED strings with specific
>> control banks in a group or as individually controlled strings.
> 
> Thanks for getting this driver done. I need help a bit using
> this though.. What's the glue to the drm driver?
> 
> I can control the backlight brightness just fine via /sys, and
> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
> but /sys/class/backlight is empty and looks like drm can't find it.
> 
> Do I need to enable some additional driver(s) to get this to work
> with the drm driver?
> 

Can you dump or point to the defconfig?

Dan

> Regards,
> 
> Tony
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-25 12:35       ` Dan Murphy
  (?)
@ 2019-03-25 14:54       ` Tony Lindgren
  2019-03-25 16:01           ` Dan Murphy
  -1 siblings, 1 reply; 51+ messages in thread
From: Tony Lindgren @ 2019-03-25 14:54 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

* Dan Murphy <dmurphy@ti.com> [190325 12:36]:
> On 3/22/19 5:16 PM, Tony Lindgren wrote:
> > I can control the backlight brightness just fine via /sys, and
> > backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
> > but /sys/class/backlight is empty and looks like drm can't find it.
> > 
> > Do I need to enable some additional driver(s) to get this to work
> > with the drm driver?
> > 
> 
> Can you dump or point to the defconfig?

This is just with the omap2plus_defconfig as in the droid4-pending-v5.0
test branch below [0]. That branch has Sebastian's drm patches. The
branch also has the older ti-lmu patches that I reverted for testing
before applying your new series and enabling it in .config.

The drm driver (drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c) just
does:

backlight = of_parse_phandle(node, "backlight", 0);
...

That should still work the same, right?

Regards,

Tony


[0] https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git/log/?h=droid4-pending-v5.0

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-25 14:54       ` Tony Lindgren
@ 2019-03-25 16:01           ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-25 16:01 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

On 3/25/19 9:54 AM, Tony Lindgren wrote:
> * Dan Murphy <dmurphy@ti.com> [190325 12:36]:
>> On 3/22/19 5:16 PM, Tony Lindgren wrote:
>>> I can control the backlight brightness just fine via /sys, and
>>> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
>>> but /sys/class/backlight is empty and looks like drm can't find it.
>>>
>>> Do I need to enable some additional driver(s) to get this to work
>>> with the drm driver?
>>>
>>
>> Can you dump or point to the defconfig?
> 
> This is just with the omap2plus_defconfig as in the droid4-pending-v5.0
> test branch below [0]. That branch has Sebastian's drm patches. The
> branch also has the older ti-lmu patches that I reverted for testing
> before applying your new series and enabling it in .config.
> 
> The drm driver (drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c) just
> does:
> 
> backlight = of_parse_phandle(node, "backlight", 0);
> ...
> 
> That should still work the same, right?

Yes it should still work the same.
I did not change the node name.
So the DRM driver should find the node.

Dan

> 
> Regards,
> 
> Tony
> 
> 
> [0] https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git/log/?h=droid4-pending-v5.0
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-25 16:01           ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-25 16:01 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

On 3/25/19 9:54 AM, Tony Lindgren wrote:
> * Dan Murphy <dmurphy@ti.com> [190325 12:36]:
>> On 3/22/19 5:16 PM, Tony Lindgren wrote:
>>> I can control the backlight brightness just fine via /sys, and
>>> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
>>> but /sys/class/backlight is empty and looks like drm can't find it.
>>>
>>> Do I need to enable some additional driver(s) to get this to work
>>> with the drm driver?
>>>
>>
>> Can you dump or point to the defconfig?
> 
> This is just with the omap2plus_defconfig as in the droid4-pending-v5.0
> test branch below [0]. That branch has Sebastian's drm patches. The
> branch also has the older ti-lmu patches that I reverted for testing
> before applying your new series and enabling it in .config.
> 
> The drm driver (drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c) just
> does:
> 
> backlight = of_parse_phandle(node, "backlight", 0);
> ...
> 
> That should still work the same, right?

Yes it should still work the same.
I did not change the node name.
So the DRM driver should find the node.

Dan

> 
> Regards,
> 
> Tony
> 
> 
> [0] https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git/log/?h=droid4-pending-v5.0
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-03-25  7:53     ` Lee Jones
@ 2019-03-25 21:11       ` Jacek Anaszewski
  2019-04-03  7:57         ` Lee Jones
  0 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-03-25 21:11 UTC (permalink / raw)
  To: Lee Jones
  Cc: Dan Murphy, robh+dt, pavel, tony, devicetree, linux-kernel, linux-leds

On 3/25/19 8:53 AM, Lee Jones wrote:
> On Sat, 23 Mar 2019, Jacek Anaszewski wrote:
> 
>> Hi Lee,
>>
>> Can we have your ack for this going via LED tree, please?
> 
> Patch looks okay.
> 
> You can take it through the LED, but if you do I will need you to send
> me a pull-request to a minimised immutable branch please.
> 
> If you cannot do this, I can apply the set and provide the same to
> you.
> 
> If you choose the former:
> 
>    Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>
> 
> Please let me know what you decide
> 

I've been exposing integration branches in the past, but after Linus'
message [0] I have my doubts now. I wonder if it wouldn't make more
sense if I just took the patches, and you'd cherry-pick them only in
case such a need occurs. This way we would avoid this whole merge
noise, which in an optimistic and very plausible case will not be needed
at all.

[0] https://lkml.org/lkml/2017/4/19/1104

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-25 16:01           ` Dan Murphy
  (?)
@ 2019-03-28 21:04           ` Sebastian Reichel
  2019-04-03 20:06             ` Tony Lindgren
  -1 siblings, 1 reply; 51+ messages in thread
From: Sebastian Reichel @ 2019-03-28 21:04 UTC (permalink / raw)
  To: Dan Murphy
  Cc: Tony Lindgren, robh+dt, jacek.anaszewski, pavel, lee.jones,
	devicetree, linux-kernel, linux-leds

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

Hi,

On Mon, Mar 25, 2019 at 11:01:18AM -0500, Dan Murphy wrote:
> On 3/25/19 9:54 AM, Tony Lindgren wrote:
> > * Dan Murphy <dmurphy@ti.com> [190325 12:36]:
> >> On 3/22/19 5:16 PM, Tony Lindgren wrote:
> >>> I can control the backlight brightness just fine via /sys, and
> >>> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
> >>> but /sys/class/backlight is empty and looks like drm can't find it.
> >>>
> >>> Do I need to enable some additional driver(s) to get this to work
> >>> with the drm driver?
> >>>
> >>
> >> Can you dump or point to the defconfig?
> > 
> > This is just with the omap2plus_defconfig as in the droid4-pending-v5.0
> > test branch below [0]. That branch has Sebastian's drm patches. The
> > branch also has the older ti-lmu patches that I reverted for testing
> > before applying your new series and enabling it in .config.
> > 
> > The drm driver (drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c) just
> > does:
> > 
> > backlight = of_parse_phandle(node, "backlight", 0);
> > ...
> > 
> > That should still work the same, right?
> 
> Yes it should still work the same.
> I did not change the node name.
> So the DRM driver should find the node.

This will not work, since the next line tries to get it as a
backlight device, but it's an LED device instead:

of_find_backlight_by_node(backlight);

I suppose the backlight device could be instantiated on top
of the LED device somehow.

(sorry for slow responses; I'm quite busy right now)

-- Sebastian

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

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-03-25 21:11       ` Jacek Anaszewski
@ 2019-04-03  7:57         ` Lee Jones
  2019-04-03 17:45           ` Jacek Anaszewski
  0 siblings, 1 reply; 51+ messages in thread
From: Lee Jones @ 2019-04-03  7:57 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Dan Murphy, robh+dt, pavel, tony, devicetree, linux-kernel, linux-leds

On Mon, 25 Mar 2019, Jacek Anaszewski wrote:

> On 3/25/19 8:53 AM, Lee Jones wrote:
> > On Sat, 23 Mar 2019, Jacek Anaszewski wrote:
> > 
> > > Hi Lee,
> > > 
> > > Can we have your ack for this going via LED tree, please?
> > 
> > Patch looks okay.
> > 
> > You can take it through the LED, but if you do I will need you to send
> > me a pull-request to a minimised immutable branch please.
> > 
> > If you cannot do this, I can apply the set and provide the same to
> > you.
> > 
> > If you choose the former:
> > 
> >    Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>
> > 
> > Please let me know what you decide
> > 
> 
> I've been exposing integration branches in the past, but after Linus'
> message [0] I have my doubts now. I wonder if it wouldn't make more
> sense if I just took the patches, and you'd cherry-pick them only in
> case such a need occurs. This way we would avoid this whole merge
> noise, which in an optimistic and very plausible case will not be needed
> at all.
> 
> [0] https://lkml.org/lkml/2017/4/19/1104

That email is 2 years old, and does not seem relevant to what we're
trying to achieve.  I've only ever had issues when *not* creating
immutable branches for these, cross subsystem scenarios.  The
shared branches I create are always minimalist and never change.

I'm happy to take the patches and create a suitable pull-request for
you if you are uncomfortable with the process.  I just need your Ack
to do so.  Up to you.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-04-03  7:57         ` Lee Jones
@ 2019-04-03 17:45           ` Jacek Anaszewski
  2019-04-04  2:44             ` Lee Jones
  0 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-04-03 17:45 UTC (permalink / raw)
  To: Lee Jones
  Cc: Dan Murphy, robh+dt, pavel, tony, devicetree, linux-kernel, linux-leds

On 4/3/19 9:57 AM, Lee Jones wrote:
> On Mon, 25 Mar 2019, Jacek Anaszewski wrote:
> 
>> On 3/25/19 8:53 AM, Lee Jones wrote:
>>> On Sat, 23 Mar 2019, Jacek Anaszewski wrote:
>>>
>>>> Hi Lee,
>>>>
>>>> Can we have your ack for this going via LED tree, please?
>>>
>>> Patch looks okay.
>>>
>>> You can take it through the LED, but if you do I will need you to send
>>> me a pull-request to a minimised immutable branch please.
>>>
>>> If you cannot do this, I can apply the set and provide the same to
>>> you.
>>>
>>> If you choose the former:
>>>
>>>     Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>
>>>
>>> Please let me know what you decide
>>>
>>
>> I've been exposing integration branches in the past, but after Linus'
>> message [0] I have my doubts now. I wonder if it wouldn't make more
>> sense if I just took the patches, and you'd cherry-pick them only in
>> case such a need occurs. This way we would avoid this whole merge
>> noise, which in an optimistic and very plausible case will not be needed
>> at all.
>>
>> [0] https://lkml.org/lkml/2017/4/19/1104
> 
> That email is 2 years old, and does not seem relevant to what we're
> trying to achieve.  I've only ever had issues when *not* creating
> immutable branches for these, cross subsystem scenarios.  The
> shared branches I create are always minimalist and never change.
> 
> I'm happy to take the patches and create a suitable pull-request for
> you if you are uncomfortable with the process.  I just need your Ack
> to do so.  Up to you.

I don't have any problem with the process. The clear gain of cherry
picking is more linear history. And the branch can be always created
when such a need occurs in linux-next.

That being said, I will send you a pull request once we sort out
the problem with obtaining a reference to the backlight node.

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-28 21:04           ` Sebastian Reichel
@ 2019-04-03 20:06             ` Tony Lindgren
  2019-04-03 23:55               ` Tony Lindgren
  0 siblings, 1 reply; 51+ messages in thread
From: Tony Lindgren @ 2019-04-03 20:06 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Dan Murphy, robh+dt, jacek.anaszewski, pavel, lee.jones,
	devicetree, linux-kernel, linux-leds

* Sebastian Reichel <sre@kernel.org> [190329 05:36]:
> Hi,
> 
> On Mon, Mar 25, 2019 at 11:01:18AM -0500, Dan Murphy wrote:
> > On 3/25/19 9:54 AM, Tony Lindgren wrote:
> > > * Dan Murphy <dmurphy@ti.com> [190325 12:36]:
> > >> On 3/22/19 5:16 PM, Tony Lindgren wrote:
> > >>> I can control the backlight brightness just fine via /sys, and
> > >>> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
> > >>> but /sys/class/backlight is empty and looks like drm can't find it.
> > >>>
> > >>> Do I need to enable some additional driver(s) to get this to work
> > >>> with the drm driver?
> > >>>
> > >>
> > >> Can you dump or point to the defconfig?
> > > 
> > > This is just with the omap2plus_defconfig as in the droid4-pending-v5.0
> > > test branch below [0]. That branch has Sebastian's drm patches. The
> > > branch also has the older ti-lmu patches that I reverted for testing
> > > before applying your new series and enabling it in .config.
> > > 
> > > The drm driver (drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c) just
> > > does:
> > > 
> > > backlight = of_parse_phandle(node, "backlight", 0);
> > > ...
> > > 
> > > That should still work the same, right?
> > 
> > Yes it should still work the same.
> > I did not change the node name.
> > So the DRM driver should find the node.
> 
> This will not work, since the next line tries to get it as a
> backlight device, but it's an LED device instead:
> 
> of_find_backlight_by_node(backlight);
> 
> I suppose the backlight device could be instantiated on top
> of the LED device somehow.

Hmm yeah I thought setting the ledtrig-backlight for it
would do the trick. But after thinking about it there might
be some backlight lifecycle issues with that where everything
would need to be torn down for the panel to change the
backlight trigger. I think the panel driver(s) assume the
backlight to always be there at probe time. Well this is
just based on just guessing.. I might be wrong.

I have no issues using of_find_backlight_by_node() like
other panels.

> (sorry for slow responses; I'm quite busy right now)

No problem.

Regards,

Tony

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-04-03 20:06             ` Tony Lindgren
@ 2019-04-03 23:55               ` Tony Lindgren
  0 siblings, 0 replies; 51+ messages in thread
From: Tony Lindgren @ 2019-04-03 23:55 UTC (permalink / raw)
  To: Sebastian Reichel
  Cc: Dan Murphy, robh+dt, jacek.anaszewski, pavel, lee.jones,
	devicetree, linux-kernel, linux-leds

* Tony Lindgren <tony@atomide.com> [190403 13:06]:
> * Sebastian Reichel <sre@kernel.org> [190329 05:36]:
> > Hi,
> > 
> > On Mon, Mar 25, 2019 at 11:01:18AM -0500, Dan Murphy wrote:
> > > On 3/25/19 9:54 AM, Tony Lindgren wrote:
> > > > * Dan Murphy <dmurphy@ti.com> [190325 12:36]:
> > > >> On 3/22/19 5:16 PM, Tony Lindgren wrote:
> > > >>> I can control the backlight brightness just fine via /sys, and
> > > >>> backlight shows up as the trigger in /sys/class/leds/lm3532:backlight,
> > > >>> but /sys/class/backlight is empty and looks like drm can't find it.
> > > >>>
> > > >>> Do I need to enable some additional driver(s) to get this to work
> > > >>> with the drm driver?
> > > >>>
> > > >>
> > > >> Can you dump or point to the defconfig?
> > > > 
> > > > This is just with the omap2plus_defconfig as in the droid4-pending-v5.0
> > > > test branch below [0]. That branch has Sebastian's drm patches. The
> > > > branch also has the older ti-lmu patches that I reverted for testing
> > > > before applying your new series and enabling it in .config.
> > > > 
> > > > The drm driver (drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c) just
> > > > does:
> > > > 
> > > > backlight = of_parse_phandle(node, "backlight", 0);
> > > > ...
> > > > 
> > > > That should still work the same, right?
> > > 
> > > Yes it should still work the same.
> > > I did not change the node name.
> > > So the DRM driver should find the node.
> > 
> > This will not work, since the next line tries to get it as a
> > backlight device, but it's an LED device instead:
> > 
> > of_find_backlight_by_node(backlight);
> > 
> > I suppose the backlight device could be instantiated on top
> > of the LED device somehow.
> 
> Hmm yeah I thought setting the ledtrig-backlight for it
> would do the trick. But after thinking about it there might
> be some backlight lifecycle issues with that where everything
> would need to be torn down for the panel to change the
> backlight trigger. I think the panel driver(s) assume the
> backlight to always be there at probe time. Well this is
> just based on just guessing.. I might be wrong.
> 
> I have no issues using of_find_backlight_by_node() like
> other panels.

Oh sorry, I did not read the code before replying.
I somehow thought of_find_backlight_by_node() should be
used for LEDs but that's for backlight still :)

Looks like all we need to do is leave out the backlight
line from dts, we don't need to do anything with
of_find_backlight_by_node(). Having ledtrig-backlight
configured means lm3532 will just use the notifier
for FB_EVENT_BLANK.

I'll reply to the dts patch and ack the test, looks
like we're good to go as far as I'm concerned.

Regards,

Tony

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

* Re: [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties
  2019-03-21 14:28   ` Dan Murphy
  (?)
@ 2019-04-04  0:03   ` Tony Lindgren
  -1 siblings, 0 replies; 51+ messages in thread
From: Tony Lindgren @ 2019-04-04  0:03 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds

Hi,

* Dan Murphy <dmurphy@ti.com> [190321 14:29]:
> Update the properties for the lm3532 device node for droid4.
> With this change the backlight LED string and the keypad
> LED strings will be controlled separately.

We also need the following incremental change to prevent
panel-dsi-cm trying to use of_find_backlight_by_node().
We have ledtrig-backlight use FB_EVENT_BLANK, and I
guess more events can be added there as needed.

There should be no dependency to the driver changes with
this patch, so it's probably best that I queue this dts
patch separately. I'll fold in the following change too
assuming no more comments.

Regards,

Tony

8< -----------------
diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
+++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
@@ -214,7 +214,6 @@
 
 		width-mm = <50>;
 		height-mm = <89>;
-		backlight = <&lcd_backlight>;
 
 		panel-timing {
 			clock-frequency = <0>;		/* Calculated by dsi */

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

* Re: [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
  2019-03-21 14:28 ` Dan Murphy
                   ` (5 preceding siblings ...)
  (?)
@ 2019-04-04  0:04 ` Tony Lindgren
  -1 siblings, 0 replies; 51+ messages in thread
From: Tony Lindgren @ 2019-04-04  0:04 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds

* Dan Murphy <dmurphy@ti.com> [190321 14:29]:
> Add the lm3532 device tree documentation.
> Remove lm3532 device tree reference from the ti_lmu devicetree
> documentation.
> 
> With the addition of the dedicated lm3532 documentation the device
> can be removed from the ti_lmu.txt.
> 
> The reason for this is that the lm3532 dt documentation now defines
> the ability to control LED output strings against different control
> banks or groups multiple strings to be controlled by a single control
> bank.
> 
> Another addition was for ALS lighting control and configuration.  The
> LM3532 has a feature that can take in the ALS reading from 2 separate
> ALS devices and adjust the brightness on the strings that are configured
> to support this feature.
> 
> Finally the device specific properties were moved to the parent node as these
> properties are not control bank configurable.  These include the runtime ramp
> and the ALS configuration.

Acked-by: Tony Lindgren <tony@atomide.com>

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-03-21 14:28   ` Dan Murphy
  (?)
  (?)
@ 2019-04-04  0:04   ` Tony Lindgren
  -1 siblings, 0 replies; 51+ messages in thread
From: Tony Lindgren @ 2019-04-04  0:04 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds

* Dan Murphy <dmurphy@ti.com> [190321 14:29]:
> Remove the LM3532 backlight driver references from the ti-lmu
> code as dedicated driver support is available.

Acked-by: Tony Lindgren <tony@atomide.com>

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-21 14:28   ` Dan Murphy
  (?)
  (?)
@ 2019-04-04  0:09   ` Tony Lindgren
  2019-04-04 18:48     ` Jacek Anaszewski
  -1 siblings, 1 reply; 51+ messages in thread
From: Tony Lindgren @ 2019-04-04  0:09 UTC (permalink / raw)
  To: Dan Murphy
  Cc: robh+dt, jacek.anaszewski, pavel, lee.jones, devicetree,
	linux-kernel, linux-leds, Sebastian Reichel

* Dan Murphy <dmurphy@ti.com> [190321 14:29]:
> Introduce the Texas Instruments LM3532 White LED driver.
> The driver supports ALS configurability or manual brightness
> control.
> 
> The driver also supports associating LED strings with specific
> control banks in a group or as individually controlled strings.

I'm seeing slightly different naming under /sys/class/leds:

lm3532:backlight
lm3532:platform::kbd_backlight

Not sure if this is correct with the the "platform" and
"::" there for the kbd_backlight?

With the dts change I posted, I've tested this with
linux-next and Sebastian's DSI command mode patches
"[PATCHv6 0/4] omapdrm: DSI command mode panel support".

So feel free to add:

Tested-by: Tony Lindgren <tony@atomide.com>

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

* Re: [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references
  2019-04-03 17:45           ` Jacek Anaszewski
@ 2019-04-04  2:44             ` Lee Jones
  0 siblings, 0 replies; 51+ messages in thread
From: Lee Jones @ 2019-04-04  2:44 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Dan Murphy, robh+dt, pavel, tony, devicetree, linux-kernel, linux-leds

On Wed, 03 Apr 2019, Jacek Anaszewski wrote:

> On 4/3/19 9:57 AM, Lee Jones wrote:
> > On Mon, 25 Mar 2019, Jacek Anaszewski wrote:
> > 
> > > On 3/25/19 8:53 AM, Lee Jones wrote:
> > > > On Sat, 23 Mar 2019, Jacek Anaszewski wrote:
> > > > 
> > > > > Hi Lee,
> > > > > 
> > > > > Can we have your ack for this going via LED tree, please?
> > > > 
> > > > Patch looks okay.
> > > > 
> > > > You can take it through the LED, but if you do I will need you to send
> > > > me a pull-request to a minimised immutable branch please.
> > > > 
> > > > If you cannot do this, I can apply the set and provide the same to
> > > > you.
> > > > 
> > > > If you choose the former:
> > > > 
> > > >     Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>
> > > > 
> > > > Please let me know what you decide
> > > > 
> > > 
> > > I've been exposing integration branches in the past, but after Linus'
> > > message [0] I have my doubts now. I wonder if it wouldn't make more
> > > sense if I just took the patches, and you'd cherry-pick them only in
> > > case such a need occurs. This way we would avoid this whole merge
> > > noise, which in an optimistic and very plausible case will not be needed
> > > at all.
> > > 
> > > [0] https://lkml.org/lkml/2017/4/19/1104
> > 
> > That email is 2 years old, and does not seem relevant to what we're
> > trying to achieve.  I've only ever had issues when *not* creating
> > immutable branches for these, cross subsystem scenarios.  The
> > shared branches I create are always minimalist and never change.
> > 
> > I'm happy to take the patches and create a suitable pull-request for
> > you if you are uncomfortable with the process.  I just need your Ack
> > to do so.  Up to you.
> 
> I don't have any problem with the process. The clear gain of cherry
> picking is more linear history. And the branch can be always created
> when such a need occurs in linux-next.
> 
> That being said, I will send you a pull request once we sort out
> the problem with obtaining a reference to the backlight node.

Sounds good.  Thanks Jacek.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-04-04  0:09   ` Tony Lindgren
@ 2019-04-04 18:48     ` Jacek Anaszewski
  2019-04-04 19:23         ` Dan Murphy
  0 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-04-04 18:48 UTC (permalink / raw)
  To: Tony Lindgren, Dan Murphy
  Cc: robh+dt, pavel, lee.jones, devicetree, linux-kernel, linux-leds,
	Sebastian Reichel

Hi Tony,

Thanks for the feedback.

On 4/4/19 2:09 AM, Tony Lindgren wrote:
> * Dan Murphy <dmurphy@ti.com> [190321 14:29]:
>> Introduce the Texas Instruments LM3532 White LED driver.
>> The driver supports ALS configurability or manual brightness
>> control.
>>
>> The driver also supports associating LED strings with specific
>> control banks in a group or as individually controlled strings.
> 
> I'm seeing slightly different naming under /sys/class/leds:
> 
> lm3532:backlight
> lm3532:platform::kbd_backlight

The problem is in the "platform:" being a part of DT
label property. It should not be included there if devicename
section is added in the driver.

> 
> Not sure if this is correct with the the "platform" and
> "::" there for the kbd_backlight?
> 
> With the dts change I posted, I've tested this with
> linux-next and Sebastian's DSI command mode patches
> "[PATCHv6 0/4] omapdrm: DSI command mode panel support".
> 
> So feel free to add:
> 
> Tested-by: Tony Lindgren <tony@atomide.com>
> 

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-04-04 18:48     ` Jacek Anaszewski
@ 2019-04-04 19:23         ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-04-04 19:23 UTC (permalink / raw)
  To: Jacek Anaszewski, Tony Lindgren
  Cc: robh+dt, pavel, lee.jones, devicetree, linux-kernel, linux-leds,
	Sebastian Reichel

Tony

On 4/4/19 1:48 PM, Jacek Anaszewski wrote:
> Hi Tony,
> 
> Thanks for the feedback.
> 
> On 4/4/19 2:09 AM, Tony Lindgren wrote:
>> * Dan Murphy <dmurphy@ti.com> [190321 14:29]:
>>> Introduce the Texas Instruments LM3532 White LED driver.
>>> The driver supports ALS configurability or manual brightness
>>> control.
>>>
>>> The driver also supports associating LED strings with specific
>>> control banks in a group or as individually controlled strings.
>>
>> I'm seeing slightly different naming under /sys/class/leds:
>>
>> lm3532:backlight
>> lm3532:platform::kbd_backlight
> 
> The problem is in the "platform:" being a part of DT
> label property. It should not be included there if devicename
> section is added in the driver.
> 

Feel free to make it whatever you want I am not married to the naming convention for Droid 4.
It was a suggestion in the code review

https://lore.kernel.org/patchwork/patch/1048806/

<snip>



-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-04-04 19:23         ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-04-04 19:23 UTC (permalink / raw)
  To: Jacek Anaszewski, Tony Lindgren
  Cc: robh+dt, pavel, lee.jones, devicetree, linux-kernel, linux-leds,
	Sebastian Reichel

Tony

On 4/4/19 1:48 PM, Jacek Anaszewski wrote:
> Hi Tony,
> 
> Thanks for the feedback.
> 
> On 4/4/19 2:09 AM, Tony Lindgren wrote:
>> * Dan Murphy <dmurphy@ti.com> [190321 14:29]:
>>> Introduce the Texas Instruments LM3532 White LED driver.
>>> The driver supports ALS configurability or manual brightness
>>> control.
>>>
>>> The driver also supports associating LED strings with specific
>>> control banks in a group or as individually controlled strings.
>>
>> I'm seeing slightly different naming under /sys/class/leds:
>>
>> lm3532:backlight
>> lm3532:platform::kbd_backlight
> 
> The problem is in the "platform:" being a part of DT
> label property. It should not be included there if devicename
> section is added in the driver.
> 

Feel free to make it whatever you want I am not married to the naming convention for Droid 4.
It was a suggestion in the code review

https://lore.kernel.org/patchwork/patch/1048806/

<snip>



-- 
------------------
Dan Murphy

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

* Re: [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties
  2019-03-21 14:28   ` Dan Murphy
  (?)
  (?)
@ 2019-04-04 20:12   ` Jacek Anaszewski
  2019-04-04 22:00     ` Tony Lindgren
  -1 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-04-04 20:12 UTC (permalink / raw)
  To: Dan Murphy, tony
  Cc: robh+dt, pavel, lee.jones, devicetree, linux-kernel, linux-leds

Tony,

On 3/21/19 3:28 PM, Dan Murphy wrote:
> Update the properties for the lm3532 device node for droid4.
> With this change the backlight LED string and the keypad
> LED strings will be controlled separately.
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
> 
> v5 - No change - https://lore.kernel.org/patchwork/patch/1050409/
> 
> v4 - No change - https://lore.kernel.org/patchwork/patch/1050125/
> v3 - updated keypad label on v1 comment - https://lore.kernel.org/patchwork/patch/1049023/
> v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
> I did not change the label as it is undecided what it could be - https://lore.kernel.org/patchwork/patch/1048806/
> 
>   arch/arm/boot/dts/omap4-droid4-xt894.dts | 26 ++++++++++++++++--------
>   1 file changed, 18 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
> index e21ec929f096..aea206f04f76 100644
> --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
> +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
> @@ -383,20 +383,30 @@
>   };
>   
>   &i2c1 {
> -	lm3532@38 {
> +	led-controller@38 {
>   		compatible = "ti,lm3532";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
>   		reg = <0x38>;
>   
>   		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
>   
> -		lcd_backlight: backlight {
> -			compatible = "ti,lm3532-backlight";
> +		ramp-up-us = <1024>;
> +		ramp-down-us = <8193>;
>   
> -			lcd {
> -				led-sources = <0 1 2>;
> -				ramp-up-msec = <1>;
> -				ramp-down-msec = <0>;
> -			};

Since I'll be creating integration branch for this series,
and it would be good to have this patch in it too, then
I can do the amendments by myself:

> +		lcd_backlight: led@0 {
> +			reg = <0>;
> +			led-sources = <2>;
> +			ti,led-mode = <0>;
> +			label = "backlight";

s/backlight/:backlight/

> +			linux,default-trigger = "backlight";
> +		};
> +
> +		led@1 {
> +			reg = <1>;
> +			led-sources = <1>;
> +			ti,led-mode = <0>;
> +			label = "platform::kbd_backlight";

s/platform::kbd_backlight/:kbd_backlight/

and then send you a pull request.

Would you be OK with that?

>   		};
>   	};
>   };
> 

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties
  2019-04-04 20:12   ` Jacek Anaszewski
@ 2019-04-04 22:00     ` Tony Lindgren
  2019-04-07 18:31       ` Jacek Anaszewski
  0 siblings, 1 reply; 51+ messages in thread
From: Tony Lindgren @ 2019-04-04 22:00 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: Dan Murphy, robh+dt, pavel, lee.jones, devicetree, linux-kernel,
	linux-leds

* Jacek Anaszewski <jacek.anaszewski@gmail.com> [190404 20:12]:
> Tony,
> 
> On 3/21/19 3:28 PM, Dan Murphy wrote:
> > Update the properties for the lm3532 device node for droid4.
> > With this change the backlight LED string and the keypad
> > LED strings will be controlled separately.
> > 
> > Signed-off-by: Dan Murphy <dmurphy@ti.com>
> > ---
> > 
> > v5 - No change - https://lore.kernel.org/patchwork/patch/1050409/
> > 
> > v4 - No change - https://lore.kernel.org/patchwork/patch/1050125/
> > v3 - updated keypad label on v1 comment - https://lore.kernel.org/patchwork/patch/1049023/
> > v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
> > I did not change the label as it is undecided what it could be - https://lore.kernel.org/patchwork/patch/1048806/
> > 
> >   arch/arm/boot/dts/omap4-droid4-xt894.dts | 26 ++++++++++++++++--------
> >   1 file changed, 18 insertions(+), 8 deletions(-)
> > 
> > diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
> > index e21ec929f096..aea206f04f76 100644
> > --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
> > +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
> > @@ -383,20 +383,30 @@
> >   };
> >   &i2c1 {
> > -	lm3532@38 {
> > +	led-controller@38 {
> >   		compatible = "ti,lm3532";
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> >   		reg = <0x38>;
> >   		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
> > -		lcd_backlight: backlight {
> > -			compatible = "ti,lm3532-backlight";
> > +		ramp-up-us = <1024>;
> > +		ramp-down-us = <8193>;
> > -			lcd {
> > -				led-sources = <0 1 2>;
> > -				ramp-up-msec = <1>;
> > -				ramp-down-msec = <0>;
> > -			};
> 
> Since I'll be creating integration branch for this series,
> and it would be good to have this patch in it too, then
> I can do the amendments by myself:
> 
> > +		lcd_backlight: led@0 {
> > +			reg = <0>;
> > +			led-sources = <2>;
> > +			ti,led-mode = <0>;
> > +			label = "backlight";
> 
> s/backlight/:backlight/
> 
> > +			linux,default-trigger = "backlight";
> > +		};
> > +
> > +		led@1 {
> > +			reg = <1>;
> > +			led-sources = <1>;
> > +			ti,led-mode = <0>;
> > +			label = "platform::kbd_backlight";
> 
> s/platform::kbd_backlight/:kbd_backlight/

Yes makes sense to me.

> and then send you a pull request.
> 
> Would you be OK with that?

Sure go for it. Here's my ack for the changes:

Acked-by: Tony Lindgren <tony@atomide.com>

And then for the one liner to fold in below:

Signed-off-by: Tony Lindgren <tony@atomide.com>

8< -------------
diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
--- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
+++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
@@ -214,7 +214,6 @@
 
 		width-mm = <50>;
 		height-mm = <89>;
-		backlight = <&lcd_backlight>;
 
 		panel-timing {
 			clock-frequency = <0>;		/* Calculated by dsi */

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

* Re: [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties
  2019-04-04 22:00     ` Tony Lindgren
@ 2019-04-07 18:31       ` Jacek Anaszewski
  0 siblings, 0 replies; 51+ messages in thread
From: Jacek Anaszewski @ 2019-04-07 18:31 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Dan Murphy, robh+dt, pavel, lee.jones, devicetree, linux-kernel,
	linux-leds

On 4/5/19 12:00 AM, Tony Lindgren wrote:
> * Jacek Anaszewski <jacek.anaszewski@gmail.com> [190404 20:12]:
>> Tony,
>>
>> On 3/21/19 3:28 PM, Dan Murphy wrote:
>>> Update the properties for the lm3532 device node for droid4.
>>> With this change the backlight LED string and the keypad
>>> LED strings will be controlled separately.
>>>
>>> Signed-off-by: Dan Murphy <dmurphy@ti.com>
>>> ---
>>>
>>> v5 - No change - https://lore.kernel.org/patchwork/patch/1050409/
>>>
>>> v4 - No change - https://lore.kernel.org/patchwork/patch/1050125/
>>> v3 - updated keypad label on v1 comment - https://lore.kernel.org/patchwork/patch/1049023/
>>> v2 - Fixed ramp-up and ramp-down properties, removed hard coded property values,
>>> I did not change the label as it is undecided what it could be - https://lore.kernel.org/patchwork/patch/1048806/
>>>
>>>    arch/arm/boot/dts/omap4-droid4-xt894.dts | 26 ++++++++++++++++--------
>>>    1 file changed, 18 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
>>> index e21ec929f096..aea206f04f76 100644
>>> --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
>>> +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
>>> @@ -383,20 +383,30 @@
>>>    };
>>>    &i2c1 {
>>> -	lm3532@38 {
>>> +	led-controller@38 {
>>>    		compatible = "ti,lm3532";
>>> +		#address-cells = <1>;
>>> +		#size-cells = <0>;
>>>    		reg = <0x38>;
>>>    		enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
>>> -		lcd_backlight: backlight {
>>> -			compatible = "ti,lm3532-backlight";
>>> +		ramp-up-us = <1024>;
>>> +		ramp-down-us = <8193>;
>>> -			lcd {
>>> -				led-sources = <0 1 2>;
>>> -				ramp-up-msec = <1>;
>>> -				ramp-down-msec = <0>;
>>> -			};
>>
>> Since I'll be creating integration branch for this series,
>> and it would be good to have this patch in it too, then
>> I can do the amendments by myself:
>>
>>> +		lcd_backlight: led@0 {
>>> +			reg = <0>;
>>> +			led-sources = <2>;
>>> +			ti,led-mode = <0>;
>>> +			label = "backlight";
>>
>> s/backlight/:backlight/
>>
>>> +			linux,default-trigger = "backlight";
>>> +		};
>>> +
>>> +		led@1 {
>>> +			reg = <1>;
>>> +			led-sources = <1>;
>>> +			ti,led-mode = <0>;
>>> +			label = "platform::kbd_backlight";
>>
>> s/platform::kbd_backlight/:kbd_backlight/
> 
> Yes makes sense to me.
> 
>> and then send you a pull request.
>>
>> Would you be OK with that?
> 
> Sure go for it. Here's my ack for the changes:
> 
> Acked-by: Tony Lindgren <tony@atomide.com>
> 
> And then for the one liner to fold in below:
> 
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> 
> 8< -------------
> diff --git a/arch/arm/boot/dts/omap4-droid4-xt894.dts b/arch/arm/boot/dts/omap4-droid4-xt894.dts
> --- a/arch/arm/boot/dts/omap4-droid4-xt894.dts
> +++ b/arch/arm/boot/dts/omap4-droid4-xt894.dts
> @@ -214,7 +214,6 @@
>   
>   		width-mm = <50>;
>   		height-mm = <89>;
> -		backlight = <&lcd_backlight>;
>   
>   		panel-timing {
>   			clock-frequency = <0>;		/* Calculated by dsi */
> 

Folded in, thanks. Beside that, I also removed lcd_backlight DT
labels from both DT bindings and dts, since it is now unused
and misleading.

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc
  2019-03-21 14:28 ` Dan Murphy
                   ` (6 preceding siblings ...)
  (?)
@ 2019-04-07 19:11 ` Jacek Anaszewski
  -1 siblings, 0 replies; 51+ messages in thread
From: Jacek Anaszewski @ 2019-04-07 19:11 UTC (permalink / raw)
  To: Dan Murphy, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Hi Dan,

On 3/21/19 3:28 PM, Dan Murphy wrote:
> Add the lm3532 device tree documentation.
> Remove lm3532 device tree reference from the ti_lmu devicetree
> documentation.
> 
> With the addition of the dedicated lm3532 documentation the device
> can be removed from the ti_lmu.txt.
> 
> The reason for this is that the lm3532 dt documentation now defines
> the ability to control LED output strings against different control
> banks or groups multiple strings to be controlled by a single control
> bank.
> 
> Another addition was for ALS lighting control and configuration.  The
> LM3532 has a feature that can take in the ALS reading from 2 separate
> ALS devices and adjust the brightness on the strings that are configured
> to support this feature.
> 
> Finally the device specific properties were moved to the parent node as these
> properties are not control bank configurable.  These include the runtime ramp
> and the ALS configuration.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---

Thank you for your work on this set. Applied.

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-11 17:47               ` Dan Murphy
  (?)
@ 2019-03-13 15:49               ` Joe Perches
  -1 siblings, 0 replies; 51+ messages in thread
From: Joe Perches @ 2019-03-13 15:49 UTC (permalink / raw)
  To: Dan Murphy, Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

On Mon, 2019-03-11 at 12:47 -0500, Dan Murphy wrote:
> On 3/11/19 12:30 PM, Joe Perches wrote:
> > On Mon, 2019-03-11 at 12:24 -0500, Dan Murphy wrote:
> > > checkpatch takes issue with // in headers.
> > > Unless they have removed that requirement.
[]
> I guess I was referring to this SPDX warning
>  
> WARNING: Missing or malformed SPDX-License-Identifier tag in line 1
> #1: FILE: drivers/net/can/m_can/m_can.h:1:
> +//SPDX-License-Identifier: GPL-2.0

The general form uses a space after the //

And much more recently:

commit fdf13693d370653013eec3bc7f80a3f535001bf0
Author: Joe Perches <joe@perches.com>
Date:   Thu Mar 7 16:28:32 2019 -0800

    checkpatch: verify SPDX comment style
    
    Using SPDX commenting style // or /* is specified for various file types
    in Documentation/process/license-rules.rst so add an appropriate test for
    .[chsS] files because many proposed file additions and patches do not use
    the correct style.

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-11 17:30           ` Joe Perches
@ 2019-03-11 17:47               ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-11 17:47 UTC (permalink / raw)
  To: Joe Perches, Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Thanks Joe

On 3/11/19 12:30 PM, Joe Perches wrote:
> On Mon, 2019-03-11 at 12:24 -0500, Dan Murphy wrote:
>> checkpatch takes issue with // in headers.
>> Unless they have removed that requirement.
> 
> Awhile ago...
>

I guess I was referring to this SPDX warning
 
WARNING: Missing or malformed SPDX-License-Identifier tag in line 1
#1: FILE: drivers/net/can/m_can/m_can.h:1:
+//SPDX-License-Identifier: GPL-2.0

> commit dadf680de3c2eb4cba9840619991eda0cfe98778
> Author: Joe Perches <joe@perches.com>
> Date:   Tue Aug 2 14:04:33 2016 -0700
> 
>     checkpatch: allow c99 style // comments
>     
>     Sanitise the lines that contain c99 comments so that the error doesn't
>     get emitted.
>     
>     Link: http://lkml.kernel.org/r/d4d22c34ad7bcc1bceb52f0742f76b7a6d585235.1468368420.git.joe@perches.com
>     Signed-off-by: Joe Perches <joe@perches.com>
>     Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
>     Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-11 17:47               ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-11 17:47 UTC (permalink / raw)
  To: Joe Perches, Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Thanks Joe

On 3/11/19 12:30 PM, Joe Perches wrote:
> On Mon, 2019-03-11 at 12:24 -0500, Dan Murphy wrote:
>> checkpatch takes issue with // in headers.
>> Unless they have removed that requirement.
> 
> Awhile ago...
>

I guess I was referring to this SPDX warning
 
WARNING: Missing or malformed SPDX-License-Identifier tag in line 1
#1: FILE: drivers/net/can/m_can/m_can.h:1:
+//SPDX-License-Identifier: GPL-2.0

> commit dadf680de3c2eb4cba9840619991eda0cfe98778
> Author: Joe Perches <joe@perches.com>
> Date:   Tue Aug 2 14:04:33 2016 -0700
> 
>     checkpatch: allow c99 style // comments
>     
>     Sanitise the lines that contain c99 comments so that the error doesn't
>     get emitted.
>     
>     Link: http://lkml.kernel.org/r/d4d22c34ad7bcc1bceb52f0742f76b7a6d585235.1468368420.git.joe@perches.com
>     Signed-off-by: Joe Perches <joe@perches.com>
>     Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
>     Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-11 17:24           ` Dan Murphy
  (?)
@ 2019-03-11 17:30           ` Joe Perches
  2019-03-11 17:47               ` Dan Murphy
  -1 siblings, 1 reply; 51+ messages in thread
From: Joe Perches @ 2019-03-11 17:30 UTC (permalink / raw)
  To: Dan Murphy, Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

On Mon, 2019-03-11 at 12:24 -0500, Dan Murphy wrote:
> checkpatch takes issue with // in headers.
> Unless they have removed that requirement.

Awhile ago...

commit dadf680de3c2eb4cba9840619991eda0cfe98778
Author: Joe Perches <joe@perches.com>
Date:   Tue Aug 2 14:04:33 2016 -0700

    checkpatch: allow c99 style // comments
    
    Sanitise the lines that contain c99 comments so that the error doesn't
    get emitted.
    
    Link: http://lkml.kernel.org/r/d4d22c34ad7bcc1bceb52f0742f76b7a6d585235.1468368420.git.joe@perches.com
    Signed-off-by: Joe Perches <joe@perches.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-11 17:22       ` Jacek Anaszewski
@ 2019-03-11 17:24           ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-11 17:24 UTC (permalink / raw)
  To: Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Jacek

On 3/11/19 12:22 PM, Jacek Anaszewski wrote:
> Dan,
> 
> One more thing I forgot to mention before.
> 
> On 3/11/19 12:36 PM, Dan Murphy wrote:
>> Jacek
> [...]
>>
>>>> @@ -0,0 +1,72 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/* TI LM3532 LED driver
>>>> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>>>> + */
> 
> Let's have "//" comments here.
> 

Like I said earlier in v2 this header went away.

And checkpatch takes issue with // in headers.

Unless they have removed that requirement.

Dan

>>>> +#ifndef __DT_BINDINGS_LEDS_LM3532_H
>>>> +#define __DT_BINDINGS_LEDS_LM3532_H
>>>> +
>>>> +#define LM3532_BL_MODE_MANUAL    0x00 /* "man" */
>>>> +#define LM3532_BL_MODE_ALS    0x01 /* "als" */
>>>> +
>>>> +/* ALS Resistor Select */
>>>> +#define LM3532_IMP_HIGH        0x00
>>>> +#define LM3532_IMP_37K        0x01
>>>> +#define LM3532_IMP_18_5K    0x02
>>>> +#define LM3532_IMP_12_33K    0x03
>>>> +#define LM3532_IMP_9_25K    0x04
>>>> +#define LM3532_IMP_7_4K        0x05
>>>> +#define LM3532_IMP_6_17K    0x06
>>>> +#define LM3532_IMP_5_29K    0x07
>>>> +#define LM3532_IMP_4_63K    0x08
>>>> +#define LM3532_IMP_4_11K    0x09
>>>> +#define LM3532_IMP_3_7K        0x0a
>>>> +#define LM3532_IMP_3_36K    0x0b
>>>> +#define LM3532_IMP_3_08K    0x0c
>>>> +#define LM3532_IMP_2_85K    0x0d
>>>> +#define LM3532_IMP_2_64K    0x0e
>>>> +#define LM3532_IMP_2_44K    0x0f
>>>> +#define LM3532_IMP_2_31K    0x10
>>>> +#define LM3532_IMP_2_18K    0x11
>>>> +#define LM3532_IMP_2_06K    0x12
>>>> +#define LM3532_IMP_1_95K    0x13
>>>> +#define LM3532_IMP_1_85K    0x14
>>>> +#define LM3532_IMP_1_76K    0x15
>>>> +#define LM3532_IMP_1_68K    0x16
>>>> +#define LM3532_IMP_1_61K    0x17
>>>> +#define LM3532_IMP_1_54K    0x18
>>>> +#define LM3532_IMP_1_48K    0x19
>>>> +#define LM3532_IMP_1_42K    0x1a
>>>> +#define LM3532_IMP_1_37K    0x1b
>>>> +#define LM3532_IMP_1_32K    0x1c
>>>> +#define LM3532_IMP_1_28K    0x1d
>>>> +#define LM3532_IMP_1_23K    0x1e
>>>> +#define LM3532_IMP_1_19K    0x1f
>>>> +
>>>> +/* ALS Averaging Time */
>>>> +#define LM3532_ALS_AVRG_TIME_17_92ms    0x00
>>>> +#define LM3532_ALS_AVRG_TIME_35_84ms    0x01
>>>> +#define LM3532_ALS_AVRG_TIME_71_68ms    0x02
>>>> +#define LM3532_ALS_AVRG_TIME_143_36ms    0x03
>>>> +#define LM3532_ALS_AVRG_TIME_286_72ms    0x04
>>>> +#define LM3532_ALS_AVRG_TIME_573_44ms    0x05
>>>> +#define LM3532_ALS_AVRG_TIME_1146_88ms    0x06
>>>> +#define LM3532_ALS_AVRG_TIME_2293_76ms    0x07
>>>> +
>>>> +/* ALS input select */
>>>> +#define LM3532_ALS_INPUT_AVRG    0x00 /* ALS1 and ALS2 input average */
>>>> +#define LM3532_ALS_INPUT_ALS1    0x01 /* ALS1 Input */
>>>> +#define LM3532_ALS_INPUT_ALS2    0x02 /* ALS2 Input */
>>>> +#define LM3532_ALS_INPUT_CEIL    0x03 /* Max of ALS1 and ALS2 */
>>>> +
>>>> +/* Ramp Times */
>>>> +#define LM3532_RAMP_8us        0x00
>>>> +#define LM3532_RAMP_1024us    0x01
>>>> +#define LM3532_RAMP_2048us    0x02
>>>> +#define LM3532_RAMP_4096us    0x03
>>>> +#define LM3532_RAMP_8192us    0x04
>>>> +#define LM3532_RAMP_16384us    0x05
>>>> +#define LM3532_RAMP_32768us    0x06
>>>> +#define LM3532_RAMP_65536us    0x07
>>>> +
>>>> +#endif /* __DT_BINDINGS_LEDS_LM3532_H */
>>>>
>>>
>>
>>
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-11 17:24           ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-11 17:24 UTC (permalink / raw)
  To: Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Jacek

On 3/11/19 12:22 PM, Jacek Anaszewski wrote:
> Dan,
> 
> One more thing I forgot to mention before.
> 
> On 3/11/19 12:36 PM, Dan Murphy wrote:
>> Jacek
> [...]
>>
>>>> @@ -0,0 +1,72 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/* TI LM3532 LED driver
>>>> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>>>> + */
> 
> Let's have "//" comments here.
> 

Like I said earlier in v2 this header went away.

And checkpatch takes issue with // in headers.

Unless they have removed that requirement.

Dan

>>>> +#ifndef __DT_BINDINGS_LEDS_LM3532_H
>>>> +#define __DT_BINDINGS_LEDS_LM3532_H
>>>> +
>>>> +#define LM3532_BL_MODE_MANUAL    0x00 /* "man" */
>>>> +#define LM3532_BL_MODE_ALS    0x01 /* "als" */
>>>> +
>>>> +/* ALS Resistor Select */
>>>> +#define LM3532_IMP_HIGH        0x00
>>>> +#define LM3532_IMP_37K        0x01
>>>> +#define LM3532_IMP_18_5K    0x02
>>>> +#define LM3532_IMP_12_33K    0x03
>>>> +#define LM3532_IMP_9_25K    0x04
>>>> +#define LM3532_IMP_7_4K        0x05
>>>> +#define LM3532_IMP_6_17K    0x06
>>>> +#define LM3532_IMP_5_29K    0x07
>>>> +#define LM3532_IMP_4_63K    0x08
>>>> +#define LM3532_IMP_4_11K    0x09
>>>> +#define LM3532_IMP_3_7K        0x0a
>>>> +#define LM3532_IMP_3_36K    0x0b
>>>> +#define LM3532_IMP_3_08K    0x0c
>>>> +#define LM3532_IMP_2_85K    0x0d
>>>> +#define LM3532_IMP_2_64K    0x0e
>>>> +#define LM3532_IMP_2_44K    0x0f
>>>> +#define LM3532_IMP_2_31K    0x10
>>>> +#define LM3532_IMP_2_18K    0x11
>>>> +#define LM3532_IMP_2_06K    0x12
>>>> +#define LM3532_IMP_1_95K    0x13
>>>> +#define LM3532_IMP_1_85K    0x14
>>>> +#define LM3532_IMP_1_76K    0x15
>>>> +#define LM3532_IMP_1_68K    0x16
>>>> +#define LM3532_IMP_1_61K    0x17
>>>> +#define LM3532_IMP_1_54K    0x18
>>>> +#define LM3532_IMP_1_48K    0x19
>>>> +#define LM3532_IMP_1_42K    0x1a
>>>> +#define LM3532_IMP_1_37K    0x1b
>>>> +#define LM3532_IMP_1_32K    0x1c
>>>> +#define LM3532_IMP_1_28K    0x1d
>>>> +#define LM3532_IMP_1_23K    0x1e
>>>> +#define LM3532_IMP_1_19K    0x1f
>>>> +
>>>> +/* ALS Averaging Time */
>>>> +#define LM3532_ALS_AVRG_TIME_17_92ms    0x00
>>>> +#define LM3532_ALS_AVRG_TIME_35_84ms    0x01
>>>> +#define LM3532_ALS_AVRG_TIME_71_68ms    0x02
>>>> +#define LM3532_ALS_AVRG_TIME_143_36ms    0x03
>>>> +#define LM3532_ALS_AVRG_TIME_286_72ms    0x04
>>>> +#define LM3532_ALS_AVRG_TIME_573_44ms    0x05
>>>> +#define LM3532_ALS_AVRG_TIME_1146_88ms    0x06
>>>> +#define LM3532_ALS_AVRG_TIME_2293_76ms    0x07
>>>> +
>>>> +/* ALS input select */
>>>> +#define LM3532_ALS_INPUT_AVRG    0x00 /* ALS1 and ALS2 input average */
>>>> +#define LM3532_ALS_INPUT_ALS1    0x01 /* ALS1 Input */
>>>> +#define LM3532_ALS_INPUT_ALS2    0x02 /* ALS2 Input */
>>>> +#define LM3532_ALS_INPUT_CEIL    0x03 /* Max of ALS1 and ALS2 */
>>>> +
>>>> +/* Ramp Times */
>>>> +#define LM3532_RAMP_8us        0x00
>>>> +#define LM3532_RAMP_1024us    0x01
>>>> +#define LM3532_RAMP_2048us    0x02
>>>> +#define LM3532_RAMP_4096us    0x03
>>>> +#define LM3532_RAMP_8192us    0x04
>>>> +#define LM3532_RAMP_16384us    0x05
>>>> +#define LM3532_RAMP_32768us    0x06
>>>> +#define LM3532_RAMP_65536us    0x07
>>>> +
>>>> +#endif /* __DT_BINDINGS_LEDS_LM3532_H */
>>>>
>>>
>>
>>
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-11 11:36       ` Dan Murphy
  (?)
@ 2019-03-11 17:22       ` Jacek Anaszewski
  2019-03-11 17:24           ` Dan Murphy
  -1 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-03-11 17:22 UTC (permalink / raw)
  To: Dan Murphy, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Dan,

One more thing I forgot to mention before.

On 3/11/19 12:36 PM, Dan Murphy wrote:
> Jacek
[...]
> 
>>> @@ -0,0 +1,72 @@
>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>> +/* TI LM3532 LED driver
>>> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>>> + */

Let's have "//" comments here.

>>> +#ifndef __DT_BINDINGS_LEDS_LM3532_H
>>> +#define __DT_BINDINGS_LEDS_LM3532_H
>>> +
>>> +#define LM3532_BL_MODE_MANUAL    0x00 /* "man" */
>>> +#define LM3532_BL_MODE_ALS    0x01 /* "als" */
>>> +
>>> +/* ALS Resistor Select */
>>> +#define LM3532_IMP_HIGH        0x00
>>> +#define LM3532_IMP_37K        0x01
>>> +#define LM3532_IMP_18_5K    0x02
>>> +#define LM3532_IMP_12_33K    0x03
>>> +#define LM3532_IMP_9_25K    0x04
>>> +#define LM3532_IMP_7_4K        0x05
>>> +#define LM3532_IMP_6_17K    0x06
>>> +#define LM3532_IMP_5_29K    0x07
>>> +#define LM3532_IMP_4_63K    0x08
>>> +#define LM3532_IMP_4_11K    0x09
>>> +#define LM3532_IMP_3_7K        0x0a
>>> +#define LM3532_IMP_3_36K    0x0b
>>> +#define LM3532_IMP_3_08K    0x0c
>>> +#define LM3532_IMP_2_85K    0x0d
>>> +#define LM3532_IMP_2_64K    0x0e
>>> +#define LM3532_IMP_2_44K    0x0f
>>> +#define LM3532_IMP_2_31K    0x10
>>> +#define LM3532_IMP_2_18K    0x11
>>> +#define LM3532_IMP_2_06K    0x12
>>> +#define LM3532_IMP_1_95K    0x13
>>> +#define LM3532_IMP_1_85K    0x14
>>> +#define LM3532_IMP_1_76K    0x15
>>> +#define LM3532_IMP_1_68K    0x16
>>> +#define LM3532_IMP_1_61K    0x17
>>> +#define LM3532_IMP_1_54K    0x18
>>> +#define LM3532_IMP_1_48K    0x19
>>> +#define LM3532_IMP_1_42K    0x1a
>>> +#define LM3532_IMP_1_37K    0x1b
>>> +#define LM3532_IMP_1_32K    0x1c
>>> +#define LM3532_IMP_1_28K    0x1d
>>> +#define LM3532_IMP_1_23K    0x1e
>>> +#define LM3532_IMP_1_19K    0x1f
>>> +
>>> +/* ALS Averaging Time */
>>> +#define LM3532_ALS_AVRG_TIME_17_92ms    0x00
>>> +#define LM3532_ALS_AVRG_TIME_35_84ms    0x01
>>> +#define LM3532_ALS_AVRG_TIME_71_68ms    0x02
>>> +#define LM3532_ALS_AVRG_TIME_143_36ms    0x03
>>> +#define LM3532_ALS_AVRG_TIME_286_72ms    0x04
>>> +#define LM3532_ALS_AVRG_TIME_573_44ms    0x05
>>> +#define LM3532_ALS_AVRG_TIME_1146_88ms    0x06
>>> +#define LM3532_ALS_AVRG_TIME_2293_76ms    0x07
>>> +
>>> +/* ALS input select */
>>> +#define LM3532_ALS_INPUT_AVRG    0x00 /* ALS1 and ALS2 input average */
>>> +#define LM3532_ALS_INPUT_ALS1    0x01 /* ALS1 Input */
>>> +#define LM3532_ALS_INPUT_ALS2    0x02 /* ALS2 Input */
>>> +#define LM3532_ALS_INPUT_CEIL    0x03 /* Max of ALS1 and ALS2 */
>>> +
>>> +/* Ramp Times */
>>> +#define LM3532_RAMP_8us        0x00
>>> +#define LM3532_RAMP_1024us    0x01
>>> +#define LM3532_RAMP_2048us    0x02
>>> +#define LM3532_RAMP_4096us    0x03
>>> +#define LM3532_RAMP_8192us    0x04
>>> +#define LM3532_RAMP_16384us    0x05
>>> +#define LM3532_RAMP_32768us    0x06
>>> +#define LM3532_RAMP_65536us    0x07
>>> +
>>> +#endif /* __DT_BINDINGS_LEDS_LM3532_H */
>>>
>>
> 
> 

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-10 19:49   ` Jacek Anaszewski
@ 2019-03-11 11:36       ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-11 11:36 UTC (permalink / raw)
  To: Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Jacek

On 3/10/19 2:49 PM, Jacek Anaszewski wrote:
> Hi Dan,
> 
> Thank your for the patch.
> 
> I have some comments below, please take a look.
> 

Thanks for the review.  I have pushed v2 with some code changes but those changes that were
made seem to be outside your comments.

So I will implemnt these comments in v3.

> On 3/7/19 11:09 PM, Dan Murphy wrote:
>> Introduce the Texas Instruments LM3532 White LED driver.
>> The driver supports ALS configurability or manual brightness
>> control.
>>
>> The driver also supports associating LED strings with specific
>> control banks in a group or as individually controlled strings.
>>
>> Signed-off-by: Dan Murphy <dmurphy@ti.com>
>> ---
>>   drivers/leds/Kconfig                   |  10 +
>>   drivers/leds/Makefile                  |   1 +
>>   drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
>>   include/dt-bindings/leds/leds-lm3532.h |  72 +++
>>   4 files changed, 678 insertions(+)
>>   create mode 100644 drivers/leds/leds-lm3532.c
>>   create mode 100644 include/dt-bindings/leds/leds-lm3532.h
>>
>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
>> index a72f97fca57b..da00b9ed5a5c 100644
>> --- a/drivers/leds/Kconfig
>> +++ b/drivers/leds/Kconfig
>> @@ -138,6 +138,16 @@ config LEDS_LM3530
>>         controlled manually or using PWM input or using ambient
>>         light automatically.
>>   +config LEDS_LM3532
>> +    tristate "LCD Backlight driver for LM3532"
>> +    depends on LEDS_CLASS
>> +    depends on I2C
>> +    help
>> +      This option enables support for the LCD backlight using
>> +      LM3532 ambient light sensor chip. This ALS chip can be
>> +      controlled manually or using PWM input or using ambient
>> +      light automatically.
>> +
>>   config LEDS_LM3533
>>       tristate "LED support for LM3533"
>>       depends on LEDS_CLASS
>> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
>> index 4c1b0054f379..7a8b1f55d459 100644
>> --- a/drivers/leds/Makefile
>> +++ b/drivers/leds/Makefile
>> @@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)        += leds-bd2802.o
>>   obj-$(CONFIG_LEDS_CPCAP)        += leds-cpcap.o
>>   obj-$(CONFIG_LEDS_LOCOMO)        += leds-locomo.o
>>   obj-$(CONFIG_LEDS_LM3530)        += leds-lm3530.o
>> +obj-$(CONFIG_LEDS_LM3532)        += leds-lm3532.o
>>   obj-$(CONFIG_LEDS_LM3533)        += leds-lm3533.o
>>   obj-$(CONFIG_LEDS_LM3642)        += leds-lm3642.o
>>   obj-$(CONFIG_LEDS_MIKROTIK_RB532)    += leds-rb532.o
>> diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
>> new file mode 100644
>> index 000000000000..005478359d06
>> --- /dev/null
>> +++ b/drivers/leds/leds-lm3532.c
>> @@ -0,0 +1,595 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// TI LM3532 LED driver
>> +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/leds.h>
>> +#include <linux/slab.h>
>> +#include <linux/regmap.h>
>> +#include <linux/input.h>
>> +#include <linux/types.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/module.h>
>> +#include <uapi/linux/uleds.h>
>> +#include <linux/gpio/consumer.h>
>> +
>> +#include <dt-bindings/leds/leds-lm3532.h>
>> +
>> +#define LM3532_NAME "lm3532-led"
>> +
>> +#define LM3532_REG_OUTPUT_CFG    0x10
>> +#define LM3532_REG_STARTSHUT_RAMP    0x11
>> +#define LM3532_REG_RT_RAMP    0x12
>> +#define LM3532_REG_PWM_A_CFG    0x13
>> +#define LM3532_REG_PWM_B_CFG    0x14
>> +#define LM3532_REG_PWM_C_CFG    0x15
>> +#define LM3532_REG_ZONE_CFG_A    0x16
>> +#define LM3532_REG_CTRL_A_BRT    0x17
>> +#define LM3532_REG_ZONE_CFG_B    0x18
>> +#define LM3532_REG_CTRL_B_BRT    0x19
>> +#define LM3532_REG_ZONE_CFG_C    0x1a
>> +#define LM3532_REG_CTRL_C_BRT    0x1b
>> +#define LM3532_REG_ENABLE    0x1d
>> +#define LM3532_ALS_CONFIG    0x23
>> +#define LM3532_REG_ZN_0_HI    0x60
>> +#define LM3532_REG_ZN_0_LO    0x61
>> +#define LM3532_REG_ZN_1_HI    0x62
>> +#define LM3532_REG_ZN_1_LO    0x63
>> +#define LM3532_REG_ZN_2_HI    0x64
>> +#define LM3532_REG_ZN_2_LO    0x65
>> +#define LM3532_REG_ZN_3_HI    0x66
>> +#define LM3532_REG_ZN_3_LO    0x67
>> +#define LM3532_REG_MAX        0x7e
>> +
>> +/* Contorl Enable */
>> +#define LM3532_CTRL_A_ENABLE    BIT(0)
>> +#define LM3532_CTRL_B_ENABLE    BIT(1)
>> +#define LM3532_CTRL_C_ENABLE    BIT(2)
>> +
>> +/* PWM Zone Control */
>> +#define LM3532_PWM_ZONE_MASK    0x7c
>> +#define LM3532_PWM_ZONE_0_EN    BIT(2)
>> +#define LM3532_PWM_ZONE_1_EN    BIT(3)
>> +#define LM3532_PWM_ZONE_2_EN    BIT(4)
>> +#define LM3532_PWM_ZONE_3_EN    BIT(5)
>> +#define LM3532_PWM_ZONE_4_EN    BIT(6)
>> +
>> +/* Brightness Configuration */
>> +#define LM3532_I2C_CTRL        BIT(0)
>> +#define LM3532_LINEAR_MAP    BIT(1)
>> +#define LM3532_ZONE_MASK    (BIT(2) | BIT(3) | BIT(4))
>> +#define LM3532_ZONE_0        0
>> +#define LM3532_ZONE_1        BIT(2)
>> +#define LM3532_ZONE_2        BIT(3)
>> +#define LM3532_ZONE_3        (BIT(2) | BIT(3))
>> +#define LM3532_ZONE_4        BIT(4)
>> +
>> +#define LM3532_ENABLE_ALS    BIT(3)
>> +#define LM3532_ALS_SEL_SHIFT    6
>> +
>> +/* Zone Boundary Register */
>> +#define LM3532_ALS_WINDOW_mV    2000
>> +#define LM3532_ALS_ZB_MAX    4
>> +#define LM3532_ALS_OFFSET_mV    2
>> +
>> +#define LM3532_CONTROL_A    0
>> +#define LM3532_CONTROL_B    1
>> +#define LM3532_CONTROL_C    2
>> +#define LM3532_MAX_CONTROL_BANKS 3
>> +#define LM3532_MAX_LED_STRINGS    3
>> +
>> +#define LM3532_OUTPUT_CFG_MASK    0x3
>> +#define LM3532_BRT_VAL_ADJUST    8
>> +#define LM3532_RAMP_DOWN_SHIFT    3
>> +
>> +/*
>> + * struct lm3532_als_data
>> + * @config - value of ALS configuration register
>> + * @als1_imp_sel - value of ALS1 resistor select register
>> + * @als2_imp_sel - value of ALS2 resistor select register
>> + * @als_avrg_time - ALS averaging time
>> + * @als_input_mode - ALS input mode for brightness control
>> + * @als_vmin - Minimum ALS voltage
>> + * @als_vmax - Maximum ALS voltage
>> + * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
>> + * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
>> + */
>> +struct lm3532_als_data {
>> +    u8 config;
>> +    u8 als1_imp_sel;
>> +    u8 als2_imp_sel;
>> +    u8 als_avrg_time;
>> +    u8 als_input_mode;
>> +    u32 als_vmin;
>> +    u32 als_vmax;
>> +    u8 zones_lo[LM3532_ALS_ZB_MAX];
>> +    u8 zones_hi[LM3532_ALS_ZB_MAX];
>> +};
>> +
>> +/**
>> + * struct lm3532_led
>> + * @led_dev: led class device
>> + * @priv - Pointer the device data structure
>> + * @control_bank - Control bank the LED is associated to
>> + * @mode - Mode of the LED string
>> + * @num_leds - Number of LED strings are supported in this array
>> + * @led_strings - The LED strings supported in this array
>> + * @label - LED label
>> + */
>> +struct lm3532_led {
>> +    struct led_classdev led_dev;
>> +    struct lm3532_data *priv;
>> +
>> +    int control_bank;
>> +    int mode;
>> +    int num_leds;
>> +    u32 led_strings[LM3532_MAX_CONTROL_BANKS];
>> +    char label[LED_MAX_NAME_SIZE];
>> +};
>> +
>> +/**
>> + * struct lm3532_data
>> + * @enable_gpio - Hardware enable gpio
>> + * @regulator: regulator
>> + * @client: i2c client
>> + * @regmap - Devices register map
>> + * @dev - Pointer to the devices device struct
>> + * @lock - Lock for reading/writing the device
>> + * @als_data - Pointer to the als data struct
>> + * @runtime_ramp_up - Runtime ramp up setting
>> + * @runtime_ramp_down - Runtime ramp down setting
>> + * @leds - Array of LED strings
>> + */
>> +struct lm3532_data {
>> +    struct gpio_desc *enable_gpio;
>> +    struct regulator *regulator;
>> +    struct i2c_client *client;
>> +    struct regmap *regmap;
>> +    struct device *dev;
>> +    struct mutex lock;
>> +
>> +    struct lm3532_als_data *als_data;
>> +
>> +    u32 runtime_ramp_up;
>> +    u32 runtime_ramp_down;
>> +
>> +    struct lm3532_led leds[];
>> +};
>> +
>> +static const struct reg_default lm3532_reg_defs[] = {
>> +    {LM3532_REG_OUTPUT_CFG, 0xe4},
>> +    {LM3532_REG_STARTSHUT_RAMP, 0xc0},
>> +    {LM3532_REG_RT_RAMP, 0xc0},
>> +    {LM3532_REG_PWM_A_CFG, 0x82},
>> +    {LM3532_REG_PWM_B_CFG, 0x82},
>> +    {LM3532_REG_PWM_C_CFG, 0x82},
>> +    {LM3532_REG_ZONE_CFG_A, 0xf1},
>> +    {LM3532_REG_CTRL_A_BRT, 0xf3},
>> +    {LM3532_REG_ZONE_CFG_B, 0xf1},
>> +    {LM3532_REG_CTRL_B_BRT, 0xf3},
>> +    {LM3532_REG_ZONE_CFG_C, 0xf1},
>> +    {LM3532_REG_CTRL_C_BRT, 0xf3},
>> +    {LM3532_REG_ENABLE, 0xf8},
>> +    {LM3532_ALS_CONFIG, 0x44},
>> +    {LM3532_REG_ZN_0_HI, 0x35},
>> +    {LM3532_REG_ZN_0_LO, 0x33},
>> +    {LM3532_REG_ZN_1_HI, 0x6a},
>> +    {LM3532_REG_ZN_1_LO, 0x66},
>> +    {LM3532_REG_ZN_2_HI, 0xa1},
>> +    {LM3532_REG_ZN_2_LO, 0x99},
>> +    {LM3532_REG_ZN_3_HI, 0xdc},
>> +    {LM3532_REG_ZN_3_LO, 0xcc},
>> +};
>> +
>> +static const struct regmap_config lm3532_regmap_config = {
>> +    .reg_bits = 8,
>> +    .val_bits = 8,
>> +
>> +    .max_register = LM3532_REG_MAX,
>> +    .reg_defaults = lm3532_reg_defs,
>> +    .num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
>> +    .cache_type = REGCACHE_FLAT,
>> +};
>> +
>> +static int lm3532_led_enable(struct lm3532_led *led_data)
>> +{
>> +    int ctrl_en_val;
>> +    int ret;
>> +
>> +    switch (led_data->control_bank) {
>> +    case LM3532_CONTROL_A:
>> +        ctrl_en_val = LM3532_CTRL_A_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_B:
>> +        ctrl_en_val = LM3532_CTRL_B_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_C:
>> +        ctrl_en_val = LM3532_CTRL_C_ENABLE;
>> +        break;
>> +    default:
>> +        dev_err(led_data->priv->dev, "Invalid control bank\n");
> 
> If control_bank was validated in lm3532_parse_node(), then you wouldn't
> have to take into account this option here.
> 
> Besides, you don't need this switch statement, but can easily calculate
> ctrl_en_val:
> 
> #define LM3532_GET_CTRL_BANK_EN_VAL(bank_id) BIT(bank_id)
> 

Ack.  Probably don't even need the macro for this.

ctrl_en_val = BIT(led_data->control_bank);

>> +        return -EINVAL;
>> +    };
>> +
>> +    ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
>> +                     ctrl_en_val, ctrl_en_val);
>> +    if (ret) {
>> +        dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    return regulator_enable(led_data->priv->regulator);
>> +}
>> +
>> +static int lm3532_led_disable(struct lm3532_led *led_data)
>> +{
>> +    int ctrl_en_val;
>> +    int ret;
>> +
>> +    switch (led_data->control_bank) {
>> +    case LM3532_CONTROL_A:
>> +        ctrl_en_val = LM3532_CTRL_A_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_B:
>> +        ctrl_en_val = LM3532_CTRL_B_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_C:
>> +        ctrl_en_val = LM3532_CTRL_C_ENABLE;
>> +        break;
>> +    default:
>> +        dev_err(led_data->priv->dev, "Invalid control bank\n");
>> +        return -EINVAL;
>> +    };
> 
> Ditto.
> 

Ack  Same as above

>> +
>> +    ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
>> +                     ctrl_en_val, ~ctrl_en_val);
>> +    if (ret) {
>> +        dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    return regulator_disable(led_data->priv->regulator);
>> +}
>> +
>> +static int lm3532_brightness_set(struct led_classdev *led_cdev,
>> +                 enum led_brightness brt_val)
>> +{
>> +    struct lm3532_led *led =
>> +            container_of(led_cdev, struct lm3532_led, led_dev);
>> +    u8 brightnes_reg;
>> +    int ret;
>> +
>> +    mutex_lock(&led->priv->lock);
>> +
>> +    if (led->mode == LM3532_BL_MODE_ALS) {
>> +        ret = 0;
>> +        goto unlock;
>> +    }
>> +
>> +    switch (led->control_bank) {
>> +    case LM3532_CONTROL_A:
>> +        brightnes_reg = LM3532_REG_CTRL_A_BRT;
>> +        break;
>> +    case LM3532_CONTROL_B:
>> +        brightnes_reg = LM3532_REG_CTRL_B_BRT;
>> +        break;
>> +    case LM3532_CONTROL_C:
>> +        brightnes_reg = LM3532_REG_CTRL_C_BRT;
>> +        break;
>> +    default:
>> +        dev_err(led->priv->dev, "Invalid control bank\n");
>> +        ret = -EINVAL;
>> +        goto unlock;
>> +    };
> 
> Similarly here. use following macro:
> 
> #define LM3532_GET_CTRL_BANK_BRT_REG (bank_id) BIT((LM3532_REG_CTRL_A_BRT + bank_id*2))
> 

Ack. Probably don't need a macro since it is only used once.

brightness_reg = LM3532_REG_CTRL_A_BRT + led->control_bank * 2

>> +    if (brt_val == LED_OFF) {
>> +        ret = lm3532_led_disable(led);
>> +        goto unlock;
>> +    }
>> +
>> +    lm3532_led_enable(led);
>> +    brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
>> +
>> +    ret = regmap_write(led->priv->regmap, brightnes_reg, brt_val);
>> +
>> +unlock:
>> +    mutex_unlock(&led->priv->lock);
>> +    return ret;
>> +}
>> +
>> +static int lm3532_init_registers(struct lm3532_led *led)
>> +{
>> +    struct lm3532_data *drvdata = led->priv;
>> +    unsigned int runtime_ramp_val;
>> +    unsigned int output_cfg_val = 0;
>> +    unsigned int output_cfg_shift = 0;
>> +    unsigned int output_cfg_mask = 0;
>> +    int ret, i;
>> +
>> +    for (i = 0; i < led->num_leds; i++) {
>> +        output_cfg_shift = led->led_strings[i] * 2;
>> +        output_cfg_val |= (led->control_bank << output_cfg_shift);
>> +        output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
>> +    }
>> +
>> +    ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
>> +                 output_cfg_mask, output_cfg_val);
>> +
>> +    runtime_ramp_val = drvdata->runtime_ramp_up |
>> +             (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
>> +
>> +    return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
>> +                runtime_ramp_val);
>> +}
>> +
>> +static int lm3532_als_configure(struct lm3532_data *priv)
>> +{
>> +    struct lm3532_als_data *als = priv->als_data;
>> +    u32 als_vmin, als_vmax, als_vstep;
>> +    int zone_reg = LM3532_REG_ZN_0_HI;
>> +    int ret;
>> +    int i;
>> +
>> +    als_vmin = als->als_vmin;
>> +    als_vmax = als->als_vmax;
>> +
>> +    als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
>> +
>> +    for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
>> +        als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
>> +                LED_FULL) / 1000;
>> +        als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
>> +                als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
>> +
>> +        zone_reg = LM3532_REG_ZN_0_HI + i * 2;
>> +        ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
>> +        if (ret)
>> +            return ret;
>> +
>> +        zone_reg += 1;
>> +        ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
>> +        if (ret)
>> +            return ret;
>> +    }
>> +
>> +    als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
>> +        (als->als_input_mode << LM3532_ALS_SEL_SHIFT));
>> +
>> +    return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
>> +}
>> +
>> +static int lm3532_parse_als(struct lm3532_data *priv)
>> +{
>> +    struct lm3532_als_data *als;
>> +    int ret;
>> +
>> +    als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
>> +    if (als == NULL)
>> +        return -ENOMEM;
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "als-vmin",
>> +                       &als->als_vmin);
>> +    if (ret)
>> +        als->als_vmin = 0;
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "als-vmax",
>> +                       &als->als_vmax);
>> +    if (ret)
>> +        als->als_vmax = LM3532_ALS_WINDOW_mV;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als1-imp-sel",
>> +                      &als->als1_imp_sel);
>> +    if (ret)
>> +        als->als1_imp_sel = 0;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als2-imp-sel",
>> +                      &als->als2_imp_sel);
>> +    if (ret)
>> +        als->als2_imp_sel = 0;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als-avrg-time",
>> +                      &als->als_avrg_time);
>> +    if (ret)
>> +        als->als_avrg_time = 0;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als-input-mode",
>> +                      &als->als_input_mode);
>> +    if (ret)
>> +        als->als_input_mode = 0;
>> +
>> +    priv->als_data = als;
>> +
>> +    return ret;
>> +}
>> +
>> +static int lm3532_parse_node(struct lm3532_data *priv)
>> +{
>> +    struct fwnode_handle *child = NULL;
>> +    struct lm3532_led *led;
>> +    const char *name;
>> +    int control_bank;
>> +    size_t i = 0;
>> +    int ret;
>> +
>> +    priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
>> +                           "enable", GPIOD_OUT_LOW);
>> +    if (IS_ERR(priv->enable_gpio))
>> +        priv->enable_gpio = NULL;
>> +
>> +    priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
>> +    if (IS_ERR(priv->regulator))
>> +        priv->regulator = NULL;
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
>> +                       &priv->runtime_ramp_up);
>> +    if (ret)
>> +        dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
>> +                       &priv->runtime_ramp_down);
>> +    if (ret)
>> +        dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
>> +
>> +    device_for_each_child_node(priv->dev, child) {
>> +        led = &priv->leds[i];
>> +
>> +        ret = fwnode_property_read_u32(child, "reg", &control_bank);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "reg property missing\n");
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        if (control_bank > LM3532_CONTROL_C) {
>> +            dev_err(&priv->client->dev, "Control bank invalid\n");
>> +            continue;
>> +        }
>> +
>> +        led->control_bank = control_bank;
>> +
>> +        ret = fwnode_property_read_u32(child, "ti,led-mode",
>> +                           &led->mode);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "ti,led-mode property missing\n");
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        if (led->mode == LM3532_BL_MODE_ALS) {
>> +            ret = lm3532_parse_als(priv);
>> +            if (ret)
>> +                dev_err(&priv->client->dev, "Failed to parse als\n");
>> +            else
>> +                lm3532_als_configure(priv);
>> +        }
>> +
>> +        led->num_leds = fwnode_property_read_u32_array(child,
>> +                                   "led-sources",
>> +                                   NULL, 0);
>> +
>> +        if (led->num_leds > LM3532_MAX_LED_STRINGS) {
>> +            dev_err(&priv->client->dev, "To many LED string defined\n");
>> +            continue;
>> +        }
>> +
>> +        ret = fwnode_property_read_u32_array(child, "led-sources",
>> +                            led->led_strings,
>> +                            led->num_leds);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "led-sources property missing\n");
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        fwnode_property_read_string(child, "linux,default-trigger",
>> +                        &led->led_dev.default_trigger);
>> +
>> +        ret = fwnode_property_read_string(child, "label", &name);
>> +        if (ret)
>> +            snprintf(led->label, sizeof(led->label),
>> +                "%s::", priv->client->name);
>> +        else
>> +            snprintf(led->label, sizeof(led->label),
>> +                 "%s:%s", priv->client->name, name);
>> +
>> +        led->priv = priv;
>> +        led->led_dev.name = led->label;
>> +        led->led_dev.brightness_set_blocking = lm3532_brightness_set;
>> +
>> +        ret = devm_led_classdev_register(priv->dev, &led->led_dev);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "led register err: %d\n",
>> +                ret);
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        lm3532_init_registers(led);
>> +
>> +        i++;
>> +    }
>> +
>> +child_out:
>> +    return ret;
>> +}
>> +
>> +static int lm3532_probe(struct i2c_client *client,
>> +               const struct i2c_device_id *id)
>> +{
>> +    struct lm3532_data *drvdata;
>> +    int ret = 0;
>> +    int count;
>> +
>> +    count = device_get_child_node_count(&client->dev);
>> +    if (!count) {
>> +        dev_err(&client->dev, "LEDs are not defined in device tree!");
>> +        return -ENODEV;
>> +    }
>> +
>> +    drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
>> +               GFP_KERNEL);
>> +    if (drvdata == NULL)
>> +        return -ENOMEM;
>> +
>> +    drvdata->client = client;
>> +    drvdata->dev = &client->dev;
>> +
>> +    drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
>> +    if (IS_ERR(drvdata->regmap)) {
>> +        ret = PTR_ERR(drvdata->regmap);
>> +        dev_err(&client->dev, "Failed to allocate register map: %d\n",
>> +            ret);
>> +        return ret;
>> +    }
>> +
>> +    mutex_init(&drvdata->lock);
>> +    i2c_set_clientdata(client, drvdata);
>> +
>> +    ret = lm3532_parse_node(drvdata);
>> +    if (ret) {
>> +        dev_err(&client->dev, "Failed to parse node\n");
>> +        return ret;
>> +    }
>> +
>> +    if (drvdata->enable_gpio)
>> +        gpiod_direction_output(drvdata->enable_gpio, 1);
>> +
>> +    return ret;
>> +}
>> +
>> +static int lm3532_remove(struct i2c_client *client)
>> +{
>> +    struct lm3532_data *drvdata = i2c_get_clientdata(client);
> 
> mutex_destroy() is missing here.

Ack

> 
>> +    if (drvdata->enable_gpio)
>> +        gpiod_direction_output(drvdata->enable_gpio, 0);
>> +
>> +    return 0;
>> +}
>> +
>> +static const struct of_device_id of_lm3532_leds_match[] = {
>> +    { .compatible = "ti,lm3532", },
>> +    {},
>> +};
>> +MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
>> +
>> +static const struct i2c_device_id lm3532_id[] = {
>> +    {LM3532_NAME, 0},
>> +    {}
>> +};
>> +MODULE_DEVICE_TABLE(i2c, lm3532_id);
>> +
>> +static struct i2c_driver lm3532_i2c_driver = {
>> +    .probe = lm3532_probe,
>> +    .remove = lm3532_remove,
>> +    .id_table = lm3532_id,
>> +    .driver = {
>> +        .name = LM3532_NAME,
>> +        .of_match_table = of_lm3532_leds_match,
>> +    },
>> +};
>> +module_i2c_driver(lm3532_i2c_driver);
>> +
>> +MODULE_DESCRIPTION("Back Light driver for LM3532");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
>> diff --git a/include/dt-bindings/leds/leds-lm3532.h b/include/dt-bindings/leds/leds-lm3532.h
>> new file mode 100644
>> index 000000000000..724dbc0cb395
>> --- /dev/null
>> +++ b/include/dt-bindings/leds/leds-lm3532.h
> 
> This should go in a separate patch, with DT bindings - see checkpatch.pl
> complaint.
> 

I have removed this in v2 of the next patchset.

Dan

>> @@ -0,0 +1,72 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* TI LM3532 LED driver
>> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>> + */
>> +
>> +#ifndef __DT_BINDINGS_LEDS_LM3532_H
>> +#define __DT_BINDINGS_LEDS_LM3532_H
>> +
>> +#define LM3532_BL_MODE_MANUAL    0x00 /* "man" */
>> +#define LM3532_BL_MODE_ALS    0x01 /* "als" */
>> +
>> +/* ALS Resistor Select */
>> +#define LM3532_IMP_HIGH        0x00
>> +#define LM3532_IMP_37K        0x01
>> +#define LM3532_IMP_18_5K    0x02
>> +#define LM3532_IMP_12_33K    0x03
>> +#define LM3532_IMP_9_25K    0x04
>> +#define LM3532_IMP_7_4K        0x05
>> +#define LM3532_IMP_6_17K    0x06
>> +#define LM3532_IMP_5_29K    0x07
>> +#define LM3532_IMP_4_63K    0x08
>> +#define LM3532_IMP_4_11K    0x09
>> +#define LM3532_IMP_3_7K        0x0a
>> +#define LM3532_IMP_3_36K    0x0b
>> +#define LM3532_IMP_3_08K    0x0c
>> +#define LM3532_IMP_2_85K    0x0d
>> +#define LM3532_IMP_2_64K    0x0e
>> +#define LM3532_IMP_2_44K    0x0f
>> +#define LM3532_IMP_2_31K    0x10
>> +#define LM3532_IMP_2_18K    0x11
>> +#define LM3532_IMP_2_06K    0x12
>> +#define LM3532_IMP_1_95K    0x13
>> +#define LM3532_IMP_1_85K    0x14
>> +#define LM3532_IMP_1_76K    0x15
>> +#define LM3532_IMP_1_68K    0x16
>> +#define LM3532_IMP_1_61K    0x17
>> +#define LM3532_IMP_1_54K    0x18
>> +#define LM3532_IMP_1_48K    0x19
>> +#define LM3532_IMP_1_42K    0x1a
>> +#define LM3532_IMP_1_37K    0x1b
>> +#define LM3532_IMP_1_32K    0x1c
>> +#define LM3532_IMP_1_28K    0x1d
>> +#define LM3532_IMP_1_23K    0x1e
>> +#define LM3532_IMP_1_19K    0x1f
>> +
>> +/* ALS Averaging Time */
>> +#define LM3532_ALS_AVRG_TIME_17_92ms    0x00
>> +#define LM3532_ALS_AVRG_TIME_35_84ms    0x01
>> +#define LM3532_ALS_AVRG_TIME_71_68ms    0x02
>> +#define LM3532_ALS_AVRG_TIME_143_36ms    0x03
>> +#define LM3532_ALS_AVRG_TIME_286_72ms    0x04
>> +#define LM3532_ALS_AVRG_TIME_573_44ms    0x05
>> +#define LM3532_ALS_AVRG_TIME_1146_88ms    0x06
>> +#define LM3532_ALS_AVRG_TIME_2293_76ms    0x07
>> +
>> +/* ALS input select */
>> +#define LM3532_ALS_INPUT_AVRG    0x00 /* ALS1 and ALS2 input average */
>> +#define LM3532_ALS_INPUT_ALS1    0x01 /* ALS1 Input */
>> +#define LM3532_ALS_INPUT_ALS2    0x02 /* ALS2 Input */
>> +#define LM3532_ALS_INPUT_CEIL    0x03 /* Max of ALS1 and ALS2 */
>> +
>> +/* Ramp Times */
>> +#define LM3532_RAMP_8us        0x00
>> +#define LM3532_RAMP_1024us    0x01
>> +#define LM3532_RAMP_2048us    0x02
>> +#define LM3532_RAMP_4096us    0x03
>> +#define LM3532_RAMP_8192us    0x04
>> +#define LM3532_RAMP_16384us    0x05
>> +#define LM3532_RAMP_32768us    0x06
>> +#define LM3532_RAMP_65536us    0x07
>> +
>> +#endif /* __DT_BINDINGS_LEDS_LM3532_H */
>>
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-11 11:36       ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-11 11:36 UTC (permalink / raw)
  To: Jacek Anaszewski, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Jacek

On 3/10/19 2:49 PM, Jacek Anaszewski wrote:
> Hi Dan,
> 
> Thank your for the patch.
> 
> I have some comments below, please take a look.
> 

Thanks for the review.  I have pushed v2 with some code changes but those changes that were
made seem to be outside your comments.

So I will implemnt these comments in v3.

> On 3/7/19 11:09 PM, Dan Murphy wrote:
>> Introduce the Texas Instruments LM3532 White LED driver.
>> The driver supports ALS configurability or manual brightness
>> control.
>>
>> The driver also supports associating LED strings with specific
>> control banks in a group or as individually controlled strings.
>>
>> Signed-off-by: Dan Murphy <dmurphy@ti.com>
>> ---
>>   drivers/leds/Kconfig                   |  10 +
>>   drivers/leds/Makefile                  |   1 +
>>   drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
>>   include/dt-bindings/leds/leds-lm3532.h |  72 +++
>>   4 files changed, 678 insertions(+)
>>   create mode 100644 drivers/leds/leds-lm3532.c
>>   create mode 100644 include/dt-bindings/leds/leds-lm3532.h
>>
>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
>> index a72f97fca57b..da00b9ed5a5c 100644
>> --- a/drivers/leds/Kconfig
>> +++ b/drivers/leds/Kconfig
>> @@ -138,6 +138,16 @@ config LEDS_LM3530
>>         controlled manually or using PWM input or using ambient
>>         light automatically.
>>   +config LEDS_LM3532
>> +    tristate "LCD Backlight driver for LM3532"
>> +    depends on LEDS_CLASS
>> +    depends on I2C
>> +    help
>> +      This option enables support for the LCD backlight using
>> +      LM3532 ambient light sensor chip. This ALS chip can be
>> +      controlled manually or using PWM input or using ambient
>> +      light automatically.
>> +
>>   config LEDS_LM3533
>>       tristate "LED support for LM3533"
>>       depends on LEDS_CLASS
>> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
>> index 4c1b0054f379..7a8b1f55d459 100644
>> --- a/drivers/leds/Makefile
>> +++ b/drivers/leds/Makefile
>> @@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)        += leds-bd2802.o
>>   obj-$(CONFIG_LEDS_CPCAP)        += leds-cpcap.o
>>   obj-$(CONFIG_LEDS_LOCOMO)        += leds-locomo.o
>>   obj-$(CONFIG_LEDS_LM3530)        += leds-lm3530.o
>> +obj-$(CONFIG_LEDS_LM3532)        += leds-lm3532.o
>>   obj-$(CONFIG_LEDS_LM3533)        += leds-lm3533.o
>>   obj-$(CONFIG_LEDS_LM3642)        += leds-lm3642.o
>>   obj-$(CONFIG_LEDS_MIKROTIK_RB532)    += leds-rb532.o
>> diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
>> new file mode 100644
>> index 000000000000..005478359d06
>> --- /dev/null
>> +++ b/drivers/leds/leds-lm3532.c
>> @@ -0,0 +1,595 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// TI LM3532 LED driver
>> +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>> +
>> +#include <linux/i2c.h>
>> +#include <linux/leds.h>
>> +#include <linux/slab.h>
>> +#include <linux/regmap.h>
>> +#include <linux/input.h>
>> +#include <linux/types.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/module.h>
>> +#include <uapi/linux/uleds.h>
>> +#include <linux/gpio/consumer.h>
>> +
>> +#include <dt-bindings/leds/leds-lm3532.h>
>> +
>> +#define LM3532_NAME "lm3532-led"
>> +
>> +#define LM3532_REG_OUTPUT_CFG    0x10
>> +#define LM3532_REG_STARTSHUT_RAMP    0x11
>> +#define LM3532_REG_RT_RAMP    0x12
>> +#define LM3532_REG_PWM_A_CFG    0x13
>> +#define LM3532_REG_PWM_B_CFG    0x14
>> +#define LM3532_REG_PWM_C_CFG    0x15
>> +#define LM3532_REG_ZONE_CFG_A    0x16
>> +#define LM3532_REG_CTRL_A_BRT    0x17
>> +#define LM3532_REG_ZONE_CFG_B    0x18
>> +#define LM3532_REG_CTRL_B_BRT    0x19
>> +#define LM3532_REG_ZONE_CFG_C    0x1a
>> +#define LM3532_REG_CTRL_C_BRT    0x1b
>> +#define LM3532_REG_ENABLE    0x1d
>> +#define LM3532_ALS_CONFIG    0x23
>> +#define LM3532_REG_ZN_0_HI    0x60
>> +#define LM3532_REG_ZN_0_LO    0x61
>> +#define LM3532_REG_ZN_1_HI    0x62
>> +#define LM3532_REG_ZN_1_LO    0x63
>> +#define LM3532_REG_ZN_2_HI    0x64
>> +#define LM3532_REG_ZN_2_LO    0x65
>> +#define LM3532_REG_ZN_3_HI    0x66
>> +#define LM3532_REG_ZN_3_LO    0x67
>> +#define LM3532_REG_MAX        0x7e
>> +
>> +/* Contorl Enable */
>> +#define LM3532_CTRL_A_ENABLE    BIT(0)
>> +#define LM3532_CTRL_B_ENABLE    BIT(1)
>> +#define LM3532_CTRL_C_ENABLE    BIT(2)
>> +
>> +/* PWM Zone Control */
>> +#define LM3532_PWM_ZONE_MASK    0x7c
>> +#define LM3532_PWM_ZONE_0_EN    BIT(2)
>> +#define LM3532_PWM_ZONE_1_EN    BIT(3)
>> +#define LM3532_PWM_ZONE_2_EN    BIT(4)
>> +#define LM3532_PWM_ZONE_3_EN    BIT(5)
>> +#define LM3532_PWM_ZONE_4_EN    BIT(6)
>> +
>> +/* Brightness Configuration */
>> +#define LM3532_I2C_CTRL        BIT(0)
>> +#define LM3532_LINEAR_MAP    BIT(1)
>> +#define LM3532_ZONE_MASK    (BIT(2) | BIT(3) | BIT(4))
>> +#define LM3532_ZONE_0        0
>> +#define LM3532_ZONE_1        BIT(2)
>> +#define LM3532_ZONE_2        BIT(3)
>> +#define LM3532_ZONE_3        (BIT(2) | BIT(3))
>> +#define LM3532_ZONE_4        BIT(4)
>> +
>> +#define LM3532_ENABLE_ALS    BIT(3)
>> +#define LM3532_ALS_SEL_SHIFT    6
>> +
>> +/* Zone Boundary Register */
>> +#define LM3532_ALS_WINDOW_mV    2000
>> +#define LM3532_ALS_ZB_MAX    4
>> +#define LM3532_ALS_OFFSET_mV    2
>> +
>> +#define LM3532_CONTROL_A    0
>> +#define LM3532_CONTROL_B    1
>> +#define LM3532_CONTROL_C    2
>> +#define LM3532_MAX_CONTROL_BANKS 3
>> +#define LM3532_MAX_LED_STRINGS    3
>> +
>> +#define LM3532_OUTPUT_CFG_MASK    0x3
>> +#define LM3532_BRT_VAL_ADJUST    8
>> +#define LM3532_RAMP_DOWN_SHIFT    3
>> +
>> +/*
>> + * struct lm3532_als_data
>> + * @config - value of ALS configuration register
>> + * @als1_imp_sel - value of ALS1 resistor select register
>> + * @als2_imp_sel - value of ALS2 resistor select register
>> + * @als_avrg_time - ALS averaging time
>> + * @als_input_mode - ALS input mode for brightness control
>> + * @als_vmin - Minimum ALS voltage
>> + * @als_vmax - Maximum ALS voltage
>> + * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
>> + * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
>> + */
>> +struct lm3532_als_data {
>> +    u8 config;
>> +    u8 als1_imp_sel;
>> +    u8 als2_imp_sel;
>> +    u8 als_avrg_time;
>> +    u8 als_input_mode;
>> +    u32 als_vmin;
>> +    u32 als_vmax;
>> +    u8 zones_lo[LM3532_ALS_ZB_MAX];
>> +    u8 zones_hi[LM3532_ALS_ZB_MAX];
>> +};
>> +
>> +/**
>> + * struct lm3532_led
>> + * @led_dev: led class device
>> + * @priv - Pointer the device data structure
>> + * @control_bank - Control bank the LED is associated to
>> + * @mode - Mode of the LED string
>> + * @num_leds - Number of LED strings are supported in this array
>> + * @led_strings - The LED strings supported in this array
>> + * @label - LED label
>> + */
>> +struct lm3532_led {
>> +    struct led_classdev led_dev;
>> +    struct lm3532_data *priv;
>> +
>> +    int control_bank;
>> +    int mode;
>> +    int num_leds;
>> +    u32 led_strings[LM3532_MAX_CONTROL_BANKS];
>> +    char label[LED_MAX_NAME_SIZE];
>> +};
>> +
>> +/**
>> + * struct lm3532_data
>> + * @enable_gpio - Hardware enable gpio
>> + * @regulator: regulator
>> + * @client: i2c client
>> + * @regmap - Devices register map
>> + * @dev - Pointer to the devices device struct
>> + * @lock - Lock for reading/writing the device
>> + * @als_data - Pointer to the als data struct
>> + * @runtime_ramp_up - Runtime ramp up setting
>> + * @runtime_ramp_down - Runtime ramp down setting
>> + * @leds - Array of LED strings
>> + */
>> +struct lm3532_data {
>> +    struct gpio_desc *enable_gpio;
>> +    struct regulator *regulator;
>> +    struct i2c_client *client;
>> +    struct regmap *regmap;
>> +    struct device *dev;
>> +    struct mutex lock;
>> +
>> +    struct lm3532_als_data *als_data;
>> +
>> +    u32 runtime_ramp_up;
>> +    u32 runtime_ramp_down;
>> +
>> +    struct lm3532_led leds[];
>> +};
>> +
>> +static const struct reg_default lm3532_reg_defs[] = {
>> +    {LM3532_REG_OUTPUT_CFG, 0xe4},
>> +    {LM3532_REG_STARTSHUT_RAMP, 0xc0},
>> +    {LM3532_REG_RT_RAMP, 0xc0},
>> +    {LM3532_REG_PWM_A_CFG, 0x82},
>> +    {LM3532_REG_PWM_B_CFG, 0x82},
>> +    {LM3532_REG_PWM_C_CFG, 0x82},
>> +    {LM3532_REG_ZONE_CFG_A, 0xf1},
>> +    {LM3532_REG_CTRL_A_BRT, 0xf3},
>> +    {LM3532_REG_ZONE_CFG_B, 0xf1},
>> +    {LM3532_REG_CTRL_B_BRT, 0xf3},
>> +    {LM3532_REG_ZONE_CFG_C, 0xf1},
>> +    {LM3532_REG_CTRL_C_BRT, 0xf3},
>> +    {LM3532_REG_ENABLE, 0xf8},
>> +    {LM3532_ALS_CONFIG, 0x44},
>> +    {LM3532_REG_ZN_0_HI, 0x35},
>> +    {LM3532_REG_ZN_0_LO, 0x33},
>> +    {LM3532_REG_ZN_1_HI, 0x6a},
>> +    {LM3532_REG_ZN_1_LO, 0x66},
>> +    {LM3532_REG_ZN_2_HI, 0xa1},
>> +    {LM3532_REG_ZN_2_LO, 0x99},
>> +    {LM3532_REG_ZN_3_HI, 0xdc},
>> +    {LM3532_REG_ZN_3_LO, 0xcc},
>> +};
>> +
>> +static const struct regmap_config lm3532_regmap_config = {
>> +    .reg_bits = 8,
>> +    .val_bits = 8,
>> +
>> +    .max_register = LM3532_REG_MAX,
>> +    .reg_defaults = lm3532_reg_defs,
>> +    .num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
>> +    .cache_type = REGCACHE_FLAT,
>> +};
>> +
>> +static int lm3532_led_enable(struct lm3532_led *led_data)
>> +{
>> +    int ctrl_en_val;
>> +    int ret;
>> +
>> +    switch (led_data->control_bank) {
>> +    case LM3532_CONTROL_A:
>> +        ctrl_en_val = LM3532_CTRL_A_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_B:
>> +        ctrl_en_val = LM3532_CTRL_B_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_C:
>> +        ctrl_en_val = LM3532_CTRL_C_ENABLE;
>> +        break;
>> +    default:
>> +        dev_err(led_data->priv->dev, "Invalid control bank\n");
> 
> If control_bank was validated in lm3532_parse_node(), then you wouldn't
> have to take into account this option here.
> 
> Besides, you don't need this switch statement, but can easily calculate
> ctrl_en_val:
> 
> #define LM3532_GET_CTRL_BANK_EN_VAL(bank_id) BIT(bank_id)
> 

Ack.  Probably don't even need the macro for this.

ctrl_en_val = BIT(led_data->control_bank);

>> +        return -EINVAL;
>> +    };
>> +
>> +    ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
>> +                     ctrl_en_val, ctrl_en_val);
>> +    if (ret) {
>> +        dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    return regulator_enable(led_data->priv->regulator);
>> +}
>> +
>> +static int lm3532_led_disable(struct lm3532_led *led_data)
>> +{
>> +    int ctrl_en_val;
>> +    int ret;
>> +
>> +    switch (led_data->control_bank) {
>> +    case LM3532_CONTROL_A:
>> +        ctrl_en_val = LM3532_CTRL_A_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_B:
>> +        ctrl_en_val = LM3532_CTRL_B_ENABLE;
>> +        break;
>> +    case LM3532_CONTROL_C:
>> +        ctrl_en_val = LM3532_CTRL_C_ENABLE;
>> +        break;
>> +    default:
>> +        dev_err(led_data->priv->dev, "Invalid control bank\n");
>> +        return -EINVAL;
>> +    };
> 
> Ditto.
> 

Ack  Same as above

>> +
>> +    ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
>> +                     ctrl_en_val, ~ctrl_en_val);
>> +    if (ret) {
>> +        dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
>> +        return ret;
>> +    }
>> +
>> +    return regulator_disable(led_data->priv->regulator);
>> +}
>> +
>> +static int lm3532_brightness_set(struct led_classdev *led_cdev,
>> +                 enum led_brightness brt_val)
>> +{
>> +    struct lm3532_led *led =
>> +            container_of(led_cdev, struct lm3532_led, led_dev);
>> +    u8 brightnes_reg;
>> +    int ret;
>> +
>> +    mutex_lock(&led->priv->lock);
>> +
>> +    if (led->mode == LM3532_BL_MODE_ALS) {
>> +        ret = 0;
>> +        goto unlock;
>> +    }
>> +
>> +    switch (led->control_bank) {
>> +    case LM3532_CONTROL_A:
>> +        brightnes_reg = LM3532_REG_CTRL_A_BRT;
>> +        break;
>> +    case LM3532_CONTROL_B:
>> +        brightnes_reg = LM3532_REG_CTRL_B_BRT;
>> +        break;
>> +    case LM3532_CONTROL_C:
>> +        brightnes_reg = LM3532_REG_CTRL_C_BRT;
>> +        break;
>> +    default:
>> +        dev_err(led->priv->dev, "Invalid control bank\n");
>> +        ret = -EINVAL;
>> +        goto unlock;
>> +    };
> 
> Similarly here. use following macro:
> 
> #define LM3532_GET_CTRL_BANK_BRT_REG (bank_id) BIT((LM3532_REG_CTRL_A_BRT + bank_id*2))
> 

Ack. Probably don't need a macro since it is only used once.

brightness_reg = LM3532_REG_CTRL_A_BRT + led->control_bank * 2

>> +    if (brt_val == LED_OFF) {
>> +        ret = lm3532_led_disable(led);
>> +        goto unlock;
>> +    }
>> +
>> +    lm3532_led_enable(led);
>> +    brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
>> +
>> +    ret = regmap_write(led->priv->regmap, brightnes_reg, brt_val);
>> +
>> +unlock:
>> +    mutex_unlock(&led->priv->lock);
>> +    return ret;
>> +}
>> +
>> +static int lm3532_init_registers(struct lm3532_led *led)
>> +{
>> +    struct lm3532_data *drvdata = led->priv;
>> +    unsigned int runtime_ramp_val;
>> +    unsigned int output_cfg_val = 0;
>> +    unsigned int output_cfg_shift = 0;
>> +    unsigned int output_cfg_mask = 0;
>> +    int ret, i;
>> +
>> +    for (i = 0; i < led->num_leds; i++) {
>> +        output_cfg_shift = led->led_strings[i] * 2;
>> +        output_cfg_val |= (led->control_bank << output_cfg_shift);
>> +        output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
>> +    }
>> +
>> +    ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
>> +                 output_cfg_mask, output_cfg_val);
>> +
>> +    runtime_ramp_val = drvdata->runtime_ramp_up |
>> +             (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
>> +
>> +    return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
>> +                runtime_ramp_val);
>> +}
>> +
>> +static int lm3532_als_configure(struct lm3532_data *priv)
>> +{
>> +    struct lm3532_als_data *als = priv->als_data;
>> +    u32 als_vmin, als_vmax, als_vstep;
>> +    int zone_reg = LM3532_REG_ZN_0_HI;
>> +    int ret;
>> +    int i;
>> +
>> +    als_vmin = als->als_vmin;
>> +    als_vmax = als->als_vmax;
>> +
>> +    als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
>> +
>> +    for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
>> +        als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
>> +                LED_FULL) / 1000;
>> +        als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
>> +                als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
>> +
>> +        zone_reg = LM3532_REG_ZN_0_HI + i * 2;
>> +        ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
>> +        if (ret)
>> +            return ret;
>> +
>> +        zone_reg += 1;
>> +        ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
>> +        if (ret)
>> +            return ret;
>> +    }
>> +
>> +    als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
>> +        (als->als_input_mode << LM3532_ALS_SEL_SHIFT));
>> +
>> +    return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
>> +}
>> +
>> +static int lm3532_parse_als(struct lm3532_data *priv)
>> +{
>> +    struct lm3532_als_data *als;
>> +    int ret;
>> +
>> +    als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
>> +    if (als == NULL)
>> +        return -ENOMEM;
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "als-vmin",
>> +                       &als->als_vmin);
>> +    if (ret)
>> +        als->als_vmin = 0;
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "als-vmax",
>> +                       &als->als_vmax);
>> +    if (ret)
>> +        als->als_vmax = LM3532_ALS_WINDOW_mV;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als1-imp-sel",
>> +                      &als->als1_imp_sel);
>> +    if (ret)
>> +        als->als1_imp_sel = 0;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als2-imp-sel",
>> +                      &als->als2_imp_sel);
>> +    if (ret)
>> +        als->als2_imp_sel = 0;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als-avrg-time",
>> +                      &als->als_avrg_time);
>> +    if (ret)
>> +        als->als_avrg_time = 0;
>> +
>> +    ret = device_property_read_u8(&priv->client->dev, "als-input-mode",
>> +                      &als->als_input_mode);
>> +    if (ret)
>> +        als->als_input_mode = 0;
>> +
>> +    priv->als_data = als;
>> +
>> +    return ret;
>> +}
>> +
>> +static int lm3532_parse_node(struct lm3532_data *priv)
>> +{
>> +    struct fwnode_handle *child = NULL;
>> +    struct lm3532_led *led;
>> +    const char *name;
>> +    int control_bank;
>> +    size_t i = 0;
>> +    int ret;
>> +
>> +    priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
>> +                           "enable", GPIOD_OUT_LOW);
>> +    if (IS_ERR(priv->enable_gpio))
>> +        priv->enable_gpio = NULL;
>> +
>> +    priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
>> +    if (IS_ERR(priv->regulator))
>> +        priv->regulator = NULL;
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
>> +                       &priv->runtime_ramp_up);
>> +    if (ret)
>> +        dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
>> +
>> +    ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
>> +                       &priv->runtime_ramp_down);
>> +    if (ret)
>> +        dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
>> +
>> +    device_for_each_child_node(priv->dev, child) {
>> +        led = &priv->leds[i];
>> +
>> +        ret = fwnode_property_read_u32(child, "reg", &control_bank);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "reg property missing\n");
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        if (control_bank > LM3532_CONTROL_C) {
>> +            dev_err(&priv->client->dev, "Control bank invalid\n");
>> +            continue;
>> +        }
>> +
>> +        led->control_bank = control_bank;
>> +
>> +        ret = fwnode_property_read_u32(child, "ti,led-mode",
>> +                           &led->mode);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "ti,led-mode property missing\n");
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        if (led->mode == LM3532_BL_MODE_ALS) {
>> +            ret = lm3532_parse_als(priv);
>> +            if (ret)
>> +                dev_err(&priv->client->dev, "Failed to parse als\n");
>> +            else
>> +                lm3532_als_configure(priv);
>> +        }
>> +
>> +        led->num_leds = fwnode_property_read_u32_array(child,
>> +                                   "led-sources",
>> +                                   NULL, 0);
>> +
>> +        if (led->num_leds > LM3532_MAX_LED_STRINGS) {
>> +            dev_err(&priv->client->dev, "To many LED string defined\n");
>> +            continue;
>> +        }
>> +
>> +        ret = fwnode_property_read_u32_array(child, "led-sources",
>> +                            led->led_strings,
>> +                            led->num_leds);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "led-sources property missing\n");
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        fwnode_property_read_string(child, "linux,default-trigger",
>> +                        &led->led_dev.default_trigger);
>> +
>> +        ret = fwnode_property_read_string(child, "label", &name);
>> +        if (ret)
>> +            snprintf(led->label, sizeof(led->label),
>> +                "%s::", priv->client->name);
>> +        else
>> +            snprintf(led->label, sizeof(led->label),
>> +                 "%s:%s", priv->client->name, name);
>> +
>> +        led->priv = priv;
>> +        led->led_dev.name = led->label;
>> +        led->led_dev.brightness_set_blocking = lm3532_brightness_set;
>> +
>> +        ret = devm_led_classdev_register(priv->dev, &led->led_dev);
>> +        if (ret) {
>> +            dev_err(&priv->client->dev, "led register err: %d\n",
>> +                ret);
>> +            fwnode_handle_put(child);
>> +            goto child_out;
>> +        }
>> +
>> +        lm3532_init_registers(led);
>> +
>> +        i++;
>> +    }
>> +
>> +child_out:
>> +    return ret;
>> +}
>> +
>> +static int lm3532_probe(struct i2c_client *client,
>> +               const struct i2c_device_id *id)
>> +{
>> +    struct lm3532_data *drvdata;
>> +    int ret = 0;
>> +    int count;
>> +
>> +    count = device_get_child_node_count(&client->dev);
>> +    if (!count) {
>> +        dev_err(&client->dev, "LEDs are not defined in device tree!");
>> +        return -ENODEV;
>> +    }
>> +
>> +    drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
>> +               GFP_KERNEL);
>> +    if (drvdata == NULL)
>> +        return -ENOMEM;
>> +
>> +    drvdata->client = client;
>> +    drvdata->dev = &client->dev;
>> +
>> +    drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
>> +    if (IS_ERR(drvdata->regmap)) {
>> +        ret = PTR_ERR(drvdata->regmap);
>> +        dev_err(&client->dev, "Failed to allocate register map: %d\n",
>> +            ret);
>> +        return ret;
>> +    }
>> +
>> +    mutex_init(&drvdata->lock);
>> +    i2c_set_clientdata(client, drvdata);
>> +
>> +    ret = lm3532_parse_node(drvdata);
>> +    if (ret) {
>> +        dev_err(&client->dev, "Failed to parse node\n");
>> +        return ret;
>> +    }
>> +
>> +    if (drvdata->enable_gpio)
>> +        gpiod_direction_output(drvdata->enable_gpio, 1);
>> +
>> +    return ret;
>> +}
>> +
>> +static int lm3532_remove(struct i2c_client *client)
>> +{
>> +    struct lm3532_data *drvdata = i2c_get_clientdata(client);
> 
> mutex_destroy() is missing here.

Ack

> 
>> +    if (drvdata->enable_gpio)
>> +        gpiod_direction_output(drvdata->enable_gpio, 0);
>> +
>> +    return 0;
>> +}
>> +
>> +static const struct of_device_id of_lm3532_leds_match[] = {
>> +    { .compatible = "ti,lm3532", },
>> +    {},
>> +};
>> +MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
>> +
>> +static const struct i2c_device_id lm3532_id[] = {
>> +    {LM3532_NAME, 0},
>> +    {}
>> +};
>> +MODULE_DEVICE_TABLE(i2c, lm3532_id);
>> +
>> +static struct i2c_driver lm3532_i2c_driver = {
>> +    .probe = lm3532_probe,
>> +    .remove = lm3532_remove,
>> +    .id_table = lm3532_id,
>> +    .driver = {
>> +        .name = LM3532_NAME,
>> +        .of_match_table = of_lm3532_leds_match,
>> +    },
>> +};
>> +module_i2c_driver(lm3532_i2c_driver);
>> +
>> +MODULE_DESCRIPTION("Back Light driver for LM3532");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
>> diff --git a/include/dt-bindings/leds/leds-lm3532.h b/include/dt-bindings/leds/leds-lm3532.h
>> new file mode 100644
>> index 000000000000..724dbc0cb395
>> --- /dev/null
>> +++ b/include/dt-bindings/leds/leds-lm3532.h
> 
> This should go in a separate patch, with DT bindings - see checkpatch.pl
> complaint.
> 

I have removed this in v2 of the next patchset.

Dan

>> @@ -0,0 +1,72 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* TI LM3532 LED driver
>> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
>> + */
>> +
>> +#ifndef __DT_BINDINGS_LEDS_LM3532_H
>> +#define __DT_BINDINGS_LEDS_LM3532_H
>> +
>> +#define LM3532_BL_MODE_MANUAL    0x00 /* "man" */
>> +#define LM3532_BL_MODE_ALS    0x01 /* "als" */
>> +
>> +/* ALS Resistor Select */
>> +#define LM3532_IMP_HIGH        0x00
>> +#define LM3532_IMP_37K        0x01
>> +#define LM3532_IMP_18_5K    0x02
>> +#define LM3532_IMP_12_33K    0x03
>> +#define LM3532_IMP_9_25K    0x04
>> +#define LM3532_IMP_7_4K        0x05
>> +#define LM3532_IMP_6_17K    0x06
>> +#define LM3532_IMP_5_29K    0x07
>> +#define LM3532_IMP_4_63K    0x08
>> +#define LM3532_IMP_4_11K    0x09
>> +#define LM3532_IMP_3_7K        0x0a
>> +#define LM3532_IMP_3_36K    0x0b
>> +#define LM3532_IMP_3_08K    0x0c
>> +#define LM3532_IMP_2_85K    0x0d
>> +#define LM3532_IMP_2_64K    0x0e
>> +#define LM3532_IMP_2_44K    0x0f
>> +#define LM3532_IMP_2_31K    0x10
>> +#define LM3532_IMP_2_18K    0x11
>> +#define LM3532_IMP_2_06K    0x12
>> +#define LM3532_IMP_1_95K    0x13
>> +#define LM3532_IMP_1_85K    0x14
>> +#define LM3532_IMP_1_76K    0x15
>> +#define LM3532_IMP_1_68K    0x16
>> +#define LM3532_IMP_1_61K    0x17
>> +#define LM3532_IMP_1_54K    0x18
>> +#define LM3532_IMP_1_48K    0x19
>> +#define LM3532_IMP_1_42K    0x1a
>> +#define LM3532_IMP_1_37K    0x1b
>> +#define LM3532_IMP_1_32K    0x1c
>> +#define LM3532_IMP_1_28K    0x1d
>> +#define LM3532_IMP_1_23K    0x1e
>> +#define LM3532_IMP_1_19K    0x1f
>> +
>> +/* ALS Averaging Time */
>> +#define LM3532_ALS_AVRG_TIME_17_92ms    0x00
>> +#define LM3532_ALS_AVRG_TIME_35_84ms    0x01
>> +#define LM3532_ALS_AVRG_TIME_71_68ms    0x02
>> +#define LM3532_ALS_AVRG_TIME_143_36ms    0x03
>> +#define LM3532_ALS_AVRG_TIME_286_72ms    0x04
>> +#define LM3532_ALS_AVRG_TIME_573_44ms    0x05
>> +#define LM3532_ALS_AVRG_TIME_1146_88ms    0x06
>> +#define LM3532_ALS_AVRG_TIME_2293_76ms    0x07
>> +
>> +/* ALS input select */
>> +#define LM3532_ALS_INPUT_AVRG    0x00 /* ALS1 and ALS2 input average */
>> +#define LM3532_ALS_INPUT_ALS1    0x01 /* ALS1 Input */
>> +#define LM3532_ALS_INPUT_ALS2    0x02 /* ALS2 Input */
>> +#define LM3532_ALS_INPUT_CEIL    0x03 /* Max of ALS1 and ALS2 */
>> +
>> +/* Ramp Times */
>> +#define LM3532_RAMP_8us        0x00
>> +#define LM3532_RAMP_1024us    0x01
>> +#define LM3532_RAMP_2048us    0x02
>> +#define LM3532_RAMP_4096us    0x03
>> +#define LM3532_RAMP_8192us    0x04
>> +#define LM3532_RAMP_16384us    0x05
>> +#define LM3532_RAMP_32768us    0x06
>> +#define LM3532_RAMP_65536us    0x07
>> +
>> +#endif /* __DT_BINDINGS_LEDS_LM3532_H */
>>
> 


-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-07 22:09   ` Dan Murphy
  (?)
  (?)
@ 2019-03-10 19:49   ` Jacek Anaszewski
  2019-03-11 11:36       ` Dan Murphy
  -1 siblings, 1 reply; 51+ messages in thread
From: Jacek Anaszewski @ 2019-03-10 19:49 UTC (permalink / raw)
  To: Dan Murphy, robh+dt, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Hi Dan,

Thank your for the patch.

I have some comments below, please take a look.

On 3/7/19 11:09 PM, Dan Murphy wrote:
> Introduce the Texas Instruments LM3532 White LED driver.
> The driver supports ALS configurability or manual brightness
> control.
> 
> The driver also supports associating LED strings with specific
> control banks in a group or as individually controlled strings.
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
>   drivers/leds/Kconfig                   |  10 +
>   drivers/leds/Makefile                  |   1 +
>   drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
>   include/dt-bindings/leds/leds-lm3532.h |  72 +++
>   4 files changed, 678 insertions(+)
>   create mode 100644 drivers/leds/leds-lm3532.c
>   create mode 100644 include/dt-bindings/leds/leds-lm3532.h
> 
> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> index a72f97fca57b..da00b9ed5a5c 100644
> --- a/drivers/leds/Kconfig
> +++ b/drivers/leds/Kconfig
> @@ -138,6 +138,16 @@ config LEDS_LM3530
>   	  controlled manually or using PWM input or using ambient
>   	  light automatically.
>   
> +config LEDS_LM3532
> +	tristate "LCD Backlight driver for LM3532"
> +	depends on LEDS_CLASS
> +	depends on I2C
> +	help
> +	  This option enables support for the LCD backlight using
> +	  LM3532 ambient light sensor chip. This ALS chip can be
> +	  controlled manually or using PWM input or using ambient
> +	  light automatically.
> +
>   config LEDS_LM3533
>   	tristate "LED support for LM3533"
>   	depends on LEDS_CLASS
> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> index 4c1b0054f379..7a8b1f55d459 100644
> --- a/drivers/leds/Makefile
> +++ b/drivers/leds/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
>   obj-$(CONFIG_LEDS_CPCAP)		+= leds-cpcap.o
>   obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
>   obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
> +obj-$(CONFIG_LEDS_LM3532)		+= leds-lm3532.o
>   obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
>   obj-$(CONFIG_LEDS_LM3642)		+= leds-lm3642.o
>   obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
> diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
> new file mode 100644
> index 000000000000..005478359d06
> --- /dev/null
> +++ b/drivers/leds/leds-lm3532.c
> @@ -0,0 +1,595 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// TI LM3532 LED driver
> +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
> +
> +#include <linux/i2c.h>
> +#include <linux/leds.h>
> +#include <linux/slab.h>
> +#include <linux/regmap.h>
> +#include <linux/input.h>
> +#include <linux/types.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/module.h>
> +#include <uapi/linux/uleds.h>
> +#include <linux/gpio/consumer.h>
> +
> +#include <dt-bindings/leds/leds-lm3532.h>
> +
> +#define LM3532_NAME "lm3532-led"
> +
> +#define LM3532_REG_OUTPUT_CFG	0x10
> +#define LM3532_REG_STARTSHUT_RAMP	0x11
> +#define LM3532_REG_RT_RAMP	0x12
> +#define LM3532_REG_PWM_A_CFG	0x13
> +#define LM3532_REG_PWM_B_CFG	0x14
> +#define LM3532_REG_PWM_C_CFG	0x15
> +#define LM3532_REG_ZONE_CFG_A	0x16
> +#define LM3532_REG_CTRL_A_BRT	0x17
> +#define LM3532_REG_ZONE_CFG_B	0x18
> +#define LM3532_REG_CTRL_B_BRT	0x19
> +#define LM3532_REG_ZONE_CFG_C	0x1a
> +#define LM3532_REG_CTRL_C_BRT	0x1b
> +#define LM3532_REG_ENABLE	0x1d
> +#define LM3532_ALS_CONFIG	0x23
> +#define LM3532_REG_ZN_0_HI	0x60
> +#define LM3532_REG_ZN_0_LO	0x61
> +#define LM3532_REG_ZN_1_HI	0x62
> +#define LM3532_REG_ZN_1_LO	0x63
> +#define LM3532_REG_ZN_2_HI	0x64
> +#define LM3532_REG_ZN_2_LO	0x65
> +#define LM3532_REG_ZN_3_HI	0x66
> +#define LM3532_REG_ZN_3_LO	0x67
> +#define LM3532_REG_MAX		0x7e
> +
> +/* Contorl Enable */
> +#define LM3532_CTRL_A_ENABLE	BIT(0)
> +#define LM3532_CTRL_B_ENABLE	BIT(1)
> +#define LM3532_CTRL_C_ENABLE	BIT(2)
> +
> +/* PWM Zone Control */
> +#define LM3532_PWM_ZONE_MASK	0x7c
> +#define LM3532_PWM_ZONE_0_EN	BIT(2)
> +#define LM3532_PWM_ZONE_1_EN	BIT(3)
> +#define LM3532_PWM_ZONE_2_EN	BIT(4)
> +#define LM3532_PWM_ZONE_3_EN	BIT(5)
> +#define LM3532_PWM_ZONE_4_EN	BIT(6)
> +
> +/* Brightness Configuration */
> +#define LM3532_I2C_CTRL		BIT(0)
> +#define LM3532_LINEAR_MAP	BIT(1)
> +#define LM3532_ZONE_MASK	(BIT(2) | BIT(3) | BIT(4))
> +#define LM3532_ZONE_0		0
> +#define LM3532_ZONE_1		BIT(2)
> +#define LM3532_ZONE_2		BIT(3)
> +#define LM3532_ZONE_3		(BIT(2) | BIT(3))
> +#define LM3532_ZONE_4		BIT(4)
> +
> +#define LM3532_ENABLE_ALS	BIT(3)
> +#define LM3532_ALS_SEL_SHIFT	6
> +
> +/* Zone Boundary Register */
> +#define LM3532_ALS_WINDOW_mV	2000
> +#define LM3532_ALS_ZB_MAX	4
> +#define LM3532_ALS_OFFSET_mV	2
> +
> +#define LM3532_CONTROL_A	0
> +#define LM3532_CONTROL_B	1
> +#define LM3532_CONTROL_C	2
> +#define LM3532_MAX_CONTROL_BANKS 3
> +#define LM3532_MAX_LED_STRINGS	3
> +
> +#define LM3532_OUTPUT_CFG_MASK	0x3
> +#define LM3532_BRT_VAL_ADJUST	8
> +#define LM3532_RAMP_DOWN_SHIFT	3
> +
> +/*
> + * struct lm3532_als_data
> + * @config - value of ALS configuration register
> + * @als1_imp_sel - value of ALS1 resistor select register
> + * @als2_imp_sel - value of ALS2 resistor select register
> + * @als_avrg_time - ALS averaging time
> + * @als_input_mode - ALS input mode for brightness control
> + * @als_vmin - Minimum ALS voltage
> + * @als_vmax - Maximum ALS voltage
> + * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
> + * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
> + */
> +struct lm3532_als_data {
> +	u8 config;
> +	u8 als1_imp_sel;
> +	u8 als2_imp_sel;
> +	u8 als_avrg_time;
> +	u8 als_input_mode;
> +	u32 als_vmin;
> +	u32 als_vmax;
> +	u8 zones_lo[LM3532_ALS_ZB_MAX];
> +	u8 zones_hi[LM3532_ALS_ZB_MAX];
> +};
> +
> +/**
> + * struct lm3532_led
> + * @led_dev: led class device
> + * @priv - Pointer the device data structure
> + * @control_bank - Control bank the LED is associated to
> + * @mode - Mode of the LED string
> + * @num_leds - Number of LED strings are supported in this array
> + * @led_strings - The LED strings supported in this array
> + * @label - LED label
> + */
> +struct lm3532_led {
> +	struct led_classdev led_dev;
> +	struct lm3532_data *priv;
> +
> +	int control_bank;
> +	int mode;
> +	int num_leds;
> +	u32 led_strings[LM3532_MAX_CONTROL_BANKS];
> +	char label[LED_MAX_NAME_SIZE];
> +};
> +
> +/**
> + * struct lm3532_data
> + * @enable_gpio - Hardware enable gpio
> + * @regulator: regulator
> + * @client: i2c client
> + * @regmap - Devices register map
> + * @dev - Pointer to the devices device struct
> + * @lock - Lock for reading/writing the device
> + * @als_data - Pointer to the als data struct
> + * @runtime_ramp_up - Runtime ramp up setting
> + * @runtime_ramp_down - Runtime ramp down setting
> + * @leds - Array of LED strings
> + */
> +struct lm3532_data {
> +	struct gpio_desc *enable_gpio;
> +	struct regulator *regulator;
> +	struct i2c_client *client;
> +	struct regmap *regmap;
> +	struct device *dev;
> +	struct mutex lock;
> +
> +	struct lm3532_als_data *als_data;
> +
> +	u32 runtime_ramp_up;
> +	u32 runtime_ramp_down;
> +
> +	struct lm3532_led leds[];
> +};
> +
> +static const struct reg_default lm3532_reg_defs[] = {
> +	{LM3532_REG_OUTPUT_CFG, 0xe4},
> +	{LM3532_REG_STARTSHUT_RAMP, 0xc0},
> +	{LM3532_REG_RT_RAMP, 0xc0},
> +	{LM3532_REG_PWM_A_CFG, 0x82},
> +	{LM3532_REG_PWM_B_CFG, 0x82},
> +	{LM3532_REG_PWM_C_CFG, 0x82},
> +	{LM3532_REG_ZONE_CFG_A, 0xf1},
> +	{LM3532_REG_CTRL_A_BRT, 0xf3},
> +	{LM3532_REG_ZONE_CFG_B, 0xf1},
> +	{LM3532_REG_CTRL_B_BRT, 0xf3},
> +	{LM3532_REG_ZONE_CFG_C, 0xf1},
> +	{LM3532_REG_CTRL_C_BRT, 0xf3},
> +	{LM3532_REG_ENABLE, 0xf8},
> +	{LM3532_ALS_CONFIG, 0x44},
> +	{LM3532_REG_ZN_0_HI, 0x35},
> +	{LM3532_REG_ZN_0_LO, 0x33},
> +	{LM3532_REG_ZN_1_HI, 0x6a},
> +	{LM3532_REG_ZN_1_LO, 0x66},
> +	{LM3532_REG_ZN_2_HI, 0xa1},
> +	{LM3532_REG_ZN_2_LO, 0x99},
> +	{LM3532_REG_ZN_3_HI, 0xdc},
> +	{LM3532_REG_ZN_3_LO, 0xcc},
> +};
> +
> +static const struct regmap_config lm3532_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +
> +	.max_register = LM3532_REG_MAX,
> +	.reg_defaults = lm3532_reg_defs,
> +	.num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
> +	.cache_type = REGCACHE_FLAT,
> +};
> +
> +static int lm3532_led_enable(struct lm3532_led *led_data)
> +{
> +	int ctrl_en_val;
> +	int ret;
> +
> +	switch (led_data->control_bank) {
> +	case LM3532_CONTROL_A:
> +		ctrl_en_val = LM3532_CTRL_A_ENABLE;
> +		break;
> +	case LM3532_CONTROL_B:
> +		ctrl_en_val = LM3532_CTRL_B_ENABLE;
> +		break;
> +	case LM3532_CONTROL_C:
> +		ctrl_en_val = LM3532_CTRL_C_ENABLE;
> +		break;
> +	default:
> +		dev_err(led_data->priv->dev, "Invalid control bank\n");

If control_bank was validated in lm3532_parse_node(), then you wouldn't
have to take into account this option here.

Besides, you don't need this switch statement, but can easily calculate
ctrl_en_val:

#define LM3532_GET_CTRL_BANK_EN_VAL(bank_id) BIT(bank_id)

> +		return -EINVAL;
> +	};
> +
> +	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
> +					 ctrl_en_val, ctrl_en_val);
> +	if (ret) {
> +		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
> +		return ret;
> +	}
> +
> +	return regulator_enable(led_data->priv->regulator);
> +}
> +
> +static int lm3532_led_disable(struct lm3532_led *led_data)
> +{
> +	int ctrl_en_val;
> +	int ret;
> +
> +	switch (led_data->control_bank) {
> +	case LM3532_CONTROL_A:
> +		ctrl_en_val = LM3532_CTRL_A_ENABLE;
> +		break;
> +	case LM3532_CONTROL_B:
> +		ctrl_en_val = LM3532_CTRL_B_ENABLE;
> +		break;
> +	case LM3532_CONTROL_C:
> +		ctrl_en_val = LM3532_CTRL_C_ENABLE;
> +		break;
> +	default:
> +		dev_err(led_data->priv->dev, "Invalid control bank\n");
> +		return -EINVAL;
> +	};

Ditto.

> +
> +	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
> +					 ctrl_en_val, ~ctrl_en_val);
> +	if (ret) {
> +		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
> +		return ret;
> +	}
> +
> +	return regulator_disable(led_data->priv->regulator);
> +}
> +
> +static int lm3532_brightness_set(struct led_classdev *led_cdev,
> +				 enum led_brightness brt_val)
> +{
> +	struct lm3532_led *led =
> +			container_of(led_cdev, struct lm3532_led, led_dev);
> +	u8 brightnes_reg;
> +	int ret;
> +
> +	mutex_lock(&led->priv->lock);
> +
> +	if (led->mode == LM3532_BL_MODE_ALS) {
> +		ret = 0;
> +		goto unlock;
> +	}
> +
> +	switch (led->control_bank) {
> +	case LM3532_CONTROL_A:
> +		brightnes_reg = LM3532_REG_CTRL_A_BRT;
> +		break;
> +	case LM3532_CONTROL_B:
> +		brightnes_reg = LM3532_REG_CTRL_B_BRT;
> +		break;
> +	case LM3532_CONTROL_C:
> +		brightnes_reg = LM3532_REG_CTRL_C_BRT;
> +		break;
> +	default:
> +		dev_err(led->priv->dev, "Invalid control bank\n");
> +		ret = -EINVAL;
> +		goto unlock;
> +	};

Similarly here. use following macro:

#define LM3532_GET_CTRL_BANK_BRT_REG (bank_id) 
BIT((LM3532_REG_CTRL_A_BRT + bank_id*2))

> +	if (brt_val == LED_OFF) {
> +		ret = lm3532_led_disable(led);
> +		goto unlock;
> +	}
> +
> +	lm3532_led_enable(led);
> +	brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
> +
> +	ret = regmap_write(led->priv->regmap, brightnes_reg, brt_val);
> +
> +unlock:
> +	mutex_unlock(&led->priv->lock);
> +	return ret;
> +}
> +
> +static int lm3532_init_registers(struct lm3532_led *led)
> +{
> +	struct lm3532_data *drvdata = led->priv;
> +	unsigned int runtime_ramp_val;
> +	unsigned int output_cfg_val = 0;
> +	unsigned int output_cfg_shift = 0;
> +	unsigned int output_cfg_mask = 0;
> +	int ret, i;
> +
> +	for (i = 0; i < led->num_leds; i++) {
> +		output_cfg_shift = led->led_strings[i] * 2;
> +		output_cfg_val |= (led->control_bank << output_cfg_shift);
> +		output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
> +	}
> +
> +	ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
> +				 output_cfg_mask, output_cfg_val);
> +
> +	runtime_ramp_val = drvdata->runtime_ramp_up |
> +			 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
> +
> +	return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
> +			    runtime_ramp_val);
> +}
> +
> +static int lm3532_als_configure(struct lm3532_data *priv)
> +{
> +	struct lm3532_als_data *als = priv->als_data;
> +	u32 als_vmin, als_vmax, als_vstep;
> +	int zone_reg = LM3532_REG_ZN_0_HI;
> +	int ret;
> +	int i;
> +
> +	als_vmin = als->als_vmin;
> +	als_vmax = als->als_vmax;
> +
> +	als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
> +
> +	for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
> +		als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
> +				LED_FULL) / 1000;
> +		als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
> +				als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
> +
> +		zone_reg = LM3532_REG_ZN_0_HI + i * 2;
> +		ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
> +		if (ret)
> +			return ret;
> +
> +		zone_reg += 1;
> +		ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
> +		(als->als_input_mode << LM3532_ALS_SEL_SHIFT));
> +
> +	return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
> +}
> +
> +static int lm3532_parse_als(struct lm3532_data *priv)
> +{
> +	struct lm3532_als_data *als;
> +	int ret;
> +
> +	als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
> +	if (als == NULL)
> +		return -ENOMEM;
> +
> +	ret = device_property_read_u32(&priv->client->dev, "als-vmin",
> +				       &als->als_vmin);
> +	if (ret)
> +		als->als_vmin = 0;
> +
> +	ret = device_property_read_u32(&priv->client->dev, "als-vmax",
> +				       &als->als_vmax);
> +	if (ret)
> +		als->als_vmax = LM3532_ALS_WINDOW_mV;
> +
> +	ret = device_property_read_u8(&priv->client->dev, "als1-imp-sel",
> +				      &als->als1_imp_sel);
> +	if (ret)
> +		als->als1_imp_sel = 0;
> +
> +	ret = device_property_read_u8(&priv->client->dev, "als2-imp-sel",
> +				      &als->als2_imp_sel);
> +	if (ret)
> +		als->als2_imp_sel = 0;
> +
> +	ret = device_property_read_u8(&priv->client->dev, "als-avrg-time",
> +				      &als->als_avrg_time);
> +	if (ret)
> +		als->als_avrg_time = 0;
> +
> +	ret = device_property_read_u8(&priv->client->dev, "als-input-mode",
> +				      &als->als_input_mode);
> +	if (ret)
> +		als->als_input_mode = 0;
> +
> +	priv->als_data = als;
> +
> +	return ret;
> +}
> +
> +static int lm3532_parse_node(struct lm3532_data *priv)
> +{
> +	struct fwnode_handle *child = NULL;
> +	struct lm3532_led *led;
> +	const char *name;
> +	int control_bank;
> +	size_t i = 0;
> +	int ret;
> +
> +	priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
> +						   "enable", GPIOD_OUT_LOW);
> +	if (IS_ERR(priv->enable_gpio))
> +		priv->enable_gpio = NULL;
> +
> +	priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
> +	if (IS_ERR(priv->regulator))
> +		priv->regulator = NULL;
> +
> +	ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
> +				       &priv->runtime_ramp_up);
> +	if (ret)
> +		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
> +
> +	ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
> +				       &priv->runtime_ramp_down);
> +	if (ret)
> +		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
> +
> +	device_for_each_child_node(priv->dev, child) {
> +		led = &priv->leds[i];
> +
> +		ret = fwnode_property_read_u32(child, "reg", &control_bank);
> +		if (ret) {
> +			dev_err(&priv->client->dev, "reg property missing\n");
> +			fwnode_handle_put(child);
> +			goto child_out;
> +		}
> +
> +		if (control_bank > LM3532_CONTROL_C) {
> +			dev_err(&priv->client->dev, "Control bank invalid\n");
> +			continue;
> +		}
> +
> +		led->control_bank = control_bank;
> +
> +		ret = fwnode_property_read_u32(child, "ti,led-mode",
> +					       &led->mode);
> +		if (ret) {
> +			dev_err(&priv->client->dev, "ti,led-mode property missing\n");
> +			fwnode_handle_put(child);
> +			goto child_out;
> +		}
> +
> +		if (led->mode == LM3532_BL_MODE_ALS) {
> +			ret = lm3532_parse_als(priv);
> +			if (ret)
> +				dev_err(&priv->client->dev, "Failed to parse als\n");
> +			else
> +				lm3532_als_configure(priv);
> +		}
> +
> +		led->num_leds = fwnode_property_read_u32_array(child,
> +							       "led-sources",
> +							       NULL, 0);
> +
> +		if (led->num_leds > LM3532_MAX_LED_STRINGS) {
> +			dev_err(&priv->client->dev, "To many LED string defined\n");
> +			continue;
> +		}
> +
> +		ret = fwnode_property_read_u32_array(child, "led-sources",
> +						    led->led_strings,
> +						    led->num_leds);
> +		if (ret) {
> +			dev_err(&priv->client->dev, "led-sources property missing\n");
> +			fwnode_handle_put(child);
> +			goto child_out;
> +		}
> +
> +		fwnode_property_read_string(child, "linux,default-trigger",
> +					    &led->led_dev.default_trigger);
> +
> +		ret = fwnode_property_read_string(child, "label", &name);
> +		if (ret)
> +			snprintf(led->label, sizeof(led->label),
> +				"%s::", priv->client->name);
> +		else
> +			snprintf(led->label, sizeof(led->label),
> +				 "%s:%s", priv->client->name, name);
> +
> +		led->priv = priv;
> +		led->led_dev.name = led->label;
> +		led->led_dev.brightness_set_blocking = lm3532_brightness_set;
> +
> +		ret = devm_led_classdev_register(priv->dev, &led->led_dev);
> +		if (ret) {
> +			dev_err(&priv->client->dev, "led register err: %d\n",
> +				ret);
> +			fwnode_handle_put(child);
> +			goto child_out;
> +		}
> +
> +		lm3532_init_registers(led);
> +
> +		i++;
> +	}
> +
> +child_out:
> +	return ret;
> +}
> +
> +static int lm3532_probe(struct i2c_client *client,
> +			   const struct i2c_device_id *id)
> +{
> +	struct lm3532_data *drvdata;
> +	int ret = 0;
> +	int count;
> +
> +	count = device_get_child_node_count(&client->dev);
> +	if (!count) {
> +		dev_err(&client->dev, "LEDs are not defined in device tree!");
> +		return -ENODEV;
> +	}
> +
> +	drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
> +			   GFP_KERNEL);
> +	if (drvdata == NULL)
> +		return -ENOMEM;
> +
> +	drvdata->client = client;
> +	drvdata->dev = &client->dev;
> +
> +	drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
> +	if (IS_ERR(drvdata->regmap)) {
> +		ret = PTR_ERR(drvdata->regmap);
> +		dev_err(&client->dev, "Failed to allocate register map: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	mutex_init(&drvdata->lock);
> +	i2c_set_clientdata(client, drvdata);
> +
> +	ret = lm3532_parse_node(drvdata);
> +	if (ret) {
> +		dev_err(&client->dev, "Failed to parse node\n");
> +		return ret;
> +	}
> +
> +	if (drvdata->enable_gpio)
> +		gpiod_direction_output(drvdata->enable_gpio, 1);
> +
> +	return ret;
> +}
> +
> +static int lm3532_remove(struct i2c_client *client)
> +{
> +	struct lm3532_data *drvdata = i2c_get_clientdata(client);

mutex_destroy() is missing here.

> +	if (drvdata->enable_gpio)
> +		gpiod_direction_output(drvdata->enable_gpio, 0);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id of_lm3532_leds_match[] = {
> +	{ .compatible = "ti,lm3532", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
> +
> +static const struct i2c_device_id lm3532_id[] = {
> +	{LM3532_NAME, 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, lm3532_id);
> +
> +static struct i2c_driver lm3532_i2c_driver = {
> +	.probe = lm3532_probe,
> +	.remove = lm3532_remove,
> +	.id_table = lm3532_id,
> +	.driver = {
> +		.name = LM3532_NAME,
> +		.of_match_table = of_lm3532_leds_match,
> +	},
> +};
> +module_i2c_driver(lm3532_i2c_driver);
> +
> +MODULE_DESCRIPTION("Back Light driver for LM3532");
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
> diff --git a/include/dt-bindings/leds/leds-lm3532.h b/include/dt-bindings/leds/leds-lm3532.h
> new file mode 100644
> index 000000000000..724dbc0cb395
> --- /dev/null
> +++ b/include/dt-bindings/leds/leds-lm3532.h

This should go in a separate patch, with DT bindings - see checkpatch.pl
complaint.

> @@ -0,0 +1,72 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* TI LM3532 LED driver
> + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
> + */
> +
> +#ifndef __DT_BINDINGS_LEDS_LM3532_H
> +#define __DT_BINDINGS_LEDS_LM3532_H
> +
> +#define LM3532_BL_MODE_MANUAL	0x00 /* "man" */
> +#define LM3532_BL_MODE_ALS	0x01 /* "als" */
> +
> +/* ALS Resistor Select */
> +#define LM3532_IMP_HIGH		0x00
> +#define LM3532_IMP_37K		0x01
> +#define LM3532_IMP_18_5K	0x02
> +#define LM3532_IMP_12_33K	0x03
> +#define LM3532_IMP_9_25K	0x04
> +#define LM3532_IMP_7_4K		0x05
> +#define LM3532_IMP_6_17K	0x06
> +#define LM3532_IMP_5_29K	0x07
> +#define LM3532_IMP_4_63K	0x08
> +#define LM3532_IMP_4_11K	0x09
> +#define LM3532_IMP_3_7K		0x0a
> +#define LM3532_IMP_3_36K	0x0b
> +#define LM3532_IMP_3_08K	0x0c
> +#define LM3532_IMP_2_85K	0x0d
> +#define LM3532_IMP_2_64K	0x0e
> +#define LM3532_IMP_2_44K	0x0f
> +#define LM3532_IMP_2_31K	0x10
> +#define LM3532_IMP_2_18K	0x11
> +#define LM3532_IMP_2_06K	0x12
> +#define LM3532_IMP_1_95K	0x13
> +#define LM3532_IMP_1_85K	0x14
> +#define LM3532_IMP_1_76K	0x15
> +#define LM3532_IMP_1_68K	0x16
> +#define LM3532_IMP_1_61K	0x17
> +#define LM3532_IMP_1_54K	0x18
> +#define LM3532_IMP_1_48K	0x19
> +#define LM3532_IMP_1_42K	0x1a
> +#define LM3532_IMP_1_37K	0x1b
> +#define LM3532_IMP_1_32K	0x1c
> +#define LM3532_IMP_1_28K	0x1d
> +#define LM3532_IMP_1_23K	0x1e
> +#define LM3532_IMP_1_19K	0x1f
> +
> +/* ALS Averaging Time */
> +#define LM3532_ALS_AVRG_TIME_17_92ms	0x00
> +#define LM3532_ALS_AVRG_TIME_35_84ms	0x01
> +#define LM3532_ALS_AVRG_TIME_71_68ms	0x02
> +#define LM3532_ALS_AVRG_TIME_143_36ms	0x03
> +#define LM3532_ALS_AVRG_TIME_286_72ms	0x04
> +#define LM3532_ALS_AVRG_TIME_573_44ms	0x05
> +#define LM3532_ALS_AVRG_TIME_1146_88ms	0x06
> +#define LM3532_ALS_AVRG_TIME_2293_76ms	0x07
> +
> +/* ALS input select */
> +#define LM3532_ALS_INPUT_AVRG	0x00 /* ALS1 and ALS2 input average */
> +#define LM3532_ALS_INPUT_ALS1	0x01 /* ALS1 Input */
> +#define LM3532_ALS_INPUT_ALS2	0x02 /* ALS2 Input */
> +#define LM3532_ALS_INPUT_CEIL	0x03 /* Max of ALS1 and ALS2 */
> +
> +/* Ramp Times */
> +#define LM3532_RAMP_8us		0x00
> +#define LM3532_RAMP_1024us	0x01
> +#define LM3532_RAMP_2048us	0x02
> +#define LM3532_RAMP_4096us	0x03
> +#define LM3532_RAMP_8192us	0x04
> +#define LM3532_RAMP_16384us	0x05
> +#define LM3532_RAMP_32768us	0x06
> +#define LM3532_RAMP_65536us	0x07
> +
> +#endif /* __DT_BINDINGS_LEDS_LM3532_H */
> 

-- 
Best regards,
Jacek Anaszewski

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-07 22:09   ` Dan Murphy
@ 2019-03-08 13:28     ` Dan Murphy
  -1 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-08 13:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Hello

On 3/7/19 4:09 PM, Dan Murphy wrote:
> Introduce the Texas Instruments LM3532 White LED driver.
> The driver supports ALS configurability or manual brightness
> control.
> 
> The driver also supports associating LED strings with specific
> control banks in a group or as individually controlled strings.
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
>  drivers/leds/Kconfig                   |  10 +
>  drivers/leds/Makefile                  |   1 +
>  drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
>  include/dt-bindings/leds/leds-lm3532.h |  72 +++
>  4 files changed, 678 insertions(+)
>  create mode 100644 drivers/leds/leds-lm3532.c
>  create mode 100644 include/dt-bindings/leds/leds-lm3532.h
> 

After thinking about this dt header I am not happy about having it.
I am thinking of removing this file completely and doing some calculations in the driver
file for the impedance, averaging time and ramp times.

I would still like to get comments on the rest of the code but in v2 the dt bindings header will
go away.

Dan

<snip>
-- 
------------------
Dan Murphy

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

* Re: [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-08 13:28     ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-08 13:28 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds

Hello

On 3/7/19 4:09 PM, Dan Murphy wrote:
> Introduce the Texas Instruments LM3532 White LED driver.
> The driver supports ALS configurability or manual brightness
> control.
> 
> The driver also supports associating LED strings with specific
> control banks in a group or as individually controlled strings.
> 
> Signed-off-by: Dan Murphy <dmurphy@ti.com>
> ---
>  drivers/leds/Kconfig                   |  10 +
>  drivers/leds/Makefile                  |   1 +
>  drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
>  include/dt-bindings/leds/leds-lm3532.h |  72 +++
>  4 files changed, 678 insertions(+)
>  create mode 100644 drivers/leds/leds-lm3532.c
>  create mode 100644 include/dt-bindings/leds/leds-lm3532.h
> 

After thinking about this dt header I am not happy about having it.
I am thinking of removing this file completely and doing some calculations in the driver
file for the impedance, averaging time and ramp times.

I would still like to get comments on the rest of the code but in v2 the dt bindings header will
go away.

Dan

<snip>
-- 
------------------
Dan Murphy

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

* [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
  2019-03-07 22:09 Dan Murphy
@ 2019-03-07 22:09   ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-07 22:09 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Introduce the Texas Instruments LM3532 White LED driver.
The driver supports ALS configurability or manual brightness
control.

The driver also supports associating LED strings with specific
control banks in a group or as individually controlled strings.

Signed-off-by: Dan Murphy <dmurphy@ti.com>
---
 drivers/leds/Kconfig                   |  10 +
 drivers/leds/Makefile                  |   1 +
 drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
 include/dt-bindings/leds/leds-lm3532.h |  72 +++
 4 files changed, 678 insertions(+)
 create mode 100644 drivers/leds/leds-lm3532.c
 create mode 100644 include/dt-bindings/leds/leds-lm3532.h

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a72f97fca57b..da00b9ed5a5c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -138,6 +138,16 @@ config LEDS_LM3530
 	  controlled manually or using PWM input or using ambient
 	  light automatically.
 
+config LEDS_LM3532
+	tristate "LCD Backlight driver for LM3532"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for the LCD backlight using
+	  LM3532 ambient light sensor chip. This ALS chip can be
+	  controlled manually or using PWM input or using ambient
+	  light automatically.
+
 config LEDS_LM3533
 	tristate "LED support for LM3533"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 4c1b0054f379..7a8b1f55d459 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_CPCAP)		+= leds-cpcap.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
+obj-$(CONFIG_LEDS_LM3532)		+= leds-lm3532.o
 obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
 obj-$(CONFIG_LEDS_LM3642)		+= leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
new file mode 100644
index 000000000000..005478359d06
--- /dev/null
+++ b/drivers/leds/leds-lm3532.c
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: GPL-2.0
+// TI LM3532 LED driver
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <uapi/linux/uleds.h>
+#include <linux/gpio/consumer.h>
+
+#include <dt-bindings/leds/leds-lm3532.h>
+
+#define LM3532_NAME "lm3532-led"
+
+#define LM3532_REG_OUTPUT_CFG	0x10
+#define LM3532_REG_STARTSHUT_RAMP	0x11
+#define LM3532_REG_RT_RAMP	0x12
+#define LM3532_REG_PWM_A_CFG	0x13
+#define LM3532_REG_PWM_B_CFG	0x14
+#define LM3532_REG_PWM_C_CFG	0x15
+#define LM3532_REG_ZONE_CFG_A	0x16
+#define LM3532_REG_CTRL_A_BRT	0x17
+#define LM3532_REG_ZONE_CFG_B	0x18
+#define LM3532_REG_CTRL_B_BRT	0x19
+#define LM3532_REG_ZONE_CFG_C	0x1a
+#define LM3532_REG_CTRL_C_BRT	0x1b
+#define LM3532_REG_ENABLE	0x1d
+#define LM3532_ALS_CONFIG	0x23
+#define LM3532_REG_ZN_0_HI	0x60
+#define LM3532_REG_ZN_0_LO	0x61
+#define LM3532_REG_ZN_1_HI	0x62
+#define LM3532_REG_ZN_1_LO	0x63
+#define LM3532_REG_ZN_2_HI	0x64
+#define LM3532_REG_ZN_2_LO	0x65
+#define LM3532_REG_ZN_3_HI	0x66
+#define LM3532_REG_ZN_3_LO	0x67
+#define LM3532_REG_MAX		0x7e
+
+/* Contorl Enable */
+#define LM3532_CTRL_A_ENABLE	BIT(0)
+#define LM3532_CTRL_B_ENABLE	BIT(1)
+#define LM3532_CTRL_C_ENABLE	BIT(2)
+
+/* PWM Zone Control */
+#define LM3532_PWM_ZONE_MASK	0x7c
+#define LM3532_PWM_ZONE_0_EN	BIT(2)
+#define LM3532_PWM_ZONE_1_EN	BIT(3)
+#define LM3532_PWM_ZONE_2_EN	BIT(4)
+#define LM3532_PWM_ZONE_3_EN	BIT(5)
+#define LM3532_PWM_ZONE_4_EN	BIT(6)
+
+/* Brightness Configuration */
+#define LM3532_I2C_CTRL		BIT(0)
+#define LM3532_LINEAR_MAP	BIT(1)
+#define LM3532_ZONE_MASK	(BIT(2) | BIT(3) | BIT(4))
+#define LM3532_ZONE_0		0
+#define LM3532_ZONE_1		BIT(2)
+#define LM3532_ZONE_2		BIT(3)
+#define LM3532_ZONE_3		(BIT(2) | BIT(3))
+#define LM3532_ZONE_4		BIT(4)
+
+#define LM3532_ENABLE_ALS	BIT(3)
+#define LM3532_ALS_SEL_SHIFT	6
+
+/* Zone Boundary Register */
+#define LM3532_ALS_WINDOW_mV	2000
+#define LM3532_ALS_ZB_MAX	4
+#define LM3532_ALS_OFFSET_mV	2
+
+#define LM3532_CONTROL_A	0
+#define LM3532_CONTROL_B	1
+#define LM3532_CONTROL_C	2
+#define LM3532_MAX_CONTROL_BANKS 3
+#define LM3532_MAX_LED_STRINGS	3
+
+#define LM3532_OUTPUT_CFG_MASK	0x3
+#define LM3532_BRT_VAL_ADJUST	8
+#define LM3532_RAMP_DOWN_SHIFT	3
+
+/*
+ * struct lm3532_als_data
+ * @config - value of ALS configuration register
+ * @als1_imp_sel - value of ALS1 resistor select register
+ * @als2_imp_sel - value of ALS2 resistor select register
+ * @als_avrg_time - ALS averaging time
+ * @als_input_mode - ALS input mode for brightness control
+ * @als_vmin - Minimum ALS voltage
+ * @als_vmax - Maximum ALS voltage
+ * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
+ * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
+ */
+struct lm3532_als_data {
+	u8 config;
+	u8 als1_imp_sel;
+	u8 als2_imp_sel;
+	u8 als_avrg_time;
+	u8 als_input_mode;
+	u32 als_vmin;
+	u32 als_vmax;
+	u8 zones_lo[LM3532_ALS_ZB_MAX];
+	u8 zones_hi[LM3532_ALS_ZB_MAX];
+};
+
+/**
+ * struct lm3532_led
+ * @led_dev: led class device
+ * @priv - Pointer the device data structure
+ * @control_bank - Control bank the LED is associated to
+ * @mode - Mode of the LED string
+ * @num_leds - Number of LED strings are supported in this array
+ * @led_strings - The LED strings supported in this array
+ * @label - LED label
+ */
+struct lm3532_led {
+	struct led_classdev led_dev;
+	struct lm3532_data *priv;
+
+	int control_bank;
+	int mode;
+	int num_leds;
+	u32 led_strings[LM3532_MAX_CONTROL_BANKS];
+	char label[LED_MAX_NAME_SIZE];
+};
+
+/**
+ * struct lm3532_data
+ * @enable_gpio - Hardware enable gpio
+ * @regulator: regulator
+ * @client: i2c client
+ * @regmap - Devices register map
+ * @dev - Pointer to the devices device struct
+ * @lock - Lock for reading/writing the device
+ * @als_data - Pointer to the als data struct
+ * @runtime_ramp_up - Runtime ramp up setting
+ * @runtime_ramp_down - Runtime ramp down setting
+ * @leds - Array of LED strings
+ */
+struct lm3532_data {
+	struct gpio_desc *enable_gpio;
+	struct regulator *regulator;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct device *dev;
+	struct mutex lock;
+
+	struct lm3532_als_data *als_data;
+
+	u32 runtime_ramp_up;
+	u32 runtime_ramp_down;
+
+	struct lm3532_led leds[];
+};
+
+static const struct reg_default lm3532_reg_defs[] = {
+	{LM3532_REG_OUTPUT_CFG, 0xe4},
+	{LM3532_REG_STARTSHUT_RAMP, 0xc0},
+	{LM3532_REG_RT_RAMP, 0xc0},
+	{LM3532_REG_PWM_A_CFG, 0x82},
+	{LM3532_REG_PWM_B_CFG, 0x82},
+	{LM3532_REG_PWM_C_CFG, 0x82},
+	{LM3532_REG_ZONE_CFG_A, 0xf1},
+	{LM3532_REG_CTRL_A_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_B, 0xf1},
+	{LM3532_REG_CTRL_B_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_C, 0xf1},
+	{LM3532_REG_CTRL_C_BRT, 0xf3},
+	{LM3532_REG_ENABLE, 0xf8},
+	{LM3532_ALS_CONFIG, 0x44},
+	{LM3532_REG_ZN_0_HI, 0x35},
+	{LM3532_REG_ZN_0_LO, 0x33},
+	{LM3532_REG_ZN_1_HI, 0x6a},
+	{LM3532_REG_ZN_1_LO, 0x66},
+	{LM3532_REG_ZN_2_HI, 0xa1},
+	{LM3532_REG_ZN_2_LO, 0x99},
+	{LM3532_REG_ZN_3_HI, 0xdc},
+	{LM3532_REG_ZN_3_LO, 0xcc},
+};
+
+static const struct regmap_config lm3532_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = LM3532_REG_MAX,
+	.reg_defaults = lm3532_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
+	.cache_type = REGCACHE_FLAT,
+};
+
+static int lm3532_led_enable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val;
+	int ret;
+
+	switch (led_data->control_bank) {
+	case LM3532_CONTROL_A:
+		ctrl_en_val = LM3532_CTRL_A_ENABLE;
+		break;
+	case LM3532_CONTROL_B:
+		ctrl_en_val = LM3532_CTRL_B_ENABLE;
+		break;
+	case LM3532_CONTROL_C:
+		ctrl_en_val = LM3532_CTRL_C_ENABLE;
+		break;
+	default:
+		dev_err(led_data->priv->dev, "Invalid control bank\n");
+		return -EINVAL;
+	};
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_enable(led_data->priv->regulator);
+}
+
+static int lm3532_led_disable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val;
+	int ret;
+
+	switch (led_data->control_bank) {
+	case LM3532_CONTROL_A:
+		ctrl_en_val = LM3532_CTRL_A_ENABLE;
+		break;
+	case LM3532_CONTROL_B:
+		ctrl_en_val = LM3532_CTRL_B_ENABLE;
+		break;
+	case LM3532_CONTROL_C:
+		ctrl_en_val = LM3532_CTRL_C_ENABLE;
+		break;
+	default:
+		dev_err(led_data->priv->dev, "Invalid control bank\n");
+		return -EINVAL;
+	};
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ~ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_disable(led_data->priv->regulator);
+}
+
+static int lm3532_brightness_set(struct led_classdev *led_cdev,
+				 enum led_brightness brt_val)
+{
+	struct lm3532_led *led =
+			container_of(led_cdev, struct lm3532_led, led_dev);
+	u8 brightnes_reg;
+	int ret;
+
+	mutex_lock(&led->priv->lock);
+
+	if (led->mode == LM3532_BL_MODE_ALS) {
+		ret = 0;
+		goto unlock;
+	}
+
+	switch (led->control_bank) {
+	case LM3532_CONTROL_A:
+		brightnes_reg = LM3532_REG_CTRL_A_BRT;
+		break;
+	case LM3532_CONTROL_B:
+		brightnes_reg = LM3532_REG_CTRL_B_BRT;
+		break;
+	case LM3532_CONTROL_C:
+		brightnes_reg = LM3532_REG_CTRL_C_BRT;
+		break;
+	default:
+		dev_err(led->priv->dev, "Invalid control bank\n");
+		ret = -EINVAL;
+		goto unlock;
+	};
+
+	if (brt_val == LED_OFF) {
+		ret = lm3532_led_disable(led);
+		goto unlock;
+	}
+
+	lm3532_led_enable(led);
+	brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
+
+	ret = regmap_write(led->priv->regmap, brightnes_reg, brt_val);
+
+unlock:
+	mutex_unlock(&led->priv->lock);
+	return ret;
+}
+
+static int lm3532_init_registers(struct lm3532_led *led)
+{
+	struct lm3532_data *drvdata = led->priv;
+	unsigned int runtime_ramp_val;
+	unsigned int output_cfg_val = 0;
+	unsigned int output_cfg_shift = 0;
+	unsigned int output_cfg_mask = 0;
+	int ret, i;
+
+	for (i = 0; i < led->num_leds; i++) {
+		output_cfg_shift = led->led_strings[i] * 2;
+		output_cfg_val |= (led->control_bank << output_cfg_shift);
+		output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
+	}
+
+	ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
+				 output_cfg_mask, output_cfg_val);
+
+	runtime_ramp_val = drvdata->runtime_ramp_up |
+			 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
+
+	return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
+			    runtime_ramp_val);
+}
+
+static int lm3532_als_configure(struct lm3532_data *priv)
+{
+	struct lm3532_als_data *als = priv->als_data;
+	u32 als_vmin, als_vmax, als_vstep;
+	int zone_reg = LM3532_REG_ZN_0_HI;
+	int ret;
+	int i;
+
+	als_vmin = als->als_vmin;
+	als_vmax = als->als_vmax;
+
+	als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
+
+	for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
+		als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
+				LED_FULL) / 1000;
+		als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
+				als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
+
+		zone_reg = LM3532_REG_ZN_0_HI + i * 2;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
+		if (ret)
+			return ret;
+
+		zone_reg += 1;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
+		if (ret)
+			return ret;
+	}
+
+	als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
+		(als->als_input_mode << LM3532_ALS_SEL_SHIFT));
+
+	return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
+}
+
+static int lm3532_parse_als(struct lm3532_data *priv)
+{
+	struct lm3532_als_data *als;
+	int ret;
+
+	als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
+	if (als == NULL)
+		return -ENOMEM;
+
+	ret = device_property_read_u32(&priv->client->dev, "als-vmin",
+				       &als->als_vmin);
+	if (ret)
+		als->als_vmin = 0;
+
+	ret = device_property_read_u32(&priv->client->dev, "als-vmax",
+				       &als->als_vmax);
+	if (ret)
+		als->als_vmax = LM3532_ALS_WINDOW_mV;
+
+	ret = device_property_read_u8(&priv->client->dev, "als1-imp-sel",
+				      &als->als1_imp_sel);
+	if (ret)
+		als->als1_imp_sel = 0;
+
+	ret = device_property_read_u8(&priv->client->dev, "als2-imp-sel",
+				      &als->als2_imp_sel);
+	if (ret)
+		als->als2_imp_sel = 0;
+
+	ret = device_property_read_u8(&priv->client->dev, "als-avrg-time",
+				      &als->als_avrg_time);
+	if (ret)
+		als->als_avrg_time = 0;
+
+	ret = device_property_read_u8(&priv->client->dev, "als-input-mode",
+				      &als->als_input_mode);
+	if (ret)
+		als->als_input_mode = 0;
+
+	priv->als_data = als;
+
+	return ret;
+}
+
+static int lm3532_parse_node(struct lm3532_data *priv)
+{
+	struct fwnode_handle *child = NULL;
+	struct lm3532_led *led;
+	const char *name;
+	int control_bank;
+	size_t i = 0;
+	int ret;
+
+	priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
+						   "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->enable_gpio))
+		priv->enable_gpio = NULL;
+
+	priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
+	if (IS_ERR(priv->regulator))
+		priv->regulator = NULL;
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
+				       &priv->runtime_ramp_up);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
+				       &priv->runtime_ramp_down);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+
+	device_for_each_child_node(priv->dev, child) {
+		led = &priv->leds[i];
+
+		ret = fwnode_property_read_u32(child, "reg", &control_bank);
+		if (ret) {
+			dev_err(&priv->client->dev, "reg property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (control_bank > LM3532_CONTROL_C) {
+			dev_err(&priv->client->dev, "Control bank invalid\n");
+			continue;
+		}
+
+		led->control_bank = control_bank;
+
+		ret = fwnode_property_read_u32(child, "ti,led-mode",
+					       &led->mode);
+		if (ret) {
+			dev_err(&priv->client->dev, "ti,led-mode property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (led->mode == LM3532_BL_MODE_ALS) {
+			ret = lm3532_parse_als(priv);
+			if (ret)
+				dev_err(&priv->client->dev, "Failed to parse als\n");
+			else
+				lm3532_als_configure(priv);
+		}
+
+		led->num_leds = fwnode_property_read_u32_array(child,
+							       "led-sources",
+							       NULL, 0);
+
+		if (led->num_leds > LM3532_MAX_LED_STRINGS) {
+			dev_err(&priv->client->dev, "To many LED string defined\n");
+			continue;
+		}
+
+		ret = fwnode_property_read_u32_array(child, "led-sources",
+						    led->led_strings,
+						    led->num_leds);
+		if (ret) {
+			dev_err(&priv->client->dev, "led-sources property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		fwnode_property_read_string(child, "linux,default-trigger",
+					    &led->led_dev.default_trigger);
+
+		ret = fwnode_property_read_string(child, "label", &name);
+		if (ret)
+			snprintf(led->label, sizeof(led->label),
+				"%s::", priv->client->name);
+		else
+			snprintf(led->label, sizeof(led->label),
+				 "%s:%s", priv->client->name, name);
+
+		led->priv = priv;
+		led->led_dev.name = led->label;
+		led->led_dev.brightness_set_blocking = lm3532_brightness_set;
+
+		ret = devm_led_classdev_register(priv->dev, &led->led_dev);
+		if (ret) {
+			dev_err(&priv->client->dev, "led register err: %d\n",
+				ret);
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		lm3532_init_registers(led);
+
+		i++;
+	}
+
+child_out:
+	return ret;
+}
+
+static int lm3532_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct lm3532_data *drvdata;
+	int ret = 0;
+	int count;
+
+	count = device_get_child_node_count(&client->dev);
+	if (!count) {
+		dev_err(&client->dev, "LEDs are not defined in device tree!");
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
+			   GFP_KERNEL);
+	if (drvdata == NULL)
+		return -ENOMEM;
+
+	drvdata->client = client;
+	drvdata->dev = &client->dev;
+
+	drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
+	if (IS_ERR(drvdata->regmap)) {
+		ret = PTR_ERR(drvdata->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	mutex_init(&drvdata->lock);
+	i2c_set_clientdata(client, drvdata);
+
+	ret = lm3532_parse_node(drvdata);
+	if (ret) {
+		dev_err(&client->dev, "Failed to parse node\n");
+		return ret;
+	}
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 1);
+
+	return ret;
+}
+
+static int lm3532_remove(struct i2c_client *client)
+{
+	struct lm3532_data *drvdata = i2c_get_clientdata(client);
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 0);
+
+	return 0;
+}
+
+static const struct of_device_id of_lm3532_leds_match[] = {
+	{ .compatible = "ti,lm3532", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
+
+static const struct i2c_device_id lm3532_id[] = {
+	{LM3532_NAME, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, lm3532_id);
+
+static struct i2c_driver lm3532_i2c_driver = {
+	.probe = lm3532_probe,
+	.remove = lm3532_remove,
+	.id_table = lm3532_id,
+	.driver = {
+		.name = LM3532_NAME,
+		.of_match_table = of_lm3532_leds_match,
+	},
+};
+module_i2c_driver(lm3532_i2c_driver);
+
+MODULE_DESCRIPTION("Back Light driver for LM3532");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
diff --git a/include/dt-bindings/leds/leds-lm3532.h b/include/dt-bindings/leds/leds-lm3532.h
new file mode 100644
index 000000000000..724dbc0cb395
--- /dev/null
+++ b/include/dt-bindings/leds/leds-lm3532.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* TI LM3532 LED driver
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#ifndef __DT_BINDINGS_LEDS_LM3532_H
+#define __DT_BINDINGS_LEDS_LM3532_H
+
+#define LM3532_BL_MODE_MANUAL	0x00 /* "man" */
+#define LM3532_BL_MODE_ALS	0x01 /* "als" */
+
+/* ALS Resistor Select */
+#define LM3532_IMP_HIGH		0x00
+#define LM3532_IMP_37K		0x01
+#define LM3532_IMP_18_5K	0x02
+#define LM3532_IMP_12_33K	0x03
+#define LM3532_IMP_9_25K	0x04
+#define LM3532_IMP_7_4K		0x05
+#define LM3532_IMP_6_17K	0x06
+#define LM3532_IMP_5_29K	0x07
+#define LM3532_IMP_4_63K	0x08
+#define LM3532_IMP_4_11K	0x09
+#define LM3532_IMP_3_7K		0x0a
+#define LM3532_IMP_3_36K	0x0b
+#define LM3532_IMP_3_08K	0x0c
+#define LM3532_IMP_2_85K	0x0d
+#define LM3532_IMP_2_64K	0x0e
+#define LM3532_IMP_2_44K	0x0f
+#define LM3532_IMP_2_31K	0x10
+#define LM3532_IMP_2_18K	0x11
+#define LM3532_IMP_2_06K	0x12
+#define LM3532_IMP_1_95K	0x13
+#define LM3532_IMP_1_85K	0x14
+#define LM3532_IMP_1_76K	0x15
+#define LM3532_IMP_1_68K	0x16
+#define LM3532_IMP_1_61K	0x17
+#define LM3532_IMP_1_54K	0x18
+#define LM3532_IMP_1_48K	0x19
+#define LM3532_IMP_1_42K	0x1a
+#define LM3532_IMP_1_37K	0x1b
+#define LM3532_IMP_1_32K	0x1c
+#define LM3532_IMP_1_28K	0x1d
+#define LM3532_IMP_1_23K	0x1e
+#define LM3532_IMP_1_19K	0x1f
+
+/* ALS Averaging Time */
+#define LM3532_ALS_AVRG_TIME_17_92ms	0x00
+#define LM3532_ALS_AVRG_TIME_35_84ms	0x01
+#define LM3532_ALS_AVRG_TIME_71_68ms	0x02
+#define LM3532_ALS_AVRG_TIME_143_36ms	0x03
+#define LM3532_ALS_AVRG_TIME_286_72ms	0x04
+#define LM3532_ALS_AVRG_TIME_573_44ms	0x05
+#define LM3532_ALS_AVRG_TIME_1146_88ms	0x06
+#define LM3532_ALS_AVRG_TIME_2293_76ms	0x07
+
+/* ALS input select */
+#define LM3532_ALS_INPUT_AVRG	0x00 /* ALS1 and ALS2 input average */
+#define LM3532_ALS_INPUT_ALS1	0x01 /* ALS1 Input */
+#define LM3532_ALS_INPUT_ALS2	0x02 /* ALS2 Input */
+#define LM3532_ALS_INPUT_CEIL	0x03 /* Max of ALS1 and ALS2 */
+
+/* Ramp Times */
+#define LM3532_RAMP_8us		0x00
+#define LM3532_RAMP_1024us	0x01
+#define LM3532_RAMP_2048us	0x02
+#define LM3532_RAMP_4096us	0x03
+#define LM3532_RAMP_8192us	0x04
+#define LM3532_RAMP_16384us	0x05
+#define LM3532_RAMP_32768us	0x06
+#define LM3532_RAMP_65536us	0x07
+
+#endif /* __DT_BINDINGS_LEDS_LM3532_H */
-- 
2.20.1.390.gb5101f9297

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

* [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver
@ 2019-03-07 22:09   ` Dan Murphy
  0 siblings, 0 replies; 51+ messages in thread
From: Dan Murphy @ 2019-03-07 22:09 UTC (permalink / raw)
  To: robh+dt, jacek.anaszewski, pavel, tony, lee.jones
  Cc: devicetree, linux-kernel, linux-leds, Dan Murphy

Introduce the Texas Instruments LM3532 White LED driver.
The driver supports ALS configurability or manual brightness
control.

The driver also supports associating LED strings with specific
control banks in a group or as individually controlled strings.

Signed-off-by: Dan Murphy <dmurphy@ti.com>
---
 drivers/leds/Kconfig                   |  10 +
 drivers/leds/Makefile                  |   1 +
 drivers/leds/leds-lm3532.c             | 595 +++++++++++++++++++++++++
 include/dt-bindings/leds/leds-lm3532.h |  72 +++
 4 files changed, 678 insertions(+)
 create mode 100644 drivers/leds/leds-lm3532.c
 create mode 100644 include/dt-bindings/leds/leds-lm3532.h

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a72f97fca57b..da00b9ed5a5c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -138,6 +138,16 @@ config LEDS_LM3530
 	  controlled manually or using PWM input or using ambient
 	  light automatically.
 
+config LEDS_LM3532
+	tristate "LCD Backlight driver for LM3532"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for the LCD backlight using
+	  LM3532 ambient light sensor chip. This ALS chip can be
+	  controlled manually or using PWM input or using ambient
+	  light automatically.
+
 config LEDS_LM3533
 	tristate "LED support for LM3533"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 4c1b0054f379..7a8b1f55d459 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_CPCAP)		+= leds-cpcap.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
+obj-$(CONFIG_LEDS_LM3532)		+= leds-lm3532.o
 obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
 obj-$(CONFIG_LEDS_LM3642)		+= leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
diff --git a/drivers/leds/leds-lm3532.c b/drivers/leds/leds-lm3532.c
new file mode 100644
index 000000000000..005478359d06
--- /dev/null
+++ b/drivers/leds/leds-lm3532.c
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: GPL-2.0
+// TI LM3532 LED driver
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <uapi/linux/uleds.h>
+#include <linux/gpio/consumer.h>
+
+#include <dt-bindings/leds/leds-lm3532.h>
+
+#define LM3532_NAME "lm3532-led"
+
+#define LM3532_REG_OUTPUT_CFG	0x10
+#define LM3532_REG_STARTSHUT_RAMP	0x11
+#define LM3532_REG_RT_RAMP	0x12
+#define LM3532_REG_PWM_A_CFG	0x13
+#define LM3532_REG_PWM_B_CFG	0x14
+#define LM3532_REG_PWM_C_CFG	0x15
+#define LM3532_REG_ZONE_CFG_A	0x16
+#define LM3532_REG_CTRL_A_BRT	0x17
+#define LM3532_REG_ZONE_CFG_B	0x18
+#define LM3532_REG_CTRL_B_BRT	0x19
+#define LM3532_REG_ZONE_CFG_C	0x1a
+#define LM3532_REG_CTRL_C_BRT	0x1b
+#define LM3532_REG_ENABLE	0x1d
+#define LM3532_ALS_CONFIG	0x23
+#define LM3532_REG_ZN_0_HI	0x60
+#define LM3532_REG_ZN_0_LO	0x61
+#define LM3532_REG_ZN_1_HI	0x62
+#define LM3532_REG_ZN_1_LO	0x63
+#define LM3532_REG_ZN_2_HI	0x64
+#define LM3532_REG_ZN_2_LO	0x65
+#define LM3532_REG_ZN_3_HI	0x66
+#define LM3532_REG_ZN_3_LO	0x67
+#define LM3532_REG_MAX		0x7e
+
+/* Contorl Enable */
+#define LM3532_CTRL_A_ENABLE	BIT(0)
+#define LM3532_CTRL_B_ENABLE	BIT(1)
+#define LM3532_CTRL_C_ENABLE	BIT(2)
+
+/* PWM Zone Control */
+#define LM3532_PWM_ZONE_MASK	0x7c
+#define LM3532_PWM_ZONE_0_EN	BIT(2)
+#define LM3532_PWM_ZONE_1_EN	BIT(3)
+#define LM3532_PWM_ZONE_2_EN	BIT(4)
+#define LM3532_PWM_ZONE_3_EN	BIT(5)
+#define LM3532_PWM_ZONE_4_EN	BIT(6)
+
+/* Brightness Configuration */
+#define LM3532_I2C_CTRL		BIT(0)
+#define LM3532_LINEAR_MAP	BIT(1)
+#define LM3532_ZONE_MASK	(BIT(2) | BIT(3) | BIT(4))
+#define LM3532_ZONE_0		0
+#define LM3532_ZONE_1		BIT(2)
+#define LM3532_ZONE_2		BIT(3)
+#define LM3532_ZONE_3		(BIT(2) | BIT(3))
+#define LM3532_ZONE_4		BIT(4)
+
+#define LM3532_ENABLE_ALS	BIT(3)
+#define LM3532_ALS_SEL_SHIFT	6
+
+/* Zone Boundary Register */
+#define LM3532_ALS_WINDOW_mV	2000
+#define LM3532_ALS_ZB_MAX	4
+#define LM3532_ALS_OFFSET_mV	2
+
+#define LM3532_CONTROL_A	0
+#define LM3532_CONTROL_B	1
+#define LM3532_CONTROL_C	2
+#define LM3532_MAX_CONTROL_BANKS 3
+#define LM3532_MAX_LED_STRINGS	3
+
+#define LM3532_OUTPUT_CFG_MASK	0x3
+#define LM3532_BRT_VAL_ADJUST	8
+#define LM3532_RAMP_DOWN_SHIFT	3
+
+/*
+ * struct lm3532_als_data
+ * @config - value of ALS configuration register
+ * @als1_imp_sel - value of ALS1 resistor select register
+ * @als2_imp_sel - value of ALS2 resistor select register
+ * @als_avrg_time - ALS averaging time
+ * @als_input_mode - ALS input mode for brightness control
+ * @als_vmin - Minimum ALS voltage
+ * @als_vmax - Maximum ALS voltage
+ * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
+ * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
+ */
+struct lm3532_als_data {
+	u8 config;
+	u8 als1_imp_sel;
+	u8 als2_imp_sel;
+	u8 als_avrg_time;
+	u8 als_input_mode;
+	u32 als_vmin;
+	u32 als_vmax;
+	u8 zones_lo[LM3532_ALS_ZB_MAX];
+	u8 zones_hi[LM3532_ALS_ZB_MAX];
+};
+
+/**
+ * struct lm3532_led
+ * @led_dev: led class device
+ * @priv - Pointer the device data structure
+ * @control_bank - Control bank the LED is associated to
+ * @mode - Mode of the LED string
+ * @num_leds - Number of LED strings are supported in this array
+ * @led_strings - The LED strings supported in this array
+ * @label - LED label
+ */
+struct lm3532_led {
+	struct led_classdev led_dev;
+	struct lm3532_data *priv;
+
+	int control_bank;
+	int mode;
+	int num_leds;
+	u32 led_strings[LM3532_MAX_CONTROL_BANKS];
+	char label[LED_MAX_NAME_SIZE];
+};
+
+/**
+ * struct lm3532_data
+ * @enable_gpio - Hardware enable gpio
+ * @regulator: regulator
+ * @client: i2c client
+ * @regmap - Devices register map
+ * @dev - Pointer to the devices device struct
+ * @lock - Lock for reading/writing the device
+ * @als_data - Pointer to the als data struct
+ * @runtime_ramp_up - Runtime ramp up setting
+ * @runtime_ramp_down - Runtime ramp down setting
+ * @leds - Array of LED strings
+ */
+struct lm3532_data {
+	struct gpio_desc *enable_gpio;
+	struct regulator *regulator;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct device *dev;
+	struct mutex lock;
+
+	struct lm3532_als_data *als_data;
+
+	u32 runtime_ramp_up;
+	u32 runtime_ramp_down;
+
+	struct lm3532_led leds[];
+};
+
+static const struct reg_default lm3532_reg_defs[] = {
+	{LM3532_REG_OUTPUT_CFG, 0xe4},
+	{LM3532_REG_STARTSHUT_RAMP, 0xc0},
+	{LM3532_REG_RT_RAMP, 0xc0},
+	{LM3532_REG_PWM_A_CFG, 0x82},
+	{LM3532_REG_PWM_B_CFG, 0x82},
+	{LM3532_REG_PWM_C_CFG, 0x82},
+	{LM3532_REG_ZONE_CFG_A, 0xf1},
+	{LM3532_REG_CTRL_A_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_B, 0xf1},
+	{LM3532_REG_CTRL_B_BRT, 0xf3},
+	{LM3532_REG_ZONE_CFG_C, 0xf1},
+	{LM3532_REG_CTRL_C_BRT, 0xf3},
+	{LM3532_REG_ENABLE, 0xf8},
+	{LM3532_ALS_CONFIG, 0x44},
+	{LM3532_REG_ZN_0_HI, 0x35},
+	{LM3532_REG_ZN_0_LO, 0x33},
+	{LM3532_REG_ZN_1_HI, 0x6a},
+	{LM3532_REG_ZN_1_LO, 0x66},
+	{LM3532_REG_ZN_2_HI, 0xa1},
+	{LM3532_REG_ZN_2_LO, 0x99},
+	{LM3532_REG_ZN_3_HI, 0xdc},
+	{LM3532_REG_ZN_3_LO, 0xcc},
+};
+
+static const struct regmap_config lm3532_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = LM3532_REG_MAX,
+	.reg_defaults = lm3532_reg_defs,
+	.num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
+	.cache_type = REGCACHE_FLAT,
+};
+
+static int lm3532_led_enable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val;
+	int ret;
+
+	switch (led_data->control_bank) {
+	case LM3532_CONTROL_A:
+		ctrl_en_val = LM3532_CTRL_A_ENABLE;
+		break;
+	case LM3532_CONTROL_B:
+		ctrl_en_val = LM3532_CTRL_B_ENABLE;
+		break;
+	case LM3532_CONTROL_C:
+		ctrl_en_val = LM3532_CTRL_C_ENABLE;
+		break;
+	default:
+		dev_err(led_data->priv->dev, "Invalid control bank\n");
+		return -EINVAL;
+	};
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_enable(led_data->priv->regulator);
+}
+
+static int lm3532_led_disable(struct lm3532_led *led_data)
+{
+	int ctrl_en_val;
+	int ret;
+
+	switch (led_data->control_bank) {
+	case LM3532_CONTROL_A:
+		ctrl_en_val = LM3532_CTRL_A_ENABLE;
+		break;
+	case LM3532_CONTROL_B:
+		ctrl_en_val = LM3532_CTRL_B_ENABLE;
+		break;
+	case LM3532_CONTROL_C:
+		ctrl_en_val = LM3532_CTRL_C_ENABLE;
+		break;
+	default:
+		dev_err(led_data->priv->dev, "Invalid control bank\n");
+		return -EINVAL;
+	};
+
+	ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
+					 ctrl_en_val, ~ctrl_en_val);
+	if (ret) {
+		dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
+		return ret;
+	}
+
+	return regulator_disable(led_data->priv->regulator);
+}
+
+static int lm3532_brightness_set(struct led_classdev *led_cdev,
+				 enum led_brightness brt_val)
+{
+	struct lm3532_led *led =
+			container_of(led_cdev, struct lm3532_led, led_dev);
+	u8 brightnes_reg;
+	int ret;
+
+	mutex_lock(&led->priv->lock);
+
+	if (led->mode == LM3532_BL_MODE_ALS) {
+		ret = 0;
+		goto unlock;
+	}
+
+	switch (led->control_bank) {
+	case LM3532_CONTROL_A:
+		brightnes_reg = LM3532_REG_CTRL_A_BRT;
+		break;
+	case LM3532_CONTROL_B:
+		brightnes_reg = LM3532_REG_CTRL_B_BRT;
+		break;
+	case LM3532_CONTROL_C:
+		brightnes_reg = LM3532_REG_CTRL_C_BRT;
+		break;
+	default:
+		dev_err(led->priv->dev, "Invalid control bank\n");
+		ret = -EINVAL;
+		goto unlock;
+	};
+
+	if (brt_val == LED_OFF) {
+		ret = lm3532_led_disable(led);
+		goto unlock;
+	}
+
+	lm3532_led_enable(led);
+	brt_val = brt_val / LM3532_BRT_VAL_ADJUST;
+
+	ret = regmap_write(led->priv->regmap, brightnes_reg, brt_val);
+
+unlock:
+	mutex_unlock(&led->priv->lock);
+	return ret;
+}
+
+static int lm3532_init_registers(struct lm3532_led *led)
+{
+	struct lm3532_data *drvdata = led->priv;
+	unsigned int runtime_ramp_val;
+	unsigned int output_cfg_val = 0;
+	unsigned int output_cfg_shift = 0;
+	unsigned int output_cfg_mask = 0;
+	int ret, i;
+
+	for (i = 0; i < led->num_leds; i++) {
+		output_cfg_shift = led->led_strings[i] * 2;
+		output_cfg_val |= (led->control_bank << output_cfg_shift);
+		output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
+	}
+
+	ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
+				 output_cfg_mask, output_cfg_val);
+
+	runtime_ramp_val = drvdata->runtime_ramp_up |
+			 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
+
+	return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
+			    runtime_ramp_val);
+}
+
+static int lm3532_als_configure(struct lm3532_data *priv)
+{
+	struct lm3532_als_data *als = priv->als_data;
+	u32 als_vmin, als_vmax, als_vstep;
+	int zone_reg = LM3532_REG_ZN_0_HI;
+	int ret;
+	int i;
+
+	als_vmin = als->als_vmin;
+	als_vmax = als->als_vmax;
+
+	als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
+
+	for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
+		als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
+				LED_FULL) / 1000;
+		als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
+				als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
+
+		zone_reg = LM3532_REG_ZN_0_HI + i * 2;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
+		if (ret)
+			return ret;
+
+		zone_reg += 1;
+		ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
+		if (ret)
+			return ret;
+	}
+
+	als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
+		(als->als_input_mode << LM3532_ALS_SEL_SHIFT));
+
+	return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
+}
+
+static int lm3532_parse_als(struct lm3532_data *priv)
+{
+	struct lm3532_als_data *als;
+	int ret;
+
+	als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
+	if (als == NULL)
+		return -ENOMEM;
+
+	ret = device_property_read_u32(&priv->client->dev, "als-vmin",
+				       &als->als_vmin);
+	if (ret)
+		als->als_vmin = 0;
+
+	ret = device_property_read_u32(&priv->client->dev, "als-vmax",
+				       &als->als_vmax);
+	if (ret)
+		als->als_vmax = LM3532_ALS_WINDOW_mV;
+
+	ret = device_property_read_u8(&priv->client->dev, "als1-imp-sel",
+				      &als->als1_imp_sel);
+	if (ret)
+		als->als1_imp_sel = 0;
+
+	ret = device_property_read_u8(&priv->client->dev, "als2-imp-sel",
+				      &als->als2_imp_sel);
+	if (ret)
+		als->als2_imp_sel = 0;
+
+	ret = device_property_read_u8(&priv->client->dev, "als-avrg-time",
+				      &als->als_avrg_time);
+	if (ret)
+		als->als_avrg_time = 0;
+
+	ret = device_property_read_u8(&priv->client->dev, "als-input-mode",
+				      &als->als_input_mode);
+	if (ret)
+		als->als_input_mode = 0;
+
+	priv->als_data = als;
+
+	return ret;
+}
+
+static int lm3532_parse_node(struct lm3532_data *priv)
+{
+	struct fwnode_handle *child = NULL;
+	struct lm3532_led *led;
+	const char *name;
+	int control_bank;
+	size_t i = 0;
+	int ret;
+
+	priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
+						   "enable", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->enable_gpio))
+		priv->enable_gpio = NULL;
+
+	priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
+	if (IS_ERR(priv->regulator))
+		priv->regulator = NULL;
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
+				       &priv->runtime_ramp_up);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+
+	ret = device_property_read_u32(&priv->client->dev, "ramp-down-ms",
+				       &priv->runtime_ramp_down);
+	if (ret)
+		dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
+
+	device_for_each_child_node(priv->dev, child) {
+		led = &priv->leds[i];
+
+		ret = fwnode_property_read_u32(child, "reg", &control_bank);
+		if (ret) {
+			dev_err(&priv->client->dev, "reg property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (control_bank > LM3532_CONTROL_C) {
+			dev_err(&priv->client->dev, "Control bank invalid\n");
+			continue;
+		}
+
+		led->control_bank = control_bank;
+
+		ret = fwnode_property_read_u32(child, "ti,led-mode",
+					       &led->mode);
+		if (ret) {
+			dev_err(&priv->client->dev, "ti,led-mode property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		if (led->mode == LM3532_BL_MODE_ALS) {
+			ret = lm3532_parse_als(priv);
+			if (ret)
+				dev_err(&priv->client->dev, "Failed to parse als\n");
+			else
+				lm3532_als_configure(priv);
+		}
+
+		led->num_leds = fwnode_property_read_u32_array(child,
+							       "led-sources",
+							       NULL, 0);
+
+		if (led->num_leds > LM3532_MAX_LED_STRINGS) {
+			dev_err(&priv->client->dev, "To many LED string defined\n");
+			continue;
+		}
+
+		ret = fwnode_property_read_u32_array(child, "led-sources",
+						    led->led_strings,
+						    led->num_leds);
+		if (ret) {
+			dev_err(&priv->client->dev, "led-sources property missing\n");
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		fwnode_property_read_string(child, "linux,default-trigger",
+					    &led->led_dev.default_trigger);
+
+		ret = fwnode_property_read_string(child, "label", &name);
+		if (ret)
+			snprintf(led->label, sizeof(led->label),
+				"%s::", priv->client->name);
+		else
+			snprintf(led->label, sizeof(led->label),
+				 "%s:%s", priv->client->name, name);
+
+		led->priv = priv;
+		led->led_dev.name = led->label;
+		led->led_dev.brightness_set_blocking = lm3532_brightness_set;
+
+		ret = devm_led_classdev_register(priv->dev, &led->led_dev);
+		if (ret) {
+			dev_err(&priv->client->dev, "led register err: %d\n",
+				ret);
+			fwnode_handle_put(child);
+			goto child_out;
+		}
+
+		lm3532_init_registers(led);
+
+		i++;
+	}
+
+child_out:
+	return ret;
+}
+
+static int lm3532_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct lm3532_data *drvdata;
+	int ret = 0;
+	int count;
+
+	count = device_get_child_node_count(&client->dev);
+	if (!count) {
+		dev_err(&client->dev, "LEDs are not defined in device tree!");
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
+			   GFP_KERNEL);
+	if (drvdata == NULL)
+		return -ENOMEM;
+
+	drvdata->client = client;
+	drvdata->dev = &client->dev;
+
+	drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
+	if (IS_ERR(drvdata->regmap)) {
+		ret = PTR_ERR(drvdata->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	mutex_init(&drvdata->lock);
+	i2c_set_clientdata(client, drvdata);
+
+	ret = lm3532_parse_node(drvdata);
+	if (ret) {
+		dev_err(&client->dev, "Failed to parse node\n");
+		return ret;
+	}
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 1);
+
+	return ret;
+}
+
+static int lm3532_remove(struct i2c_client *client)
+{
+	struct lm3532_data *drvdata = i2c_get_clientdata(client);
+
+	if (drvdata->enable_gpio)
+		gpiod_direction_output(drvdata->enable_gpio, 0);
+
+	return 0;
+}
+
+static const struct of_device_id of_lm3532_leds_match[] = {
+	{ .compatible = "ti,lm3532", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
+
+static const struct i2c_device_id lm3532_id[] = {
+	{LM3532_NAME, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, lm3532_id);
+
+static struct i2c_driver lm3532_i2c_driver = {
+	.probe = lm3532_probe,
+	.remove = lm3532_remove,
+	.id_table = lm3532_id,
+	.driver = {
+		.name = LM3532_NAME,
+		.of_match_table = of_lm3532_leds_match,
+	},
+};
+module_i2c_driver(lm3532_i2c_driver);
+
+MODULE_DESCRIPTION("Back Light driver for LM3532");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
diff --git a/include/dt-bindings/leds/leds-lm3532.h b/include/dt-bindings/leds/leds-lm3532.h
new file mode 100644
index 000000000000..724dbc0cb395
--- /dev/null
+++ b/include/dt-bindings/leds/leds-lm3532.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* TI LM3532 LED driver
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#ifndef __DT_BINDINGS_LEDS_LM3532_H
+#define __DT_BINDINGS_LEDS_LM3532_H
+
+#define LM3532_BL_MODE_MANUAL	0x00 /* "man" */
+#define LM3532_BL_MODE_ALS	0x01 /* "als" */
+
+/* ALS Resistor Select */
+#define LM3532_IMP_HIGH		0x00
+#define LM3532_IMP_37K		0x01
+#define LM3532_IMP_18_5K	0x02
+#define LM3532_IMP_12_33K	0x03
+#define LM3532_IMP_9_25K	0x04
+#define LM3532_IMP_7_4K		0x05
+#define LM3532_IMP_6_17K	0x06
+#define LM3532_IMP_5_29K	0x07
+#define LM3532_IMP_4_63K	0x08
+#define LM3532_IMP_4_11K	0x09
+#define LM3532_IMP_3_7K		0x0a
+#define LM3532_IMP_3_36K	0x0b
+#define LM3532_IMP_3_08K	0x0c
+#define LM3532_IMP_2_85K	0x0d
+#define LM3532_IMP_2_64K	0x0e
+#define LM3532_IMP_2_44K	0x0f
+#define LM3532_IMP_2_31K	0x10
+#define LM3532_IMP_2_18K	0x11
+#define LM3532_IMP_2_06K	0x12
+#define LM3532_IMP_1_95K	0x13
+#define LM3532_IMP_1_85K	0x14
+#define LM3532_IMP_1_76K	0x15
+#define LM3532_IMP_1_68K	0x16
+#define LM3532_IMP_1_61K	0x17
+#define LM3532_IMP_1_54K	0x18
+#define LM3532_IMP_1_48K	0x19
+#define LM3532_IMP_1_42K	0x1a
+#define LM3532_IMP_1_37K	0x1b
+#define LM3532_IMP_1_32K	0x1c
+#define LM3532_IMP_1_28K	0x1d
+#define LM3532_IMP_1_23K	0x1e
+#define LM3532_IMP_1_19K	0x1f
+
+/* ALS Averaging Time */
+#define LM3532_ALS_AVRG_TIME_17_92ms	0x00
+#define LM3532_ALS_AVRG_TIME_35_84ms	0x01
+#define LM3532_ALS_AVRG_TIME_71_68ms	0x02
+#define LM3532_ALS_AVRG_TIME_143_36ms	0x03
+#define LM3532_ALS_AVRG_TIME_286_72ms	0x04
+#define LM3532_ALS_AVRG_TIME_573_44ms	0x05
+#define LM3532_ALS_AVRG_TIME_1146_88ms	0x06
+#define LM3532_ALS_AVRG_TIME_2293_76ms	0x07
+
+/* ALS input select */
+#define LM3532_ALS_INPUT_AVRG	0x00 /* ALS1 and ALS2 input average */
+#define LM3532_ALS_INPUT_ALS1	0x01 /* ALS1 Input */
+#define LM3532_ALS_INPUT_ALS2	0x02 /* ALS2 Input */
+#define LM3532_ALS_INPUT_CEIL	0x03 /* Max of ALS1 and ALS2 */
+
+/* Ramp Times */
+#define LM3532_RAMP_8us		0x00
+#define LM3532_RAMP_1024us	0x01
+#define LM3532_RAMP_2048us	0x02
+#define LM3532_RAMP_4096us	0x03
+#define LM3532_RAMP_8192us	0x04
+#define LM3532_RAMP_16384us	0x05
+#define LM3532_RAMP_32768us	0x06
+#define LM3532_RAMP_65536us	0x07
+
+#endif /* __DT_BINDINGS_LEDS_LM3532_H */
-- 
2.20.1.390.gb5101f9297


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

end of thread, other threads:[~2019-04-07 19:11 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-21 14:28 [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc Dan Murphy
2019-03-21 14:28 ` Dan Murphy
2019-03-21 14:28 ` [PATCH 2/4] ARM: dts: omap4-droid4: Update backlight dt properties Dan Murphy
2019-03-21 14:28   ` Dan Murphy
2019-04-04  0:03   ` Tony Lindgren
2019-04-04 20:12   ` Jacek Anaszewski
2019-04-04 22:00     ` Tony Lindgren
2019-04-07 18:31       ` Jacek Anaszewski
2019-03-21 14:28 ` [PATCH 3/4] mfd: ti-lmu: Remove LM3532 backlight driver references Dan Murphy
2019-03-21 14:28   ` Dan Murphy
2019-03-23 16:47   ` Jacek Anaszewski
2019-03-25  7:53     ` Lee Jones
2019-03-25 21:11       ` Jacek Anaszewski
2019-04-03  7:57         ` Lee Jones
2019-04-03 17:45           ` Jacek Anaszewski
2019-04-04  2:44             ` Lee Jones
2019-04-04  0:04   ` Tony Lindgren
2019-03-21 14:28 ` [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver Dan Murphy
2019-03-21 14:28   ` Dan Murphy
2019-03-22 22:16   ` Tony Lindgren
2019-03-25 12:35     ` Dan Murphy
2019-03-25 12:35       ` Dan Murphy
2019-03-25 14:54       ` Tony Lindgren
2019-03-25 16:01         ` Dan Murphy
2019-03-25 16:01           ` Dan Murphy
2019-03-28 21:04           ` Sebastian Reichel
2019-04-03 20:06             ` Tony Lindgren
2019-04-03 23:55               ` Tony Lindgren
2019-04-04  0:09   ` Tony Lindgren
2019-04-04 18:48     ` Jacek Anaszewski
2019-04-04 19:23       ` Dan Murphy
2019-04-04 19:23         ` Dan Murphy
2019-03-21 14:30 ` [PATCH 1/4] dt: lm3532: Add lm3532 dt doc and update ti_lmu doc Dan Murphy
2019-03-21 14:30   ` Dan Murphy
2019-03-25  7:54 ` Lee Jones
2019-04-04  0:04 ` Tony Lindgren
2019-04-07 19:11 ` Jacek Anaszewski
  -- strict thread matches above, loose matches on Subject: below --
2019-03-07 22:09 Dan Murphy
2019-03-07 22:09 ` [PATCH 4/4] leds: lm3532: Introduce the lm3532 LED driver Dan Murphy
2019-03-07 22:09   ` Dan Murphy
2019-03-08 13:28   ` Dan Murphy
2019-03-08 13:28     ` Dan Murphy
2019-03-10 19:49   ` Jacek Anaszewski
2019-03-11 11:36     ` Dan Murphy
2019-03-11 11:36       ` Dan Murphy
2019-03-11 17:22       ` Jacek Anaszewski
2019-03-11 17:24         ` Dan Murphy
2019-03-11 17:24           ` Dan Murphy
2019-03-11 17:30           ` Joe Perches
2019-03-11 17:47             ` Dan Murphy
2019-03-11 17:47               ` Dan Murphy
2019-03-13 15:49               ` Joe Perches

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.