Commit 8a3367cc authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'leds-for-5.3-rc1' of...

Merge tag 'leds-for-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds

Pull LED updates from Jacek Anaszewski:

 - Add a new LED common module for ti-lmu driver family

 - Modify MFD ti-lmu bindings
        - add ti,brightness-resolution
        - add the ramp up/down property

 - Add regulator support for LM36274 driver to lm363x-regulator.c

 - New LED class drivers with DT bindings:
        - leds-spi-byte
        - leds-lm36274
        - leds-lm3697 (move the support from MFD to LED subsystem)

 - Simplify getting the I2C adapter of a client:
        - leds-tca6507
        - leds-pca955x

 - Convert LED documentation to ReST

* tag 'leds-for-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
  dt: leds-lm36274.txt: fix a broken reference to ti-lmu.txt
  docs: leds: convert to ReST
  leds: leds-tca6507: simplify getting the adapter of a client
  leds: leds-pca955x: simplify getting the adapter of a client
  leds: lm36274: Introduce the TI LM36274 LED driver
  dt-bindings: leds: Add LED bindings for the LM36274
  regulator: lm363x: Add support for LM36274
  mfd: ti-lmu: Add LM36274 support to the ti-lmu
  dt-bindings: mfd: Add lm36274 bindings to ti-lmu
  leds: max77650: Remove set but not used variable 'parent'
  leds: avoid flush_work in atomic context
  leds: lm3697: Introduce the lm3697 driver
  mfd: ti-lmu: Remove support for LM3697
  dt-bindings: ti-lmu: Modify dt bindings for the LM3697
  leds: TI LMU: Add common code for TI LMU devices
  leds: spi-byte: add single byte SPI LED driver
  dt-bindings: leds: Add binding for spi-byte LED.
  dt-bindings: mfd: LMU: Add ti,brightness-resolution
  dt-bindings: mfd: LMU: Add the ramp up/down property
parents 6e2bbb68 2605085f
* Texas Instruments LM36274 4-Channel LCD Backlight Driver w/Integrated Bias
The LM36274 is an integrated four-channel WLED driver and LCD bias supply.
The backlight boost provides the power to bias four parallel LED strings with
up to 29V total output voltage. The 11-bit LED current is programmable via
the I2C bus and/or controlled via a logic level PWM input from 60 uA to 30 mA.
Parent device properties are documented in
Documentation/devicetree/bindings/mfd/ti-lmu.txt
Regulator properties are documented in
Documentation/devicetree/bindings/regulator/lm363x-regulator.txt
Required backlight properties:
- compatible:
"ti,lm36274-backlight"
- reg : 0
- #address-cells : 1
- #size-cells : 0
- led-sources : Indicates which LED strings will be enabled.
Values from 0-3, sources is 0 based so strings will be
source value + 1.
Optional backlight properties:
- label : see Documentation/devicetree/bindings/leds/common.txt
- linux,default-trigger :
see Documentation/devicetree/bindings/leds/common.txt
Example:
HVLED string 1 and 3 are controlled by control bank A and HVLED 2 string is
controlled by control bank B.
lm36274@11 {
compatible = "ti,lm36274";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11>;
enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
regulators {
#address-cells = <1>;
#size-cells = <0>;
compatible = "ti,lm363x-regulator";
enable-gpios = <&pioC 0 GPIO_ACTIVE_HIGH>,
<&pioC 1 GPIO_ACTIVE_HIGH>;
vboost {
regulator-name = "lcd_boost";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <7150000>;
regulator-always-on;
};
vpos {
regulator-name = "lcd_vpos";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <6500000>;
};
vneg {
regulator-name = "lcd_vneg";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <6500000>;
};
};
backlight {
#address-cells = <1>;
#size-cells = <0>;
compatible = "ti,lm36274-backlight";
led@0 {
reg = <0>;
led-sources = <0 2>;
label = "white:backlight_cluster";
linux,default-trigger = "backlight";
};
};
};
For more product information please see the link below:
http://www.ti.com/lit/ds/symlink/lm36274.pdf
* Texas Instruments - LM3697 Highly Efficient White LED Driver
The LM3697 11-bit LED driver provides high-
performance backlight dimming for 1, 2, or 3 series
LED strings while delivering up to 90% efficiency.
This device is suitable for display and keypad lighting
Required properties:
- compatible:
"ti,lm3697"
- reg : I2C slave address
- #address-cells : 1
- #size-cells : 0
Optional properties:
- enable-gpios : GPIO pin to enable/disable the device
- vled-supply : LED supply
Required child properties:
- reg : 0 - LED is Controlled by bank A
1 - LED is Controlled by bank B
- led-sources : Indicates which HVLED string is associated to which
control bank. This is a zero based property so
HVLED1 = 0, HVLED2 = 1, HVLED3 = 2.
Additional information is contained
in Documentation/devicetree/bindings/leds/common.txt
Optional child properties:
- ti,brightness-resolution - see Documentation/devicetree/bindings/mfd/ti-lmu.txt
- ramp-up-us: see Documentation/devicetree/bindings/mfd/ti-lmu.txt
- ramp-down-us: see Documentation/devicetree/bindings/mfd/ti-lmu.txt
- label : see Documentation/devicetree/bindings/leds/common.txt
- linux,default-trigger :
see Documentation/devicetree/bindings/leds/common.txt
Example:
HVLED string 1 and 3 are controlled by control bank A and HVLED 2 string is
controlled by control bank B.
led-controller@36 {
compatible = "ti,lm3697";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x36>;
enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
vled-supply = <&vbatt>;
led@0 {
reg = <0>;
led-sources = <0 2>;
ti,brightness-resolution = <2047>;
ramp-up-us = <5000>;
ramp-down-us = <1000>;
label = "white:first_backlight_cluster";
linux,default-trigger = "backlight";
};
led@1 {
reg = <1>;
led-sources = <1>;
ti,brightness-resolution = <255>;
ramp-up-us = <500>;
ramp-down-us = <1000>;
label = "white:second_backlight_cluster";
linux,default-trigger = "backlight";
};
}
For more product information please see the link below:
http://www.ti.com/lit/ds/symlink/lm3697.pdf
* Single Byte SPI LED Device Driver.
The driver can be used for controllers with a very simple SPI protocol:
- one LED is controlled by a single byte on MOSI
- the value of the byte gives the brightness between two values (lowest to
highest)
- no return value is necessary (no MISO signal)
The value for lowest and highest brightness is dependent on the device and
therefore on the compatible string.
Depending on the compatible string some special functions (like hardware
accelerated blinking) might can be supported too.
The driver currently only supports one LED. The properties of the LED are
configured in a sub-node in the device node.
Required properties:
- compatible: should be one of
* "ubnt,acb-spi-led" microcontroller (SONiX 8F26E611LA) based device
used for example in Ubiquiti airCube ISP
Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
apply.
LED sub-node properties:
- label:
see Documentation/devicetree/bindings/leds/common.txt
- default-state:
see Documentation/devicetree/bindings/leds/common.txt
Only "on" and "off" are supported.
Example:
led-controller@0 {
compatible = "ubnt,acb-spi-led";
reg = <0>;
spi-max-frequency = <100000>;
led {
label = "white:status";
default-state = "on";
};
};
...@@ -8,7 +8,7 @@ TI LMU driver supports lighting devices below. ...@@ -8,7 +8,7 @@ TI LMU driver supports lighting devices below.
LM3632 Backlight and regulator LM3632 Backlight and regulator
LM3633 Backlight, LED and fault monitor LM3633 Backlight, LED and fault monitor
LM3695 Backlight LM3695 Backlight
LM3697 Backlight and fault monitor LM36274 Backlight and regulator
Required properties: Required properties:
- compatible: Should be one of: - compatible: Should be one of:
...@@ -16,15 +16,32 @@ Required properties: ...@@ -16,15 +16,32 @@ Required properties:
"ti,lm3632" "ti,lm3632"
"ti,lm3633" "ti,lm3633"
"ti,lm3695" "ti,lm3695"
"ti,lm3697" "ti,lm36274"
- reg: I2C slave address. - reg: I2C slave address.
0x11 for LM3632 0x11 for LM3632
0x29 for LM3631 0x29 for LM3631
0x36 for LM3633, LM3697 0x36 for LM3633
0x63 for LM3695 0x63 for LM3695
0x11 for LM36274
Optional property: Optional properties:
- enable-gpios: A GPIO specifier for hardware enable pin. - enable-gpios: A GPIO specifier for hardware enable pin.
- ramp-up-us: Current ramping from one brightness level to
the a higher brightness level.
Range from 2048 us - 117.44 s
- ramp-down-us: Current ramping from one brightness level to
the a lower brightness level.
Range from 2048 us - 117.44 s
- ti,brightness-resolution - This determines whether to use 8 bit brightness
mode or 11 bit brightness mode. If this value is
not set the device is defaulted to the preferred
8bit brightness mode per 7.3.4.1 of the data
sheet. This setting can either be in the parent
node or as part of the LED child nodes. This
is determined by the part itself if the strings
have a common brightness register or individual
brightness registers.
The values are 255 (8bit) or 2047 (11bit).
Required node: Required node:
- backlight: All LMU devices have backlight child nodes. - backlight: All LMU devices have backlight child nodes.
...@@ -35,14 +52,15 @@ Optional nodes: ...@@ -35,14 +52,15 @@ Optional nodes:
Required properties: Required properties:
- compatible: Should be one of: - compatible: Should be one of:
"ti,lm3633-fault-monitor" "ti,lm3633-fault-monitor"
"ti,lm3697-fault-monitor"
- leds: LED properties for LM3633. Please refer to [2]. - leds: LED properties for LM3633. Please refer to [2].
LED properties for LM36274. Please refer to [4].
- regulators: Regulator properties for LM3631 and LM3632. - regulators: Regulator properties for LM3631 and LM3632.
Please refer to [3]. Please refer to [3].
[1] ../leds/backlight/ti-lmu-backlight.txt [1] ../leds/backlight/ti-lmu-backlight.txt
[2] ../leds/leds-lm3633.txt [2] ../leds/leds-lm3633.txt
[3] ../regulator/lm363x-regulator.txt [3] ../regulator/lm363x-regulator.txt
[4] ../leds/leds-lm36274.txt
lm3631@29 { lm3631@29 {
compatible = "ti,lm3631"; compatible = "ti,lm3631";
...@@ -90,7 +108,7 @@ lm3631@29 { ...@@ -90,7 +108,7 @@ lm3631@29 {
lcd_bl { lcd_bl {
led-sources = <0 1>; led-sources = <0 1>;
ramp-up-msec = <300>; ramp-up-us = <300000>;
}; };
}; };
}; };
...@@ -152,15 +170,15 @@ lm3633@36 { ...@@ -152,15 +170,15 @@ lm3633@36 {
main { main {
label = "main_lcd"; label = "main_lcd";
led-sources = <1 2>; led-sources = <1 2>;
ramp-up-msec = <500>; ramp-up-us = <500000>;
ramp-down-msec = <500>; ramp-down-us = <500000>;
}; };
front { front {
label = "front_lcd"; label = "front_lcd";
led-sources = <0>; led-sources = <0>;
ramp-up-msec = <1000>; ramp-up-us = <1000000>;
ramp-down-msec = <0>; ramp-down-us = <0>;
}; };
}; };
...@@ -201,23 +219,51 @@ lm3695@63 { ...@@ -201,23 +219,51 @@ lm3695@63 {
}; };
}; };
lm3697@36 { lm36274@11 {
compatible = "ti,lm3697"; compatible = "ti,lm36274";
reg = <0x36>; #address-cells = <1>;
#size-cells = <0>;
reg = <0x11>;
enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>; enable-gpios = <&pioC 2 GPIO_ACTIVE_HIGH>;
regulators {
#address-cells = <1>;
#size-cells = <0>;
compatible = "ti,lm363x-regulator";
backlight { enable-gpios = <&pioC 0 GPIO_ACTIVE_HIGH>,
compatible = "ti,lm3697-backlight"; <&pioC 1 GPIO_ACTIVE_HIGH>;
lcd { vboost {
led-sources = <0 1 2>; regulator-name = "lcd_boost";
ramp-up-msec = <200>; regulator-min-microvolt = <4000000>;
ramp-down-msec = <200>; regulator-max-microvolt = <7150000>;
regulator-always-on;
}; };
vpos {
regulator-name = "lcd_vpos";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <6500000>;
}; };
fault-monitor { vneg {
compatible = "ti,lm3697-fault-monitor"; regulator-name = "lcd_vneg";
regulator-min-microvolt = <4000000>;
regulator-max-microvolt = <6500000>;
};
};
backlight {
#address-cells = <1>;
#size-cells = <0>;
compatible = "ti,lm36274-backlight";
led@0 {
reg = <0>;
led-sources = <0 2>;
label = "white:backlight_cluster";
linux,default-trigger = "backlight";
};
}; };
}; };
...@@ -679,7 +679,7 @@ status as "unknown". The available commands are: ...@@ -679,7 +679,7 @@ status as "unknown". The available commands are:
sysfs notes: sysfs notes:
The ThinkLight sysfs interface is documented by the LED class The ThinkLight sysfs interface is documented by the LED class
documentation, in Documentation/leds/leds-class.txt. The ThinkLight LED name documentation, in Documentation/leds/leds-class.rst. The ThinkLight LED name
is "tpacpi::thinklight". is "tpacpi::thinklight".
Due to limitations in the sysfs LED class, if the status of the ThinkLight Due to limitations in the sysfs LED class, if the status of the ThinkLight
...@@ -779,7 +779,7 @@ All of the above can be turned on and off and can be made to blink. ...@@ -779,7 +779,7 @@ All of the above can be turned on and off and can be made to blink.
sysfs notes: sysfs notes:
The ThinkPad LED sysfs interface is described in detail by the LED class The ThinkPad LED sysfs interface is described in detail by the LED class
documentation, in Documentation/leds/leds-class.txt. documentation, in Documentation/leds/leds-class.rst.
The LEDs are named (in LED ID order, from 0 to 12): The LEDs are named (in LED ID order, from 0 to 12):
"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", "tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt",
......
:orphan:
====
LEDs
====
.. toctree::
:maxdepth: 1
leds-class
leds-class-flash
ledtrig-oneshot
ledtrig-transient
ledtrig-usbport
uleds
leds-blinkm
leds-lm3556
leds-lp3944
leds-lp5521
leds-lp5523
leds-lp5562
leds-lp55xx
leds-mlxcpld
==================
Leds BlinkM driver
==================
The leds-blinkm driver supports the devices of the BlinkM family. The leds-blinkm driver supports the devices of the BlinkM family.
They are RGB-LED modules driven by a (AT)tiny microcontroller and They are RGB-LED modules driven by a (AT)tiny microcontroller and
...@@ -14,35 +18,36 @@ The interface this driver provides is 2-fold: ...@@ -14,35 +18,36 @@ The interface this driver provides is 2-fold:
a) LED class interface for use with triggers a) LED class interface for use with triggers
############################################ ############################################
The registration follows the scheme: The registration follows the scheme::
blinkm-<i2c-bus-nr>-<i2c-device-nr>-<color>
blinkm-<i2c-bus-nr>-<i2c-device-nr>-<color>
$ ls -h /sys/class/leds/blinkm-6-* $ ls -h /sys/class/leds/blinkm-6-*
/sys/class/leds/blinkm-6-9-blue: /sys/class/leds/blinkm-6-9-blue:
brightness device max_brightness power subsystem trigger uevent brightness device max_brightness power subsystem trigger uevent
/sys/class/leds/blinkm-6-9-green: /sys/class/leds/blinkm-6-9-green:
brightness device max_brightness power subsystem trigger uevent brightness device max_brightness power subsystem trigger uevent
/sys/class/leds/blinkm-6-9-red: /sys/class/leds/blinkm-6-9-red:
brightness device max_brightness power subsystem trigger uevent brightness device max_brightness power subsystem trigger uevent
(same is /sys/bus/i2c/devices/6-0009/leds) (same is /sys/bus/i2c/devices/6-0009/leds)
We can control the colors separated into red, green and blue and We can control the colors separated into red, green and blue and
assign triggers on each color. assign triggers on each color.
E.g.: E.g.::
$ cat blinkm-6-9-blue/brightness $ cat blinkm-6-9-blue/brightness
05 05
$ echo 200 > blinkm-6-9-blue/brightness $ echo 200 > blinkm-6-9-blue/brightness
$ $
$ modprobe ledtrig-heartbeat $ modprobe ledtrig-heartbeat
$ echo heartbeat > blinkm-6-9-green/trigger $ echo heartbeat > blinkm-6-9-green/trigger
$ $
b) Sysfs group to control rgb, fade, hsb, scripts ... b) Sysfs group to control rgb, fade, hsb, scripts ...
...@@ -52,29 +57,28 @@ This extended interface is available as folder blinkm ...@@ -52,29 +57,28 @@ This extended interface is available as folder blinkm
in the sysfs folder of the I2C device. in the sysfs folder of the I2C device.
E.g. below /sys/bus/i2c/devices/6-0009/blinkm E.g. below /sys/bus/i2c/devices/6-0009/blinkm
$ ls -h /sys/bus/i2c/devices/6-0009/blinkm/ $ ls -h /sys/bus/i2c/devices/6-0009/blinkm/
blue green red test blue green red test
Currently supported is just setting red, green, blue Currently supported is just setting red, green, blue
and a test sequence. and a test sequence.
E.g.: E.g.::
$ cat * $ cat *
00 00
00 00
00 00
#Write into test to start test sequence!# #Write into test to start test sequence!#
$ echo 1 > test $ echo 1 > test
$ $
$ echo 255 > red $ echo 255 > red
$ $
as of 6/2012 as of 6/2012
dl9pf <at> gmx <dot> de dl9pf <at> gmx <dot> de
==============================
Flash LED handling under Linux Flash LED handling under Linux
============================== ==============================
Some LED devices provide two modes - torch and flash. In the LED subsystem Some LED devices provide two modes - torch and flash. In the LED subsystem
those modes are supported by LED class (see Documentation/leds/leds-class.txt) those modes are supported by LED class (see Documentation/leds/leds-class.rst)
and LED Flash class respectively. The torch mode related features are enabled and LED Flash class respectively. The torch mode related features are enabled
by default and the flash ones only if a driver declares it by setting by default and the flash ones only if a driver declares it by setting
LED_DEV_CAP_FLASH flag. LED_DEV_CAP_FLASH flag.
...@@ -14,6 +14,7 @@ registered in the LED subsystem with led_classdev_flash_register function. ...@@ -14,6 +14,7 @@ registered in the LED subsystem with led_classdev_flash_register function.
Following sysfs attributes are exposed for controlling flash LED devices: Following sysfs attributes are exposed for controlling flash LED devices:
(see Documentation/ABI/testing/sysfs-class-led-flash) (see Documentation/ABI/testing/sysfs-class-led-flash)
- flash_brightness - flash_brightness
- max_flash_brightness - max_flash_brightness
- flash_timeout - flash_timeout
...@@ -31,30 +32,46 @@ be defined in the kernel config. ...@@ -31,30 +32,46 @@ be defined in the kernel config.
The driver must call the v4l2_flash_init function to get registered in the The driver must call the v4l2_flash_init function to get registered in the
V4L2 subsystem. The function takes six arguments: V4L2 subsystem. The function takes six arguments:
- dev : flash device, e.g. an I2C device
- of_node : of_node of the LED, may be NULL if the same as device's - dev:
- fled_cdev : LED flash class device to wrap flash device, e.g. an I2C device
- iled_cdev : LED flash class device representing indicator LED associated with - of_node:
of_node of the LED, may be NULL if the same as device's
- fled_cdev:
LED flash class device to wrap
- iled_cdev:
LED flash class device representing indicator LED associated with
fled_cdev, may be NULL fled_cdev, may be NULL
- ops : V4L2 specific ops - ops:
* external_strobe_set - defines the source of the flash LED strobe - V4L2 specific ops
* external_strobe_set
defines the source of the flash LED strobe -
V4L2_CID_FLASH_STROBE control or external source, typically V4L2_CID_FLASH_STROBE control or external source, typically
a sensor, which makes it possible to synchronise the flash a sensor, which makes it possible to synchronise the flash
strobe start with exposure start, strobe start with exposure start,
* intensity_to_led_brightness and led_brightness_to_intensity - perform * intensity_to_led_brightness and led_brightness_to_intensity
perform
enum led_brightness <-> V4L2 intensity conversion in a device enum led_brightness <-> V4L2 intensity conversion in a device
specific manner - they can be used for devices with non-linear specific manner - they can be used for devices with non-linear
LED current scale. LED current scale.
- config : configuration for V4L2 Flash sub-device - config:
* dev_name - the name of the media entity, unique in the system, configuration for V4L2 Flash sub-device
* flash_faults - bitmask of flash faults that the LED flash class
* dev_name
the name of the media entity, unique in the system,
* flash_faults
bitmask of flash faults that the LED flash class
device can report; corresponding LED_FAULT* bit definitions are device can report; corresponding LED_FAULT* bit definitions are
available in <linux/led-class-flash.h>, available in <linux/led-class-flash.h>,
* torch_intensity - constraints for the LED in TORCH mode * torch_intensity
constraints for the LED in TORCH mode
in microamperes, in microamperes,
* indicator_intensity - constraints for the indicator LED * indicator_intensity
constraints for the indicator LED
in microamperes, in microamperes,
* has_external_strobe - determines whether the flash strobe source * has_external_strobe
determines whether the flash strobe source
can be switched to external, can be switched to external,
On remove the v4l2_flash_release function has to be called, which takes one On remove the v4l2_flash_release function has to be called, which takes one
......
========================
LED handling under Linux LED handling under Linux
======================== ========================
...@@ -43,7 +43,7 @@ LED Device Naming ...@@ -43,7 +43,7 @@ LED Device Naming
Is currently of the form: Is currently of the form:
"devicename:colour:function" "devicename:colour:function"
There have been calls for LED properties such as colour to be exported as There have been calls for LED properties such as colour to be exported as
individual led class attributes. As a solution which doesn't incur as much individual led class attributes. As a solution which doesn't incur as much
...@@ -57,9 +57,12 @@ Brightness setting API ...@@ -57,9 +57,12 @@ Brightness setting API
LED subsystem core exposes following API for setting brightness: LED subsystem core exposes following API for setting brightness:
- led_set_brightness : it is guaranteed not to sleep, passing LED_OFF stops - led_set_brightness:
it is guaranteed not to sleep, passing LED_OFF stops
blinking, blinking,
- led_set_brightness_sync : for use cases when immediate effect is desired -
- led_set_brightness_sync:
for use cases when immediate effect is desired -
it can block the caller for the time required for accessing it can block the caller for the time required for accessing
device registers and can sleep, passing LED_OFF stops hardware device registers and can sleep, passing LED_OFF stops hardware
blinking, returns -EBUSY if software blink fallback is enabled. blinking, returns -EBUSY if software blink fallback is enabled.
...@@ -70,7 +73,7 @@ LED registration API ...@@ -70,7 +73,7 @@ LED registration API
A driver wanting to register a LED classdev for use by other drivers / A driver wanting to register a LED classdev for use by other drivers /
userspace needs to allocate and fill a led_classdev struct and then call userspace needs to allocate and fill a led_classdev struct and then call
[devm_]led_classdev_register. If the non devm version is used the driver `[devm_]led_classdev_register`. If the non devm version is used the driver
must call led_classdev_unregister from its remove function before must call led_classdev_unregister from its remove function before
free-ing the led_classdev struct. free-ing the led_classdev struct.
...@@ -94,7 +97,7 @@ with brightness value LED_OFF, which should stop any software ...@@ -94,7 +97,7 @@ with brightness value LED_OFF, which should stop any software
timers that may have been required for blinking. timers that may have been required for blinking.
The blink_set() function should choose a user friendly blinking value The blink_set() function should choose a user friendly blinking value
if it is called with *delay_on==0 && *delay_off==0 parameters. In this if it is called with `*delay_on==0` && `*delay_off==0` parameters. In this
case the driver should give back the chosen value through delay_on and case the driver should give back the chosen value through delay_on and
delay_off parameters to the leds subsystem. delay_off parameters to the leds subsystem.
......
========================
Kernel driver for lm3556 Kernel driver for lm3556
======================== ========================
*Texas Instrument: * Texas Instrument:
1.5 A Synchronous Boost LED Flash Driver w/ High-Side Current Source 1.5 A Synchronous Boost LED Flash Driver w/ High-Side Current Source
* Datasheet: http://www.national.com/ds/LM/LM3556.pdf * Datasheet: http://www.national.com/ds/LM/LM3556.pdf
Authors: Authors:
Daniel Jeong - Daniel Jeong
Contact:Daniel Jeong(daniel.jeong-at-ti.com, gshark.jeong-at-gmail.com) Contact:Daniel Jeong(daniel.jeong-at-ti.com, gshark.jeong-at-gmail.com)
Description Description
----------- -----------
There are 3 functions in LM3556, Flash, Torch and Indicator. There are 3 functions in LM3556, Flash, Torch and Indicator.
FLASH MODE Flash Mode
^^^^^^^^^^
In Flash Mode, the LED current source(LED) provides 16 target current levels In Flash Mode, the LED current source(LED) provides 16 target current levels
from 93.75 mA to 1500 mA.The Flash currents are adjusted via the CURRENT from 93.75 mA to 1500 mA.The Flash currents are adjusted via the CURRENT
CONTROL REGISTER(0x09).Flash mode is activated by the ENABLE REGISTER(0x0A), CONTROL REGISTER(0x09).Flash mode is activated by the ENABLE REGISTER(0x0A),
or by pulling the STROBE pin HIGH. or by pulling the STROBE pin HIGH.
LM3556 Flash can be controlled through sys/class/leds/flash/brightness file LM3556 Flash can be controlled through sys/class/leds/flash/brightness file
* if STROBE pin is enabled, below example control brightness only, and * if STROBE pin is enabled, below example control brightness only, and
ON / OFF will be controlled by STROBE pin. ON / OFF will be controlled by STROBE pin.
Flash Example: Flash Example:
OFF : #echo 0 > sys/class/leds/flash/brightness
93.75 mA: #echo 1 > sys/class/leds/flash/brightness
... .....
1500 mA: #echo 16 > sys/class/leds/flash/brightness
TORCH MODE OFF::
#echo 0 > sys/class/leds/flash/brightness
93.75 mA::
#echo 1 > sys/class/leds/flash/brightness
...
1500 mA::
#echo 16 > sys/class/leds/flash/brightness
Torch Mode
^^^^^^^^^^
In Torch Mode, the current source(LED) is programmed via the CURRENT CONTROL In Torch Mode, the current source(LED) is programmed via the CURRENT CONTROL
REGISTER(0x09).Torch Mode is activated by the ENABLE REGISTER(0x0A) or by the REGISTER(0x09).Torch Mode is activated by the ENABLE REGISTER(0x0A) or by the
hardware TORCH input. hardware TORCH input.
LM3556 torch can be controlled through sys/class/leds/torch/brightness file. LM3556 torch can be controlled through sys/class/leds/torch/brightness file.
* if TORCH pin is enabled, below example control brightness only, * if TORCH pin is enabled, below example control brightness only,
and ON / OFF will be controlled by TORCH pin. and ON / OFF will be controlled by TORCH pin.
Torch Example: Torch Example:
OFF : #echo 0 > sys/class/leds/torch/brightness
46.88 mA: #echo 1 > sys/class/leds/torch/brightness
... .....
375 mA : #echo 8 > sys/class/leds/torch/brightness
INDICATOR MODE OFF::
#echo 0 > sys/class/leds/torch/brightness
46.88 mA::
#echo 1 > sys/class/leds/torch/brightness
...
375 mA::
#echo 8 > sys/class/leds/torch/brightness
Indicator Mode
^^^^^^^^^^^^^^
Indicator pattern can be set through sys/class/leds/indicator/pattern file, Indicator pattern can be set through sys/class/leds/indicator/pattern file,
and 4 patterns are pre-defined in indicator_pattern array. and 4 patterns are pre-defined in indicator_pattern array.
According to N-lank, Pulse time and N Period values, different pattern wiill According to N-lank, Pulse time and N Period values, different pattern wiill
be generated.If you want new patterns for your own device, change be generated.If you want new patterns for your own device, change
indicator_pattern array with your own values and INDIC_PATTERN_SIZE. indicator_pattern array with your own values and INDIC_PATTERN_SIZE.
Please refer datasheet for more detail about N-Blank, Pulse time and N Period. Please refer datasheet for more detail about N-Blank, Pulse time and N Period.
Indicator pattern example: Indicator pattern example:
pattern 0: #echo 0 > sys/class/leds/indicator/pattern
.... pattern 0::
pattern 3: #echo 3 > sys/class/leds/indicator/pattern
#echo 0 > sys/class/leds/indicator/pattern
...
pattern 3::
#echo 3 > sys/class/leds/indicator/pattern
Indicator brightness can be controlled through Indicator brightness can be controlled through
sys/class/leds/indicator/brightness file. sys/class/leds/indicator/brightness file.
Example: Example:
OFF : #echo 0 > sys/class/leds/indicator/brightness
5.86 mA : #echo 1 > sys/class/leds/indicator/brightness OFF::
........
46.875mA : #echo 8 > sys/class/leds/indicator/brightness #echo 0 > sys/class/leds/indicator/brightness
5.86 mA::
#echo 1 > sys/class/leds/indicator/brightness
...
46.875mA::
#echo 8 > sys/class/leds/indicator/brightness
Notes Notes
----- -----
...@@ -70,7 +120,8 @@ Driver expects it is registered using the i2c_board_info mechanism. ...@@ -70,7 +120,8 @@ Driver expects it is registered using the i2c_board_info mechanism.
To register the chip at address 0x63 on specific adapter, set the platform data To register the chip at address 0x63 on specific adapter, set the platform data
according to include/linux/platform_data/leds-lm3556.h, set the i2c board info according to include/linux/platform_data/leds-lm3556.h, set the i2c board info
Example: Example::
static struct i2c_board_info board_i2c_ch4[] __initdata = { static struct i2c_board_info board_i2c_ch4[] __initdata = {
{ {
I2C_BOARD_INFO(LM3556_NAME, 0x63), I2C_BOARD_INFO(LM3556_NAME, 0x63),
...@@ -80,6 +131,7 @@ Example: ...@@ -80,6 +131,7 @@ Example:
and register it in the platform init function and register it in the platform init function
Example: Example::
board_register_i2c_bus(4, 400, board_register_i2c_bus(4, 400,
board_i2c_ch4, ARRAY_SIZE(board_i2c_ch4)); board_i2c_ch4, ARRAY_SIZE(board_i2c_ch4));
====================
Kernel driver lp3944 Kernel driver lp3944
==================== ====================
* National Semiconductor LP3944 Fun-light Chip * National Semiconductor LP3944 Fun-light Chip
Prefix: 'lp3944' Prefix: 'lp3944'
Addresses scanned: None (see the Notes section below) Addresses scanned: None (see the Notes section below)
Datasheet: Publicly available at the National Semiconductor website
Datasheet:
Publicly available at the National Semiconductor website
http://www.national.com/pf/LP/LP3944.html http://www.national.com/pf/LP/LP3944.html
Authors: Authors:
...@@ -19,8 +25,11 @@ is used as a led controller. ...@@ -19,8 +25,11 @@ is used as a led controller.
The DIM modes are used to set _blink_ patterns for leds, the pattern is The DIM modes are used to set _blink_ patterns for leds, the pattern is
specified supplying two parameters: specified supplying two parameters:
- period: from 0s to 1.6s
- duty cycle: percentage of the period the led is on, from 0 to 100 - period:
from 0s to 1.6s
- duty cycle:
percentage of the period the led is on, from 0 to 100
Setting a led in DIM0 or DIM1 mode makes it blink according to the pattern. Setting a led in DIM0 or DIM1 mode makes it blink according to the pattern.
See the datasheet for details. See the datasheet for details.
...@@ -35,7 +44,7 @@ The chip is used mainly in embedded contexts, so this driver expects it is ...@@ -35,7 +44,7 @@ The chip is used mainly in embedded contexts, so this driver expects it is
registered using the i2c_board_info mechanism. registered using the i2c_board_info mechanism.
To register the chip at address 0x60 on adapter 0, set the platform data To register the chip at address 0x60 on adapter 0, set the platform data
according to include/linux/leds-lp3944.h, set the i2c board info: according to include/linux/leds-lp3944.h, set the i2c board info::
static struct i2c_board_info a910_i2c_board_info[] __initdata = { static struct i2c_board_info a910_i2c_board_info[] __initdata = {
{ {
...@@ -44,7 +53,7 @@ according to include/linux/leds-lp3944.h, set the i2c board info: ...@@ -44,7 +53,7 @@ according to include/linux/leds-lp3944.h, set the i2c board info:
}, },
}; };
and register it in the platform init function and register it in the platform init function::
i2c_register_board_info(0, a910_i2c_board_info, i2c_register_board_info(0, a910_i2c_board_info,
ARRAY_SIZE(a910_i2c_board_info)); ARRAY_SIZE(a910_i2c_board_info));
========================
Kernel driver for lp5521 Kernel driver for lp5521
======================== ========================
...@@ -5,6 +6,7 @@ Kernel driver for lp5521 ...@@ -5,6 +6,7 @@ Kernel driver for lp5521
* Datasheet: http://www.national.com/pf/LP/LP5521.html * Datasheet: http://www.national.com/pf/LP/LP5521.html
Authors: Mathias Nyman, Yuri Zaporozhets, Samu Onkalo Authors: Mathias Nyman, Yuri Zaporozhets, Samu Onkalo
Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com) Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com)
Description Description
...@@ -22,39 +24,44 @@ There are two ways to run LED patterns. ...@@ -22,39 +24,44 @@ There are two ways to run LED patterns.
1) Legacy interface - enginex_mode and enginex_load 1) Legacy interface - enginex_mode and enginex_load
Control interface for the engines: Control interface for the engines:
x is 1 .. 3 x is 1 .. 3
enginex_mode : disabled, load, run
enginex_load : store program (visible only in engine load mode)
Example (start to blink the channel 2 led): enginex_mode:
disabled, load, run
enginex_load:
store program (visible only in engine load mode)
Example (start to blink the channel 2 led)::
cd /sys/class/leds/lp5521:channel2/device cd /sys/class/leds/lp5521:channel2/device
echo "load" > engine3_mode echo "load" > engine3_mode
echo "037f4d0003ff6000" > engine3_load echo "037f4d0003ff6000" > engine3_load
echo "run" > engine3_mode echo "run" > engine3_mode
To stop the engine: To stop the engine::
echo "disabled" > engine3_mode echo "disabled" > engine3_mode
2) Firmware interface - LP55xx common interface 2) Firmware interface - LP55xx common interface
For the details, please refer to 'firmware' section in leds-lp55xx.txt
For the details, please refer to 'firmware' section in leds-lp55xx.txt
sysfs contains a selftest entry. sysfs contains a selftest entry.
The test communicates with the chip and checks that The test communicates with the chip and checks that
the clock mode is automatically set to the requested one. the clock mode is automatically set to the requested one.
Each channel has its own led current settings. Each channel has its own led current settings.
/sys/class/leds/lp5521:channel0/led_current - RW
/sys/class/leds/lp5521:channel0/max_current - RO
Format: 10x mA i.e 10 means 1.0 mA
example platform data: - /sys/class/leds/lp5521:channel0/led_current - RW
- /sys/class/leds/lp5521:channel0/max_current - RO
Note: chan_nr can have values between 0 and 2. Format: 10x mA i.e 10 means 1.0 mA
The name of each channel can be configurable.
If the name field is not defined, the default name will be set to 'xxxx:channelN'
(XXXX : pdata->label or i2c client name, N : channel number)
static struct lp55xx_led_config lp5521_led_config[] = { example platform data::
static struct lp55xx_led_config lp5521_led_config[] = {
{ {
.name = "red", .name = "red",
.chan_nr = 0, .chan_nr = 0,
...@@ -71,31 +78,38 @@ static struct lp55xx_led_config lp5521_led_config[] = { ...@@ -71,31 +78,38 @@ static struct lp55xx_led_config lp5521_led_config[] = {
.led_current = 0, .led_current = 0,
.max_current = 130, .max_current = 130,
} }
}; };
static int lp5521_setup(void) static int lp5521_setup(void)
{ {
/* setup HW resources */ /* setup HW resources */
} }
static void lp5521_release(void) static void lp5521_release(void)
{ {
/* Release HW resources */ /* Release HW resources */
} }
static void lp5521_enable(bool state) static void lp5521_enable(bool state)
{ {
/* Control of chip enable signal */ /* Control of chip enable signal */
} }
static struct lp55xx_platform_data lp5521_platform_data = { static struct lp55xx_platform_data lp5521_platform_data = {
.led_config = lp5521_led_config, .led_config = lp5521_led_config,
.num_channels = ARRAY_SIZE(lp5521_led_config), .num_channels = ARRAY_SIZE(lp5521_led_config),
.clock_mode = LP55XX_CLOCK_EXT, .clock_mode = LP55XX_CLOCK_EXT,
.setup_resources = lp5521_setup, .setup_resources = lp5521_setup,
.release_resources = lp5521_release, .release_resources = lp5521_release,
.enable = lp5521_enable, .enable = lp5521_enable,
}; };
Note:
chan_nr can have values between 0 and 2.
The name of each channel can be configurable.
If the name field is not defined, the default name will be set to 'xxxx:channelN'
(XXXX : pdata->label or i2c client name, N : channel number)
If the current is set to 0 in the platform data, that channel is If the current is set to 0 in the platform data, that channel is
disabled and it is not visible in the sysfs. disabled and it is not visible in the sysfs.
========================
Kernel driver for lp5523 Kernel driver for lp5523
======================== ========================
...@@ -15,27 +16,39 @@ The name of each channel is configurable in the platform data - name and label. ...@@ -15,27 +16,39 @@ The name of each channel is configurable in the platform data - name and label.
There are three options to make the channel name. There are three options to make the channel name.
a) Define the 'name' in the platform data a) Define the 'name' in the platform data
To make specific channel name, then use 'name' platform data. To make specific channel name, then use 'name' platform data.
/sys/class/leds/R1 (name: 'R1')
/sys/class/leds/B1 (name: 'B1') - /sys/class/leds/R1 (name: 'R1')
- /sys/class/leds/B1 (name: 'B1')
b) Use the 'label' with no 'name' field b) Use the 'label' with no 'name' field
For one device name with channel number, then use 'label'. For one device name with channel number, then use 'label'.
/sys/class/leds/RGB:channelN (label: 'RGB', N: 0 ~ 8) - /sys/class/leds/RGB:channelN (label: 'RGB', N: 0 ~ 8)
c) Default c) Default
If both fields are NULL, 'lp5523' is used by default. If both fields are NULL, 'lp5523' is used by default.
/sys/class/leds/lp5523:channelN (N: 0 ~ 8) - /sys/class/leds/lp5523:channelN (N: 0 ~ 8)
LP5523 has the internal program memory for running various LED patterns. LP5523 has the internal program memory for running various LED patterns.
There are two ways to run LED patterns. There are two ways to run LED patterns.
1) Legacy interface - enginex_mode, enginex_load and enginex_leds 1) Legacy interface - enginex_mode, enginex_load and enginex_leds
Control interface for the engines: Control interface for the engines:
x is 1 .. 3 x is 1 .. 3
enginex_mode : disabled, load, run
enginex_load : microcode load enginex_mode:
enginex_leds : led mux control disabled, load, run
enginex_load:
microcode load
enginex_leds:
led mux control
::
cd /sys/class/leds/lp5523:channel2/device cd /sys/class/leds/lp5523:channel2/device
echo "load" > engine3_mode echo "load" > engine3_mode
...@@ -43,88 +56,92 @@ There are two ways to run LED patterns. ...@@ -43,88 +56,92 @@ There are two ways to run LED patterns.
echo "111111111" > engine3_leds echo "111111111" > engine3_leds
echo "run" > engine3_mode echo "run" > engine3_mode
To stop the engine: To stop the engine::
echo "disabled" > engine3_mode echo "disabled" > engine3_mode
2) Firmware interface - LP55xx common interface 2) Firmware interface - LP55xx common interface
For the details, please refer to 'firmware' section in leds-lp55xx.txt
For the details, please refer to 'firmware' section in leds-lp55xx.txt
LP5523 has three master faders. If a channel is mapped to one of LP5523 has three master faders. If a channel is mapped to one of
the master faders, its output is dimmed based on the value of the master the master faders, its output is dimmed based on the value of the master
fader. fader.
For example, For example::
echo "123000123" > master_fader_leds echo "123000123" > master_fader_leds
creates the following channel-fader mappings: creates the following channel-fader mappings::
channel 0,6 to master_fader1 channel 0,6 to master_fader1
channel 1,7 to master_fader2 channel 1,7 to master_fader2
channel 2,8 to master_fader3 channel 2,8 to master_fader3
Then, to have 25% of the original output on channel 0,6: Then, to have 25% of the original output on channel 0,6::
echo 64 > master_fader1 echo 64 > master_fader1
To have 0% of the original output (i.e. no output) channel 1,7: To have 0% of the original output (i.e. no output) channel 1,7::
echo 0 > master_fader2 echo 0 > master_fader2
To have 100% of the original output (i.e. no dimming) on channel 2,8: To have 100% of the original output (i.e. no dimming) on channel 2,8::
echo 255 > master_fader3 echo 255 > master_fader3
To clear all master fader controls: To clear all master fader controls::
echo "000000000" > master_fader_leds echo "000000000" > master_fader_leds
Selftest uses always the current from the platform data. Selftest uses always the current from the platform data.
Each channel contains led current settings. Each channel contains led current settings.
/sys/class/leds/lp5523:channel2/led_current - RW - /sys/class/leds/lp5523:channel2/led_current - RW
/sys/class/leds/lp5523:channel2/max_current - RO - /sys/class/leds/lp5523:channel2/max_current - RO
Format: 10x mA i.e 10 means 1.0 mA
Example platform data: Format: 10x mA i.e 10 means 1.0 mA
Note - chan_nr can have values between 0 and 8. Example platform data::
static struct lp55xx_led_config lp5523_led_config[] = { static struct lp55xx_led_config lp5523_led_config[] = {
{ {
.name = "D1", .name = "D1",
.chan_nr = 0, .chan_nr = 0,
.led_current = 50, .led_current = 50,
.max_current = 130, .max_current = 130,
}, },
... ...
{ {
.chan_nr = 8, .chan_nr = 8,
.led_current = 50, .led_current = 50,
.max_current = 130, .max_current = 130,
} }
}; };
static int lp5523_setup(void) static int lp5523_setup(void)
{ {
/* Setup HW resources */ /* Setup HW resources */
} }
static void lp5523_release(void) static void lp5523_release(void)
{ {
/* Release HW resources */ /* Release HW resources */
} }
static void lp5523_enable(bool state) static void lp5523_enable(bool state)
{ {
/* Control chip enable signal */ /* Control chip enable signal */
} }
static struct lp55xx_platform_data lp5523_platform_data = { static struct lp55xx_platform_data lp5523_platform_data = {
.led_config = lp5523_led_config, .led_config = lp5523_led_config,
.num_channels = ARRAY_SIZE(lp5523_led_config), .num_channels = ARRAY_SIZE(lp5523_led_config),
.clock_mode = LP55XX_CLOCK_EXT, .clock_mode = LP55XX_CLOCK_EXT,
.setup_resources = lp5523_setup, .setup_resources = lp5523_setup,
.release_resources = lp5523_release, .release_resources = lp5523_release,
.enable = lp5523_enable, .enable = lp5523_enable,
}; };
Note
chan_nr can have values between 0 and 8.
Kernel driver for LP5562 ========================
Kernel driver for lp5562
======================== ========================
* TI LP5562 LED Driver * TI LP5562 LED Driver
...@@ -6,6 +7,7 @@ Kernel driver for LP5562 ...@@ -6,6 +7,7 @@ Kernel driver for LP5562
Author: Milo(Woogyom) Kim <milo.kim@ti.com> Author: Milo(Woogyom) Kim <milo.kim@ti.com>
Description Description
===========
LP5562 can drive up to 4 channels. R/G/B and White. LP5562 can drive up to 4 channels. R/G/B and White.
LEDs can be controlled directly via the led class control interface. LEDs can be controlled directly via the led class control interface.
...@@ -14,30 +16,38 @@ Description ...@@ -14,30 +16,38 @@ Description
LP5562 has the internal program memory for running various LED patterns. LP5562 has the internal program memory for running various LED patterns.
For the details, please refer to 'firmware' section in leds-lp55xx.txt For the details, please refer to 'firmware' section in leds-lp55xx.txt
Device attribute: engine_mux Device attribute
================
engine_mux
3 Engines are allocated in LP5562, but the number of channel is 4. 3 Engines are allocated in LP5562, but the number of channel is 4.
Therefore each channel should be mapped to the engine number. Therefore each channel should be mapped to the engine number.
Value : RGB or W
Value: RGB or W
This attribute is used for programming LED data with the firmware interface. This attribute is used for programming LED data with the firmware interface.
Unlike the LP5521/LP5523/55231, LP5562 has unique feature for the engine mux, Unlike the LP5521/LP5523/55231, LP5562 has unique feature for the engine mux,
so additional sysfs is required. so additional sysfs is required
LED Map LED Map
===== === ===============================
Red ... Engine 1 (fixed) Red ... Engine 1 (fixed)
Green ... Engine 2 (fixed) Green ... Engine 2 (fixed)
Blue ... Engine 3 (fixed) Blue ... Engine 3 (fixed)
White ... Engine 1 or 2 or 3 (selective) White ... Engine 1 or 2 or 3 (selective)
===== === ===============================
How to load the program data using engine_mux How to load the program data using engine_mux
=============================================
Before loading the LP5562 program data, engine_mux should be written between Before loading the LP5562 program data, engine_mux should be written between
the engine selection and loading the firmware. the engine selection and loading the firmware.
Engine mux has two different mode, RGB and W. Engine mux has two different mode, RGB and W.
RGB is used for loading RGB program data, W is used for W program data. RGB is used for loading RGB program data, W is used for W program data.
For example, run blinking green channel pattern, For example, run blinking green channel pattern::
echo 2 > /sys/bus/i2c/devices/xxxx/select_engine # 2 is for green channel echo 2 > /sys/bus/i2c/devices/xxxx/select_engine # 2 is for green channel
echo "RGB" > /sys/bus/i2c/devices/xxxx/engine_mux # engine mux for RGB echo "RGB" > /sys/bus/i2c/devices/xxxx/engine_mux # engine mux for RGB
echo 1 > /sys/class/firmware/lp5562/loading echo 1 > /sys/class/firmware/lp5562/loading
...@@ -45,7 +55,8 @@ How to load the program data using engine_mux ...@@ -45,7 +55,8 @@ How to load the program data using engine_mux
echo 0 > /sys/class/firmware/lp5562/loading echo 0 > /sys/class/firmware/lp5562/loading
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
To run a blinking white pattern, To run a blinking white pattern::
echo 1 or 2 or 3 > /sys/bus/i2c/devices/xxxx/select_engine echo 1 or 2 or 3 > /sys/bus/i2c/devices/xxxx/select_engine
echo "W" > /sys/bus/i2c/devices/xxxx/engine_mux echo "W" > /sys/bus/i2c/devices/xxxx/engine_mux
echo 1 > /sys/class/firmware/lp5562/loading echo 1 > /sys/class/firmware/lp5562/loading
...@@ -54,19 +65,22 @@ How to load the program data using engine_mux ...@@ -54,19 +65,22 @@ How to load the program data using engine_mux
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
How to load the predefined patterns How to load the predefined patterns
===================================
Please refer to 'leds-lp55xx.txt" Please refer to 'leds-lp55xx.txt"
Setting Current of Each Channel Setting Current of Each Channel
===============================
Like LP5521 and LP5523/55231, LP5562 provides LED current settings. Like LP5521 and LP5523/55231, LP5562 provides LED current settings.
The 'led_current' and 'max_current' are used. The 'led_current' and 'max_current' are used.
(Example of Platform data) Example of Platform data
========================
To configure the platform specific data, lp55xx_platform_data structure is used. ::
static struct lp55xx_led_config lp5562_led_config[] = { static struct lp55xx_led_config lp5562_led_config[] = {
{ {
.name = "R", .name = "R",
.chan_nr = 0, .chan_nr = 0,
...@@ -91,30 +105,33 @@ static struct lp55xx_led_config lp5562_led_config[] = { ...@@ -91,30 +105,33 @@ static struct lp55xx_led_config lp5562_led_config[] = {
.led_current = 20, .led_current = 20,
.max_current = 40, .max_current = 40,
}, },
}; };
static int lp5562_setup(void) static int lp5562_setup(void)
{ {
/* setup HW resources */ /* setup HW resources */
} }
static void lp5562_release(void) static void lp5562_release(void)
{ {
/* Release HW resources */ /* Release HW resources */
} }
static void lp5562_enable(bool state) static void lp5562_enable(bool state)
{ {
/* Control of chip enable signal */ /* Control of chip enable signal */
} }
static struct lp55xx_platform_data lp5562_platform_data = { static struct lp55xx_platform_data lp5562_platform_data = {
.led_config = lp5562_led_config, .led_config = lp5562_led_config,
.num_channels = ARRAY_SIZE(lp5562_led_config), .num_channels = ARRAY_SIZE(lp5562_led_config),
.setup_resources = lp5562_setup, .setup_resources = lp5562_setup,
.release_resources = lp5562_release, .release_resources = lp5562_release,
.enable = lp5562_enable, .enable = lp5562_enable,
}; };
To configure the platform specific data, lp55xx_platform_data structure is used
If the current is set to 0 in the platform data, that channel is If the current is set to 0 in the platform data, that channel is
disabled and it is not visible in the sysfs. disabled and it is not visible in the sysfs.
=================================================
LP5521/LP5523/LP55231/LP5562/LP8501 Common Driver LP5521/LP5523/LP55231/LP5562/LP8501 Common Driver
================================================= =================================================
...@@ -14,6 +15,7 @@ LP5521, LP5523/55231, LP5562 and LP8501 have common features as below. ...@@ -14,6 +15,7 @@ LP5521, LP5523/55231, LP5562 and LP8501 have common features as below.
Program memory for running LED patterns Program memory for running LED patterns
The LP55xx common driver provides these features using exported functions. The LP55xx common driver provides these features using exported functions.
lp55xx_init_device() / lp55xx_deinit_device() lp55xx_init_device() / lp55xx_deinit_device()
lp55xx_register_leds() / lp55xx_unregister_leds() lp55xx_register_leds() / lp55xx_unregister_leds()
lp55xx_regsister_sysfs() / lp55xx_unregister_sysfs() lp55xx_regsister_sysfs() / lp55xx_unregister_sysfs()
...@@ -22,19 +24,19 @@ The LP55xx common driver provides these features using exported functions. ...@@ -22,19 +24,19 @@ The LP55xx common driver provides these features using exported functions.
In lp55xx common driver, two different data structure is used. In lp55xx common driver, two different data structure is used.
o lp55xx_led * lp55xx_led
control multi output LED channels such as led current, channel index. control multi output LED channels such as led current, channel index.
o lp55xx_chip * lp55xx_chip
general chip control such like the I2C and platform data. general chip control such like the I2C and platform data.
For example, LP5521 has maximum 3 LED channels. For example, LP5521 has maximum 3 LED channels.
LP5523/55231 has 9 output channels. LP5523/55231 has 9 output channels::
lp55xx_chip for LP5521 ... lp55xx_led #1 lp55xx_chip for LP5521 ... lp55xx_led #1
lp55xx_led #2 lp55xx_led #2
lp55xx_led #3 lp55xx_led #3
lp55xx_chip for LP5523 ... lp55xx_led #1 lp55xx_chip for LP5523 ... lp55xx_led #1
lp55xx_led #2 lp55xx_led #2
. .
. .
...@@ -45,120 +47,147 @@ lp55xx_chip for LP5523 ... lp55xx_led #1 ...@@ -45,120 +47,147 @@ lp55xx_chip for LP5523 ... lp55xx_led #1
To support device specific configurations, special structure To support device specific configurations, special structure
'lpxx_device_config' is used. 'lpxx_device_config' is used.
Maximum number of channels - Maximum number of channels
Reset command, chip enable command - Reset command, chip enable command
Chip specific initialization - Chip specific initialization
Brightness control register access - Brightness control register access
Setting LED output current - Setting LED output current
Program memory address access for running patterns - Program memory address access for running patterns
Additional device specific attributes - Additional device specific attributes
( Firmware Interface ) ( Firmware Interface )
LP55xx family devices have the internal program memory for running LP55xx family devices have the internal program memory for running
various LED patterns. various LED patterns.
This pattern data is saved as a file in the user-land or This pattern data is saved as a file in the user-land or
hex byte string is written into the memory through the I2C. hex byte string is written into the memory through the I2C.
LP55xx common driver supports the firmware interface. LP55xx common driver supports the firmware interface.
LP55xx chips have three program engines. LP55xx chips have three program engines.
To load and run the pattern, the programming sequence is following. To load and run the pattern, the programming sequence is following.
(1) Select an engine number (1/2/3) (1) Select an engine number (1/2/3)
(2) Mode change to load (2) Mode change to load
(3) Write pattern data into selected area (3) Write pattern data into selected area
(4) Mode change to run (4) Mode change to run
The LP55xx common driver provides simple interfaces as below. The LP55xx common driver provides simple interfaces as below.
select_engine : Select which engine is used for running program
run_engine : Start program which is loaded via the firmware interface select_engine:
firmware : Load program data Select which engine is used for running program
run_engine:
Start program which is loaded via the firmware interface
firmware:
Load program data
In case of LP5523, one more command is required, 'enginex_leds'. In case of LP5523, one more command is required, 'enginex_leds'.
It is used for selecting LED output(s) at each engine number. It is used for selecting LED output(s) at each engine number.
In more details, please refer to 'leds-lp5523.txt'. In more details, please refer to 'leds-lp5523.txt'.
For example, run blinking pattern in engine #1 of LP5521 For example, run blinking pattern in engine #1 of LP5521::
echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
echo 1 > /sys/class/firmware/lp5521/loading echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
echo "4000600040FF6000" > /sys/class/firmware/lp5521/data echo 1 > /sys/class/firmware/lp5521/loading
echo 0 > /sys/class/firmware/lp5521/loading echo "4000600040FF6000" > /sys/class/firmware/lp5521/data
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine echo 0 > /sys/class/firmware/lp5521/loading
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
For example, run blinking pattern in engine #3 of LP55231 For example, run blinking pattern in engine #3 of LP55231
Two LEDs are configured as pattern output channels.
echo 3 > /sys/bus/i2c/devices/xxxx/select_engine Two LEDs are configured as pattern output channels::
echo 1 > /sys/class/firmware/lp55231/loading
echo "9d0740ff7e0040007e00a0010000" > /sys/class/firmware/lp55231/data echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
echo 0 > /sys/class/firmware/lp55231/loading echo 1 > /sys/class/firmware/lp55231/loading
echo "000001100" > /sys/bus/i2c/devices/xxxx/engine3_leds echo "9d0740ff7e0040007e00a0010000" > /sys/class/firmware/lp55231/data
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine echo 0 > /sys/class/firmware/lp55231/loading
echo "000001100" > /sys/bus/i2c/devices/xxxx/engine3_leds
To start blinking patterns in engine #2 and #3 simultaneously, echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
for idx in 2 3
do To start blinking patterns in engine #2 and #3 simultaneously::
for idx in 2 3
do
echo $idx > /sys/class/leds/red/device/select_engine echo $idx > /sys/class/leds/red/device/select_engine
sleep 0.1 sleep 0.1
echo 1 > /sys/class/firmware/lp5521/loading echo 1 > /sys/class/firmware/lp5521/loading
echo "4000600040FF6000" > /sys/class/firmware/lp5521/data echo "4000600040FF6000" > /sys/class/firmware/lp5521/data
echo 0 > /sys/class/firmware/lp5521/loading echo 0 > /sys/class/firmware/lp5521/loading
done done
echo 1 > /sys/class/leds/red/device/run_engine echo 1 > /sys/class/leds/red/device/run_engine
Here is another example for LP5523. Here is another example for LP5523.
Full LED strings are selected by 'engine2_leds'.
echo 2 > /sys/bus/i2c/devices/xxxx/select_engine Full LED strings are selected by 'engine2_leds'::
echo 1 > /sys/class/firmware/lp5523/loading
echo "9d80400004ff05ff437f0000" > /sys/class/firmware/lp5523/data echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
echo 0 > /sys/class/firmware/lp5523/loading echo 1 > /sys/class/firmware/lp5523/loading
echo "111111111" > /sys/bus/i2c/devices/xxxx/engine2_leds echo "9d80400004ff05ff437f0000" > /sys/class/firmware/lp5523/data
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine echo 0 > /sys/class/firmware/lp5523/loading
echo "111111111" > /sys/bus/i2c/devices/xxxx/engine2_leds
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
As soon as 'loading' is set to 0, registered callback is called. As soon as 'loading' is set to 0, registered callback is called.
Inside the callback, the selected engine is loaded and memory is updated. Inside the callback, the selected engine is loaded and memory is updated.
To run programmed pattern, 'run_engine' attribute should be enabled. To run programmed pattern, 'run_engine' attribute should be enabled.
The pattern sequence of LP8501 is similar to LP5523. The pattern sequence of LP8501 is similar to LP5523.
However pattern data is specific. However pattern data is specific.
Ex 1) Engine 1 is used
echo 1 > /sys/bus/i2c/devices/xxxx/select_engine Ex 1) Engine 1 is used::
echo 1 > /sys/class/firmware/lp8501/loading
echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
echo 0 > /sys/class/firmware/lp8501/loading echo 1 > /sys/class/firmware/lp8501/loading
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
echo 0 > /sys/class/firmware/lp8501/loading
Ex 2) Engine 2 and 3 are used at the same time echo 1 > /sys/bus/i2c/devices/xxxx/run_engine
echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
sleep 1 Ex 2) Engine 2 and 3 are used at the same time::
echo 1 > /sys/class/firmware/lp8501/loading
echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
echo 0 > /sys/class/firmware/lp8501/loading sleep 1
sleep 1 echo 1 > /sys/class/firmware/lp8501/loading
echo 3 > /sys/bus/i2c/devices/xxxx/select_engine echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
sleep 1 echo 0 > /sys/class/firmware/lp8501/loading
echo 1 > /sys/class/firmware/lp8501/loading sleep 1
echo "9d0340ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
echo 0 > /sys/class/firmware/lp8501/loading sleep 1
sleep 1 echo 1 > /sys/class/firmware/lp8501/loading
echo 1 > /sys/class/leds/d1/device/run_engine echo "9d0340ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
echo 0 > /sys/class/firmware/lp8501/loading
sleep 1
echo 1 > /sys/class/leds/d1/device/run_engine
( 'run_engine' and 'firmware_cb' ) ( 'run_engine' and 'firmware_cb' )
The sequence of running the program data is common. The sequence of running the program data is common.
But each device has own specific register addresses for commands. But each device has own specific register addresses for commands.
To support this, 'run_engine' and 'firmware_cb' are configurable in each driver. To support this, 'run_engine' and 'firmware_cb' are configurable in each driver.
run_engine : Control the selected engine
firmware_cb : The callback function after loading the firmware is done. run_engine:
Control the selected engine
firmware_cb:
The callback function after loading the firmware is done.
Chip specific commands for loading and updating program memory. Chip specific commands for loading and updating program memory.
( Predefined pattern data ) ( Predefined pattern data )
Without the firmware interface, LP55xx driver provides another method for Without the firmware interface, LP55xx driver provides another method for
loading a LED pattern. That is 'predefined' pattern. loading a LED pattern. That is 'predefined' pattern.
A predefined pattern is defined in the platform data and load it(or them) A predefined pattern is defined in the platform data and load it(or them)
via the sysfs if needed. via the sysfs if needed.
To use the predefined pattern concept, 'patterns' and 'num_patterns' should be To use the predefined pattern concept, 'patterns' and 'num_patterns' should be
configured. configured.
Example of predefined pattern data: Example of predefined pattern data::
/* mode_1: blinking data */ /* mode_1: blinking data */
static const u8 mode_1[] = { static const u8 mode_1[] = {
...@@ -185,10 +214,11 @@ configured. ...@@ -185,10 +214,11 @@ configured.
.num_patterns = ARRAY_SIZE(board_led_patterns), .num_patterns = ARRAY_SIZE(board_led_patterns),
}; };
Then, mode_1 and mode_2 can be run via through the sysfs. Then, mode_1 and mode_2 can be run via through the sysfs::
echo 1 > /sys/bus/i2c/devices/xxxx/led_pattern # red blinking LED pattern echo 1 > /sys/bus/i2c/devices/xxxx/led_pattern # red blinking LED pattern
echo 2 > /sys/bus/i2c/devices/xxxx/led_pattern # blue LED always on echo 2 > /sys/bus/i2c/devices/xxxx/led_pattern # blue LED always on
To stop running pattern, To stop running pattern::
echo 0 > /sys/bus/i2c/devices/xxxx/led_pattern echo 0 > /sys/bus/i2c/devices/xxxx/led_pattern
=======================================
Kernel driver for Mellanox systems LEDs Kernel driver for Mellanox systems LEDs
======================================= =======================================
...@@ -9,102 +10,109 @@ Description ...@@ -9,102 +10,109 @@ Description
----------- -----------
Driver provides the following LEDs for the systems "msx6710", "msx6720", Driver provides the following LEDs for the systems "msx6710", "msx6720",
"msb7700", "msn2700", "msx1410", "msn2410", "msb7800", "msn2740": "msb7700", "msn2700", "msx1410", "msn2410", "msb7800", "msn2740":
mlxcpld:fan1:green
mlxcpld:fan1:red - mlxcpld:fan1:green
mlxcpld:fan2:green - mlxcpld:fan1:red
mlxcpld:fan2:red - mlxcpld:fan2:green
mlxcpld:fan3:green - mlxcpld:fan2:red
mlxcpld:fan3:red - mlxcpld:fan3:green
mlxcpld:fan4:green - mlxcpld:fan3:red
mlxcpld:fan4:red - mlxcpld:fan4:green
mlxcpld:psu:green - mlxcpld:fan4:red
mlxcpld:psu:red - mlxcpld:psu:green
mlxcpld:status:green - mlxcpld:psu:red
mlxcpld:status:red - mlxcpld:status:green
- mlxcpld:status:red
"status" "status"
CPLD reg offset: 0x20 - CPLD reg offset: 0x20
Bits [3:0] - Bits [3:0]
"psu" "psu"
CPLD reg offset: 0x20 - CPLD reg offset: 0x20
Bits [7:4] - Bits [7:4]
"fan1" "fan1"
CPLD reg offset: 0x21 - CPLD reg offset: 0x21
Bits [3:0] - Bits [3:0]
"fan2" "fan2"
CPLD reg offset: 0x21 - CPLD reg offset: 0x21
Bits [7:4] - Bits [7:4]
"fan3" "fan3"
CPLD reg offset: 0x22 - CPLD reg offset: 0x22
Bits [3:0] - Bits [3:0]
"fan4" "fan4"
CPLD reg offset: 0x22 - CPLD reg offset: 0x22
Bits [7:4] - Bits [7:4]
Color mask for all the above LEDs: Color mask for all the above LEDs:
[bit3,bit2,bit1,bit0] or [bit3,bit2,bit1,bit0] or
[bit7,bit6,bit5,bit4]: [bit7,bit6,bit5,bit4]:
[0,0,0,0] = LED OFF
[0,1,0,1] = Red static ON - [0,0,0,0] = LED OFF
[1,1,0,1] = Green static ON - [0,1,0,1] = Red static ON
[0,1,1,0] = Red blink 3Hz - [1,1,0,1] = Green static ON
[1,1,1,0] = Green blink 3Hz - [0,1,1,0] = Red blink 3Hz
[0,1,1,1] = Red blink 6Hz - [1,1,1,0] = Green blink 3Hz
[1,1,1,1] = Green blink 6Hz - [0,1,1,1] = Red blink 6Hz
- [1,1,1,1] = Green blink 6Hz
Driver provides the following LEDs for the system "msn2100": Driver provides the following LEDs for the system "msn2100":
mlxcpld:fan:green
mlxcpld:fan:red - mlxcpld:fan:green
mlxcpld:psu1:green - mlxcpld:fan:red
mlxcpld:psu1:red - mlxcpld:psu1:green
mlxcpld:psu2:green - mlxcpld:psu1:red
mlxcpld:psu2:red - mlxcpld:psu2:green
mlxcpld:status:green - mlxcpld:psu2:red
mlxcpld:status:red - mlxcpld:status:green
mlxcpld:uid:blue - mlxcpld:status:red
- mlxcpld:uid:blue
"status" "status"
CPLD reg offset: 0x20 - CPLD reg offset: 0x20
Bits [3:0] - Bits [3:0]
"fan" "fan"
CPLD reg offset: 0x21 - CPLD reg offset: 0x21
Bits [3:0] - Bits [3:0]
"psu1" "psu1"
CPLD reg offset: 0x23 - CPLD reg offset: 0x23
Bits [3:0] - Bits [3:0]
"psu2" "psu2"
CPLD reg offset: 0x23 - CPLD reg offset: 0x23
Bits [7:4] - Bits [7:4]
"uid" "uid"
CPLD reg offset: 0x24 - CPLD reg offset: 0x24
Bits [3:0] - Bits [3:0]
Color mask for all the above LEDs, excepted uid: Color mask for all the above LEDs, excepted uid:
[bit3,bit2,bit1,bit0] or [bit3,bit2,bit1,bit0] or
[bit7,bit6,bit5,bit4]: [bit7,bit6,bit5,bit4]:
[0,0,0,0] = LED OFF
[0,1,0,1] = Red static ON - [0,0,0,0] = LED OFF
[1,1,0,1] = Green static ON - [0,1,0,1] = Red static ON
[0,1,1,0] = Red blink 3Hz - [1,1,0,1] = Green static ON
[1,1,1,0] = Green blink 3Hz - [0,1,1,0] = Red blink 3Hz
[0,1,1,1] = Red blink 6Hz - [1,1,1,0] = Green blink 3Hz
[1,1,1,1] = Green blink 6Hz - [0,1,1,1] = Red blink 6Hz
- [1,1,1,1] = Green blink 6Hz
Color mask for uid LED: Color mask for uid LED:
[bit3,bit2,bit1,bit0]: [bit3,bit2,bit1,bit0]:
[0,0,0,0] = LED OFF
[1,1,0,1] = Blue static ON - [0,0,0,0] = LED OFF
[1,1,1,0] = Blue blink 3Hz - [1,1,0,1] = Blue static ON
[1,1,1,1] = Blue blink 6Hz - [1,1,1,0] = Blue blink 3Hz
- [1,1,1,1] = Blue blink 6Hz
Driver supports HW blinking at 3Hz and 6Hz frequency (50% duty cycle). Driver supports HW blinking at 3Hz and 6Hz frequency (50% duty cycle).
For 3Hz duty cylce is about 167 msec, for 6Hz is about 83 msec. For 3Hz duty cylce is about 167 msec, for 6Hz is about 83 msec.
====================
One-shot LED Trigger One-shot LED Trigger
==================== ====================
...@@ -17,27 +18,27 @@ additional "invert" property specifies if the LED has to stay off (normal) or ...@@ -17,27 +18,27 @@ additional "invert" property specifies if the LED has to stay off (normal) or
on (inverted) when not rearmed. on (inverted) when not rearmed.
The trigger can be activated from user space on led class devices as shown The trigger can be activated from user space on led class devices as shown
below: below::
echo oneshot > trigger echo oneshot > trigger
This adds sysfs attributes to the LED that are documented in: This adds sysfs attributes to the LED that are documented in:
Documentation/ABI/testing/sysfs-class-led-trigger-oneshot Documentation/ABI/testing/sysfs-class-led-trigger-oneshot
Example use-case: network devices, initialization: Example use-case: network devices, initialization::
echo oneshot > trigger # set trigger for this led echo oneshot > trigger # set trigger for this led
echo 33 > delay_on # blink at 1 / (33 + 33) Hz on continuous traffic echo 33 > delay_on # blink at 1 / (33 + 33) Hz on continuous traffic
echo 33 > delay_off echo 33 > delay_off
interface goes up: interface goes up::
echo 1 > invert # set led as normally-on, turn the led on echo 1 > invert # set led as normally-on, turn the led on
packet received/transmitted: packet received/transmitted::
echo 1 > shot # led starts blinking, ignored if already blinking echo 1 > shot # led starts blinking, ignored if already blinking
interface goes down interface goes down::
echo 0 > invert # set led as normally-off, turn the led off echo 0 > invert # set led as normally-off, turn the led off
=====================
LED Transient Trigger LED Transient Trigger
===================== =====================
...@@ -62,12 +63,13 @@ non-transient state. When driver gets suspended, irrespective of the transient ...@@ -62,12 +63,13 @@ non-transient state. When driver gets suspended, irrespective of the transient
state, the LED state changes to LED_OFF. state, the LED state changes to LED_OFF.
Transient trigger can be enabled and disabled from user space on led class Transient trigger can be enabled and disabled from user space on led class
devices, that support this trigger as shown below: devices, that support this trigger as shown below::
echo transient > trigger echo transient > trigger
echo none > trigger echo none > trigger
NOTE: Add a new property trigger state to control the state. NOTE:
Add a new property trigger state to control the state.
This trigger exports three properties, activate, state, and duration. When This trigger exports three properties, activate, state, and duration. When
transient trigger is activated these properties are set to default values. transient trigger is activated these properties are set to default values.
...@@ -79,7 +81,8 @@ transient trigger is activated these properties are set to default values. ...@@ -79,7 +81,8 @@ transient trigger is activated these properties are set to default values.
- state allows user to specify a transient state to be held for the specified - state allows user to specify a transient state to be held for the specified
duration. duration.
activate - one shot timer activate mechanism. activate
- one shot timer activate mechanism.
1 when activated, 0 when deactivated. 1 when activated, 0 when deactivated.
default value is zero when transient trigger is enabled, default value is zero when transient trigger is enabled,
to allow duration to be set. to allow duration to be set.
...@@ -89,12 +92,14 @@ transient trigger is activated these properties are set to default values. ...@@ -89,12 +92,14 @@ transient trigger is activated these properties are set to default values.
deactivated state indicates that there is no active timer deactivated state indicates that there is no active timer
running. running.
duration - one shot timer value. When activate is set, duration value duration
- one shot timer value. When activate is set, duration value
is used to start a timer that runs once. This value doesn't is used to start a timer that runs once. This value doesn't
get changed by the trigger unless user does a set via get changed by the trigger unless user does a set via
echo new_value > duration echo new_value > duration
state - transient state to be held. It has two values 0 or 1. 0 maps state
- transient state to be held. It has two values 0 or 1. 0 maps
to LED_OFF and 1 maps to LED_FULL. The specified state is to LED_OFF and 1 maps to LED_FULL. The specified state is
held for the duration of the one shot timer and then the held for the duration of the one shot timer and then the
state gets changed to the non-transient state which is the state gets changed to the non-transient state which is the
...@@ -114,36 +119,46 @@ When timer expires activate goes back to deactivated state, duration is left ...@@ -114,36 +119,46 @@ When timer expires activate goes back to deactivated state, duration is left
at the set value to be used when activate is set at a future time. This will at the set value to be used when activate is set at a future time. This will
allow user app to set the time once and activate it to run it once for the allow user app to set the time once and activate it to run it once for the
specified value as needed. When timer expires, state is restored to the specified value as needed. When timer expires, state is restored to the
non-transient state which is the inverse of the transient state. non-transient state which is the inverse of the transient state:
echo 1 > activate - starts timer = duration when duration is not 0. ================= ===============================================
echo 0 > activate - cancels currently running timer. echo 1 > activate starts timer = duration when duration is not 0.
echo n > duration - stores timer value to be used upon next echo 0 > activate cancels currently running timer.
echo n > duration stores timer value to be used upon next
activate. Currently active timer if activate. Currently active timer if
any, continues to run for the specified time. any, continues to run for the specified time.
echo 0 > duration - stores timer value to be used upon next echo 0 > duration stores timer value to be used upon next
activate. Currently active timer if any, activate. Currently active timer if any,
continues to run for the specified time. continues to run for the specified time.
echo 1 > state - stores desired transient state LED_FULL to be echo 1 > state stores desired transient state LED_FULL to be
held for the specified duration. held for the specified duration.
echo 0 > state - stores desired transient state LED_OFF to be echo 0 > state stores desired transient state LED_OFF to be
held for the specified duration. held for the specified duration.
================= ===============================================
What is not supported
=====================
What is not supported:
======================
- Timer activation is one shot and extending and/or shortening the timer - Timer activation is one shot and extending and/or shortening the timer
is not supported. is not supported.
Example use-case 1: Examples
========
use-case 1::
echo transient > trigger echo transient > trigger
echo n > duration echo n > duration
echo 1 > state echo 1 > state
repeat the following step as needed:
repeat the following step as needed::
echo 1 > activate - start timer = duration to run once echo 1 > activate - start timer = duration to run once
echo 1 > activate - start timer = duration to run once echo 1 > activate - start timer = duration to run once
echo none > trigger echo none > trigger
This trigger is intended to be used for for the following example use cases: This trigger is intended to be used for for the following example use cases:
- Control of vibrate (phones, tablets etc.) hardware by user space app. - Control of vibrate (phones, tablets etc.) hardware by user space app.
- Use of LED by user space app as activity indicator. - Use of LED by user space app as activity indicator.
- Use of LED by user space app as a kind of watchdog indicator -- as - Use of LED by user space app as a kind of watchdog indicator -- as
......
====================
USB port LED trigger USB port LED trigger
==================== ====================
...@@ -10,14 +11,18 @@ listed as separated entries in a "ports" subdirectory. Selecting is handled by ...@@ -10,14 +11,18 @@ listed as separated entries in a "ports" subdirectory. Selecting is handled by
echoing "1" to a chosen port. echoing "1" to a chosen port.
Please note that this trigger allows selecting multiple USB ports for a single Please note that this trigger allows selecting multiple USB ports for a single
LED. This can be useful in two cases: LED.
This can be useful in two cases:
1) Device with single USB LED and few physical ports 1) Device with single USB LED and few physical ports
====================================================
In such a case LED will be turned on as long as there is at least one connected In such a case LED will be turned on as long as there is at least one connected
USB device. USB device.
2) Device with a physical port handled by few controllers 2) Device with a physical port handled by few controllers
=========================================================
Some devices may have one controller per PHY standard. E.g. USB 3.0 physical Some devices may have one controller per PHY standard. E.g. USB 3.0 physical
port may be handled by ohci-platform, ehci-platform and xhci-hcd. If there is port may be handled by ohci-platform, ehci-platform and xhci-hcd. If there is
...@@ -25,14 +30,14 @@ only one LED user will most likely want to assign ports from all 3 hubs. ...@@ -25,14 +30,14 @@ only one LED user will most likely want to assign ports from all 3 hubs.
This trigger can be activated from user space on led class devices as shown This trigger can be activated from user space on led class devices as shown
below: below::
echo usbport > trigger echo usbport > trigger
This adds sysfs attributes to the LED that are documented in: This adds sysfs attributes to the LED that are documented in:
Documentation/ABI/testing/sysfs-class-led-trigger-usbport Documentation/ABI/testing/sysfs-class-led-trigger-usbport
Example use-case: Example use-case::
echo usbport > trigger echo usbport > trigger
echo 1 > ports/usb1-port1 echo 1 > ports/usb1-port1
......
==============
Userspace LEDs Userspace LEDs
============== ==============
...@@ -10,7 +11,7 @@ Usage ...@@ -10,7 +11,7 @@ Usage
When the driver is loaded, a character device is created at /dev/uleds. To When the driver is loaded, a character device is created at /dev/uleds. To
create a new LED class device, open /dev/uleds and write a uleds_user_dev create a new LED class device, open /dev/uleds and write a uleds_user_dev
structure to it (found in kernel public header file linux/uleds.h). structure to it (found in kernel public header file linux/uleds.h)::
#define LED_MAX_NAME_SIZE 64 #define LED_MAX_NAME_SIZE 64
......
...@@ -10165,7 +10165,7 @@ L: linux-leds@vger.kernel.org ...@@ -10165,7 +10165,7 @@ L: linux-leds@vger.kernel.org
S: Supported S: Supported
F: drivers/leds/leds-mlxcpld.c F: drivers/leds/leds-mlxcpld.c
F: drivers/leds/leds-mlxreg.c F: drivers/leds/leds-mlxreg.c
F: Documentation/leds/leds-mlxcpld.txt F: Documentation/leds/leds-mlxcpld.rst
MELLANOX PLATFORM DRIVER MELLANOX PLATFORM DRIVER
M: Vadim Pasternak <vadimp@mellanox.com> M: Vadim Pasternak <vadimp@mellanox.com>
......
...@@ -784,6 +784,41 @@ config LEDS_NIC78BX ...@@ -784,6 +784,41 @@ config LEDS_NIC78BX
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called leds-nic78bx. will be called leds-nic78bx.
config LEDS_SPI_BYTE
tristate "LED support for SPI LED controller with a single byte"
depends on LEDS_CLASS
depends on SPI
depends on OF
help
This option enables support for LED controller which use a single byte
for controlling the brightness. Currently the following controller is
supported: Ubiquiti airCube ISP microcontroller based LED controller.
config LEDS_TI_LMU_COMMON
tristate "LED driver for TI LMU"
depends on LEDS_CLASS
depends on REGMAP
help
Say Y to enable the LED driver for TI LMU devices.
This supports common features between the TI LM3532, LM3631, LM3632,
LM3633, LM3695 and LM3697.
config LEDS_LM3697
tristate "LED driver for LM3697"
depends on LEDS_TI_LMU_COMMON
depends on I2C && OF
help
Say Y to enable the LM3697 LED driver for TI LMU devices.
This supports the LED device LM3697.
config LEDS_LM36274
tristate "LED driver for LM36274"
depends on LEDS_TI_LMU_COMMON
depends on MFD_TI_LMU
help
Say Y to enable the LM36274 LED driver for TI LMU devices.
This supports the LED device LM36274.
comment "LED Triggers" comment "LED Triggers"
source "drivers/leds/trigger/Kconfig" source "drivers/leds/trigger/Kconfig"
......
...@@ -77,10 +77,14 @@ obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o ...@@ -77,10 +77,14 @@ obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o
obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o obj-$(CONFIG_LEDS_MLXCPLD) += leds-mlxcpld.o
obj-$(CONFIG_LEDS_MLXREG) += leds-mlxreg.o obj-$(CONFIG_LEDS_MLXREG) += leds-mlxreg.o
obj-$(CONFIG_LEDS_NIC78BX) += leds-nic78bx.o obj-$(CONFIG_LEDS_NIC78BX) += leds-nic78bx.o
obj-$(CONFIG_LEDS_SPI_BYTE) += leds-spi-byte.o
obj-$(CONFIG_LEDS_MT6323) += leds-mt6323.o obj-$(CONFIG_LEDS_MT6323) += leds-mt6323.o
obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o obj-$(CONFIG_LEDS_LM3692X) += leds-lm3692x.o
obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o
obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o obj-$(CONFIG_LEDS_LM3601X) += leds-lm3601x.o
obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o
obj-$(CONFIG_LEDS_LM3697) += leds-lm3697.o
obj-$(CONFIG_LEDS_LM36274) += leds-lm36274.o
# LED SPI Drivers # LED SPI Drivers
obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o
......
// SPDX-License-Identifier: GPL-2.0
// TI LM36274 LED chip family driver
// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/leds-ti-lmu-common.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/mfd/ti-lmu.h>
#include <linux/mfd/ti-lmu-register.h>
#include <uapi/linux/uleds.h>
#define LM36274_MAX_STRINGS 4
#define LM36274_BL_EN BIT(4)
/**
* struct lm36274
* @pdev: platform device
* @led_dev: led class device
* @lmu_data: Register and setting values for common code
* @regmap: Devices register map
* @dev: Pointer to the devices device struct
* @led_sources - The LED strings supported in this array
* @num_leds - Number of LED strings are supported in this array
*/
struct lm36274 {
struct platform_device *pdev;
struct led_classdev led_dev;
struct ti_lmu_bank lmu_data;
struct regmap *regmap;
struct device *dev;
u32 led_sources[LM36274_MAX_STRINGS];
int num_leds;
};
static int lm36274_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brt_val)
{
struct lm36274 *led = container_of(led_cdev, struct lm36274, led_dev);
return ti_lmu_common_set_brightness(&led->lmu_data, brt_val);
}
static int lm36274_init(struct lm36274 *lm36274_data)
{
int enable_val = 0;
int i;
for (i = 0; i < lm36274_data->num_leds; i++)
enable_val |= (1 << lm36274_data->led_sources[i]);
if (!enable_val) {
dev_err(lm36274_data->dev, "No LEDs were enabled\n");
return -EINVAL;
}
enable_val |= LM36274_BL_EN;
return regmap_write(lm36274_data->regmap, LM36274_REG_BL_EN,
enable_val);
}
static int lm36274_parse_dt(struct lm36274 *lm36274_data)
{
struct fwnode_handle *child = NULL;
char label[LED_MAX_NAME_SIZE];
struct device *dev = &lm36274_data->pdev->dev;
const char *name;
int child_cnt;
int ret = -EINVAL;
/* There should only be 1 node */
child_cnt = device_get_child_node_count(dev);
if (child_cnt != 1)
return -EINVAL;
device_for_each_child_node(dev, child) {
ret = fwnode_property_read_string(child, "label", &name);
if (ret)
snprintf(label, sizeof(label),
"%s::", lm36274_data->pdev->name);
else
snprintf(label, sizeof(label),
"%s:%s", lm36274_data->pdev->name, name);
lm36274_data->num_leds = fwnode_property_read_u32_array(child,
"led-sources",
NULL, 0);
if (lm36274_data->num_leds <= 0)
return -ENODEV;
ret = fwnode_property_read_u32_array(child, "led-sources",
lm36274_data->led_sources,
lm36274_data->num_leds);
if (ret) {
dev_err(dev, "led-sources property missing\n");
return ret;
}
fwnode_property_read_string(child, "linux,default-trigger",
&lm36274_data->led_dev.default_trigger);
}
lm36274_data->lmu_data.regmap = lm36274_data->regmap;
lm36274_data->lmu_data.max_brightness = MAX_BRIGHTNESS_11BIT;
lm36274_data->lmu_data.msb_brightness_reg = LM36274_REG_BRT_MSB;
lm36274_data->lmu_data.lsb_brightness_reg = LM36274_REG_BRT_LSB;
lm36274_data->led_dev.name = label;
lm36274_data->led_dev.max_brightness = MAX_BRIGHTNESS_11BIT;
lm36274_data->led_dev.brightness_set_blocking = lm36274_brightness_set;
return 0;
}
static int lm36274_probe(struct platform_device *pdev)
{
struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
struct lm36274 *lm36274_data;
int ret;
lm36274_data = devm_kzalloc(&pdev->dev, sizeof(*lm36274_data),
GFP_KERNEL);
if (!lm36274_data)
return -ENOMEM;
lm36274_data->pdev = pdev;
lm36274_data->dev = lmu->dev;
lm36274_data->regmap = lmu->regmap;
dev_set_drvdata(&pdev->dev, lm36274_data);
ret = lm36274_parse_dt(lm36274_data);
if (ret) {
dev_err(lm36274_data->dev, "Failed to parse DT node\n");
return ret;
}
ret = lm36274_init(lm36274_data);
if (ret) {
dev_err(lm36274_data->dev, "Failed to init the device\n");
return ret;
}
return devm_led_classdev_register(lm36274_data->dev,
&lm36274_data->led_dev);
}
static const struct of_device_id of_lm36274_leds_match[] = {
{ .compatible = "ti,lm36274-backlight", },
{},
};
MODULE_DEVICE_TABLE(of, of_lm36274_leds_match);
static struct platform_driver lm36274_driver = {
.probe = lm36274_probe,
.driver = {
.name = "lm36274-leds",
},
};
module_platform_driver(lm36274_driver)
MODULE_DESCRIPTION("Texas Instruments LM36274 LED driver");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0
// TI LM3697 LED chip family driver
// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/leds-ti-lmu-common.h>
#define LM3697_REV 0x0
#define LM3697_RESET 0x1
#define LM3697_OUTPUT_CONFIG 0x10
#define LM3697_CTRL_A_RAMP 0x11
#define LM3697_CTRL_B_RAMP 0x12
#define LM3697_CTRL_A_B_RT_RAMP 0x13
#define LM3697_CTRL_A_B_RAMP_CFG 0x14
#define LM3697_CTRL_A_B_BRT_CFG 0x16
#define LM3697_CTRL_A_FS_CURR_CFG 0x17
#define LM3697_CTRL_B_FS_CURR_CFG 0x18
#define LM3697_PWM_CFG 0x1c
#define LM3697_CTRL_A_BRT_LSB 0x20
#define LM3697_CTRL_A_BRT_MSB 0x21
#define LM3697_CTRL_B_BRT_LSB 0x22
#define LM3697_CTRL_B_BRT_MSB 0x23
#define LM3697_CTRL_ENABLE 0x24
#define LM3697_SW_RESET BIT(0)
#define LM3697_CTRL_A_EN BIT(0)
#define LM3697_CTRL_B_EN BIT(1)
#define LM3697_CTRL_A_B_EN (LM3697_CTRL_A_EN | LM3697_CTRL_B_EN)
#define LM3697_MAX_LED_STRINGS 3
#define LM3697_CONTROL_A 0
#define LM3697_CONTROL_B 1
#define LM3697_MAX_CONTROL_BANKS 2
/**
* struct lm3697_led -
* @hvled_strings: Array of LED strings associated with a control bank
* @label: LED label
* @led_dev: LED class device
* @priv: Pointer to the device struct
* @lmu_data: Register and setting values for common code
* @control_bank: Control bank the LED is associated to. 0 is control bank A
* 1 is control bank B
*/
struct lm3697_led {
u32 hvled_strings[LM3697_MAX_LED_STRINGS];
char label[LED_MAX_NAME_SIZE];
struct led_classdev led_dev;
struct lm3697 *priv;
struct ti_lmu_bank lmu_data;
int control_bank;
int enabled;
int num_leds;
};
/**
* struct lm3697 -
* @enable_gpio: Hardware enable gpio
* @regulator: LED supply regulator pointer
* @client: Pointer to the I2C client
* @regmap: Devices register map
* @dev: Pointer to the devices device struct
* @lock: Lock for reading/writing the device
* @leds: Array of LED strings
*/
struct lm3697 {
struct gpio_desc *enable_gpio;
struct regulator *regulator;
struct i2c_client *client;
struct regmap *regmap;
struct device *dev;
struct mutex lock;
int bank_cfg;
struct lm3697_led leds[];
};
static const struct reg_default lm3697_reg_defs[] = {
{LM3697_OUTPUT_CONFIG, 0x6},
{LM3697_CTRL_A_RAMP, 0x0},
{LM3697_CTRL_B_RAMP, 0x0},
{LM3697_CTRL_A_B_RT_RAMP, 0x0},
{LM3697_CTRL_A_B_RAMP_CFG, 0x0},
{LM3697_CTRL_A_B_BRT_CFG, 0x0},
{LM3697_CTRL_A_FS_CURR_CFG, 0x13},
{LM3697_CTRL_B_FS_CURR_CFG, 0x13},
{LM3697_PWM_CFG, 0xc},
{LM3697_CTRL_A_BRT_LSB, 0x0},
{LM3697_CTRL_A_BRT_MSB, 0x0},
{LM3697_CTRL_B_BRT_LSB, 0x0},
{LM3697_CTRL_B_BRT_MSB, 0x0},
{LM3697_CTRL_ENABLE, 0x0},
};
static const struct regmap_config lm3697_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = LM3697_CTRL_ENABLE,
.reg_defaults = lm3697_reg_defs,
.num_reg_defaults = ARRAY_SIZE(lm3697_reg_defs),
.cache_type = REGCACHE_FLAT,
};
static int lm3697_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brt_val)
{
struct lm3697_led *led = container_of(led_cdev, struct lm3697_led,
led_dev);
int ctrl_en_val = (1 << led->control_bank);
int ret;
mutex_lock(&led->priv->lock);
if (brt_val == LED_OFF) {
ret = regmap_update_bits(led->priv->regmap, LM3697_CTRL_ENABLE,
ctrl_en_val, ~ctrl_en_val);
if (ret) {
dev_err(&led->priv->client->dev, "Cannot write ctrl register\n");
goto brightness_out;
}
led->enabled = LED_OFF;
} else {
ret = ti_lmu_common_set_brightness(&led->lmu_data, brt_val);
if (ret) {
dev_err(&led->priv->client->dev,
"Cannot write brightness\n");
goto brightness_out;
}
if (!led->enabled) {
ret = regmap_update_bits(led->priv->regmap,
LM3697_CTRL_ENABLE,
ctrl_en_val, ctrl_en_val);
if (ret) {
dev_err(&led->priv->client->dev,
"Cannot enable the device\n");
goto brightness_out;
}
led->enabled = brt_val;
}
}
brightness_out:
mutex_unlock(&led->priv->lock);
return ret;
}
static int lm3697_init(struct lm3697 *priv)
{
struct lm3697_led *led;
int i, ret;
if (priv->enable_gpio) {
gpiod_direction_output(priv->enable_gpio, 1);
} else {
ret = regmap_write(priv->regmap, LM3697_RESET, LM3697_SW_RESET);
if (ret) {
dev_err(&priv->client->dev, "Cannot reset the device\n");
goto out;
}
}
ret = regmap_write(priv->regmap, LM3697_CTRL_ENABLE, 0x0);
if (ret) {
dev_err(&priv->client->dev, "Cannot write ctrl enable\n");
goto out;
}
ret = regmap_write(priv->regmap, LM3697_OUTPUT_CONFIG, priv->bank_cfg);
if (ret)
dev_err(&priv->client->dev, "Cannot write OUTPUT config\n");
for (i = 0; i < LM3697_MAX_CONTROL_BANKS; i++) {
led = &priv->leds[i];
ret = ti_lmu_common_set_ramp(&led->lmu_data);
if (ret)
dev_err(&priv->client->dev, "Setting the ramp rate failed\n");
}
out:
return ret;
}
static int lm3697_probe_dt(struct lm3697 *priv)
{
struct fwnode_handle *child = NULL;
struct lm3697_led *led;
const char *name;
int control_bank;
size_t i = 0;
int ret = -EINVAL;
int j;
priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
"enable", GPIOD_OUT_LOW);
if (IS_ERR(priv->enable_gpio)) {
ret = PTR_ERR(priv->enable_gpio);
dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
ret);
return ret;
}
priv->regulator = devm_regulator_get(&priv->client->dev, "vled");
if (IS_ERR(priv->regulator))
priv->regulator = NULL;
device_for_each_child_node(priv->dev, child) {
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 > LM3697_CONTROL_B) {
dev_err(&priv->client->dev, "reg property is invalid\n");
ret = -EINVAL;
fwnode_handle_put(child);
goto child_out;
}
led = &priv->leds[i];
ret = ti_lmu_common_get_brt_res(&priv->client->dev,
child, &led->lmu_data);
if (ret)
dev_warn(&priv->client->dev, "brightness resolution property missing\n");
led->control_bank = control_bank;
led->lmu_data.regmap = priv->regmap;
led->lmu_data.runtime_ramp_reg = LM3697_CTRL_A_RAMP +
control_bank;
led->lmu_data.msb_brightness_reg = LM3697_CTRL_A_BRT_MSB +
led->control_bank * 2;
led->lmu_data.lsb_brightness_reg = LM3697_CTRL_A_BRT_LSB +
led->control_bank * 2;
led->num_leds = fwnode_property_read_u32_array(child,
"led-sources",
NULL, 0);
if (led->num_leds > LM3697_MAX_LED_STRINGS) {
dev_err(&priv->client->dev, "To many LED strings defined\n");
continue;
}
ret = fwnode_property_read_u32_array(child, "led-sources",
led->hvled_strings,
led->num_leds);
if (ret) {
dev_err(&priv->client->dev, "led-sources property missing\n");
fwnode_handle_put(child);
goto child_out;
}
for (j = 0; j < led->num_leds; j++)
priv->bank_cfg |=
(led->control_bank << led->hvled_strings[j]);
ret = ti_lmu_common_get_ramp_params(&priv->client->dev,
child, &led->lmu_data);
if (ret)
dev_warn(&priv->client->dev, "runtime-ramp properties missing\n");
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.max_brightness = led->lmu_data.max_brightness;
led->led_dev.brightness_set_blocking = lm3697_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;
}
i++;
}
child_out:
return ret;
}
static int lm3697_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lm3697 *led;
int count;
int ret;
count = device_get_child_node_count(&client->dev);
if (!count) {
dev_err(&client->dev, "LEDs are not defined in device tree!");
return -ENODEV;
}
led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
GFP_KERNEL);
if (!led)
return -ENOMEM;
mutex_init(&led->lock);
i2c_set_clientdata(client, led);
led->client = client;
led->dev = &client->dev;
led->regmap = devm_regmap_init_i2c(client, &lm3697_regmap_config);
if (IS_ERR(led->regmap)) {
ret = PTR_ERR(led->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
ret = lm3697_probe_dt(led);
if (ret)
return ret;
return lm3697_init(led);
}
static int lm3697_remove(struct i2c_client *client)
{
struct lm3697 *led = i2c_get_clientdata(client);
int ret;
ret = regmap_update_bits(led->regmap, LM3697_CTRL_ENABLE,
LM3697_CTRL_A_B_EN, 0);
if (ret) {
dev_err(&led->client->dev, "Failed to disable the device\n");
return ret;
}
if (led->enable_gpio)
gpiod_direction_output(led->enable_gpio, 0);
if (led->regulator) {
ret = regulator_disable(led->regulator);
if (ret)
dev_err(&led->client->dev,
"Failed to disable regulator\n");
}
mutex_destroy(&led->lock);
return 0;
}
static const struct i2c_device_id lm3697_id[] = {
{ "lm3697", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm3697_id);
static const struct of_device_id of_lm3697_leds_match[] = {
{ .compatible = "ti,lm3697", },
{},
};
MODULE_DEVICE_TABLE(of, of_lm3697_leds_match);
static struct i2c_driver lm3697_driver = {
.driver = {
.name = "lm3697",
.of_match_table = of_lm3697_leds_match,
},
.probe = lm3697_probe,
.remove = lm3697_remove,
.id_table = lm3697_id,
};
module_i2c_driver(lm3697_driver);
MODULE_DESCRIPTION("Texas Instruments LM3697 LED driver");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_LICENSE("GPL v2");
...@@ -64,7 +64,6 @@ static int max77650_led_probe(struct platform_device *pdev) ...@@ -64,7 +64,6 @@ static int max77650_led_probe(struct platform_device *pdev)
{ {
struct device_node *of_node, *child; struct device_node *of_node, *child;
struct max77650_led *leds, *led; struct max77650_led *leds, *led;
struct device *parent;
struct device *dev; struct device *dev;
struct regmap *map; struct regmap *map;
const char *label; const char *label;
...@@ -72,7 +71,6 @@ static int max77650_led_probe(struct platform_device *pdev) ...@@ -72,7 +71,6 @@ static int max77650_led_probe(struct platform_device *pdev)
u32 reg; u32 reg;
dev = &pdev->dev; dev = &pdev->dev;
parent = dev->parent;
of_node = dev->of_node; of_node = dev->of_node;
if (!of_node) if (!of_node)
......
...@@ -429,7 +429,7 @@ static int pca955x_probe(struct i2c_client *client, ...@@ -429,7 +429,7 @@ static int pca955x_probe(struct i2c_client *client,
int ngpios = 0; int ngpios = 0;
chip = &pca955x_chipdefs[id->driver_data]; chip = &pca955x_chipdefs[id->driver_data];
adapter = to_i2c_adapter(client->dev.parent); adapter = client->adapter;
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
if (!pdata) { if (!pdata) {
pdata = pca955x_get_pdata(client, chip); pdata = pca955x_get_pdata(client, chip);
......
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Christian Mauderer <oss@c-mauderer.de>
/*
* The driver supports controllers with a very simple SPI protocol:
* - one LED is controlled by a single byte on MOSI
* - the value of the byte gives the brightness between two values (lowest to
* highest)
* - no return value is necessary (no MISO signal)
*
* The value for minimum and maximum brightness depends on the device
* (compatible string).
*
* Supported devices:
* - "ubnt,acb-spi-led": Microcontroller (SONiX 8F26E611LA) based device used
* for example in Ubiquiti airCube ISP. Reverse engineered protocol for this
* controller:
* * Higher two bits set a mode. Lower six bits are a parameter.
* * Mode: 00 -> set brightness between 0x00 (min) and 0x3F (max)
* * Mode: 01 -> pulsing pattern (min -> max -> min) with an interval. From
* some tests, the period is about (50ms + 102ms * parameter). There is a
* slightly different pattern starting from 0x10 (longer gap between the
* pulses) but the time still follows that calculation.
* * Mode: 10 -> same as 01 but with only a ramp from min to max. Again a
* slight jump in the pattern at 0x10.
* * Mode: 11 -> blinking (off -> 25% -> off -> 25% -> ...) with a period of
* (105ms * parameter)
* NOTE: This driver currently only supports mode 00.
*/
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/mutex.h>
#include <uapi/linux/uleds.h>
struct spi_byte_chipdef {
/* SPI byte that will be send to switch the LED off */
u8 off_value;
/* SPI byte that will be send to switch the LED to maximum brightness */
u8 max_value;
};
struct spi_byte_led {
struct led_classdev ldev;
struct spi_device *spi;
char name[LED_MAX_NAME_SIZE];
struct mutex mutex;
const struct spi_byte_chipdef *cdef;
};
static const struct spi_byte_chipdef ubnt_acb_spi_led_cdef = {
.off_value = 0x0,
.max_value = 0x3F,
};
static const struct of_device_id spi_byte_dt_ids[] = {
{ .compatible = "ubnt,acb-spi-led", .data = &ubnt_acb_spi_led_cdef },
{},
};
MODULE_DEVICE_TABLE(of, spi_byte_dt_ids);
static int spi_byte_brightness_set_blocking(struct led_classdev *dev,
enum led_brightness brightness)
{
struct spi_byte_led *led = container_of(dev, struct spi_byte_led, ldev);
u8 value;
int ret;
value = (u8) brightness + led->cdef->off_value;
mutex_lock(&led->mutex);
ret = spi_write(led->spi, &value, sizeof(value));
mutex_unlock(&led->mutex);
return ret;
}
static int spi_byte_probe(struct spi_device *spi)
{
const struct of_device_id *of_dev_id;
struct device_node *child;
struct device *dev = &spi->dev;
struct spi_byte_led *led;
const char *name = "leds-spi-byte::";
const char *state;
int ret;
of_dev_id = of_match_device(spi_byte_dt_ids, dev);
if (!of_dev_id)
return -EINVAL;
if (of_get_child_count(dev->of_node) != 1) {
dev_err(dev, "Device must have exactly one LED sub-node.");
return -EINVAL;
}
child = of_get_next_child(dev->of_node, NULL);
led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
of_property_read_string(child, "label", &name);
strlcpy(led->name, name, sizeof(led->name));
led->spi = spi;
mutex_init(&led->mutex);
led->cdef = of_dev_id->data;
led->ldev.name = led->name;
led->ldev.brightness = LED_OFF;
led->ldev.max_brightness = led->cdef->max_value - led->cdef->off_value;
led->ldev.brightness_set_blocking = spi_byte_brightness_set_blocking;
state = of_get_property(child, "default-state", NULL);
if (state) {
if (!strcmp(state, "on")) {
led->ldev.brightness = led->ldev.max_brightness;
} else if (strcmp(state, "off")) {
/* all other cases except "off" */
dev_err(dev, "default-state can only be 'on' or 'off'");
return -EINVAL;
}
}
spi_byte_brightness_set_blocking(&led->ldev,
led->ldev.brightness);
ret = devm_led_classdev_register(&spi->dev, &led->ldev);
if (ret) {
mutex_destroy(&led->mutex);
return ret;
}
spi_set_drvdata(spi, led);
return 0;
}
static int spi_byte_remove(struct spi_device *spi)
{
struct spi_byte_led *led = spi_get_drvdata(spi);
mutex_destroy(&led->mutex);
return 0;
}
static struct spi_driver spi_byte_driver = {
.probe = spi_byte_probe,
.remove = spi_byte_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = spi_byte_dt_ids,
},
};
module_spi_driver(spi_byte_driver);
MODULE_AUTHOR("Christian Mauderer <oss@c-mauderer.de>");
MODULE_DESCRIPTION("single byte SPI LED driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:leds-spi-byte");
...@@ -758,7 +758,7 @@ static int tca6507_probe(struct i2c_client *client, ...@@ -758,7 +758,7 @@ static int tca6507_probe(struct i2c_client *client,
int err; int err;
int i = 0; int i = 0;
adapter = to_i2c_adapter(client->dev.parent); adapter = client->adapter;
pdata = dev_get_platdata(&client->dev); pdata = dev_get_platdata(&client->dev);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
......
// SPDX-License-Identifier: GPL-2.0
// Copyright 2015 Texas Instruments
// Copyright 2018 Sebastian Reichel
// Copyright 2018 Pavel Machek <pavel@ucw.cz>
// TI LMU LED common framework, based on previous work from
// Milo Kim <milo.kim@ti.com>
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/of_device.h>
#include <linux/leds-ti-lmu-common.h>
const static int ramp_table[16] = {2048, 262000, 524000, 1049000, 2090000,
4194000, 8389000, 16780000, 33550000, 41940000,
50330000, 58720000, 67110000, 83880000,
100660000, 117440000};
static int ti_lmu_common_update_brightness(struct ti_lmu_bank *lmu_bank,
int brightness)
{
struct regmap *regmap = lmu_bank->regmap;
u8 reg, val;
int ret;
/*
* Brightness register update
*
* 11 bit dimming: update LSB bits and write MSB byte.
* MSB brightness should be shifted.
* 8 bit dimming: write MSB byte.
*/
if (lmu_bank->max_brightness == MAX_BRIGHTNESS_11BIT) {
reg = lmu_bank->lsb_brightness_reg;
ret = regmap_update_bits(regmap, reg,
LMU_11BIT_LSB_MASK,
brightness);
if (ret)
return ret;
val = brightness >> LMU_11BIT_MSB_SHIFT;
} else {
val = brightness;
}
reg = lmu_bank->msb_brightness_reg;
return regmap_write(regmap, reg, val);
}
int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness)
{
return ti_lmu_common_update_brightness(lmu_bank, brightness);
}
EXPORT_SYMBOL(ti_lmu_common_set_brightness);
static int ti_lmu_common_convert_ramp_to_index(unsigned int usec)
{
int size = ARRAY_SIZE(ramp_table);
int i;
if (usec <= ramp_table[0])
return 0;
if (usec > ramp_table[size - 1])
return size - 1;
for (i = 1; i < size; i++) {
if (usec == ramp_table[i])
return i;
/* Find an approximate index by looking up the table */
if (usec > ramp_table[i - 1] && usec < ramp_table[i]) {
if (usec - ramp_table[i - 1] < ramp_table[i] - usec)
return i - 1;
else
return i;
}
}
return -EINVAL;
}
int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank)
{
struct regmap *regmap = lmu_bank->regmap;
u8 ramp, ramp_up, ramp_down;
if (lmu_bank->ramp_up_usec == 0 && lmu_bank->ramp_down_usec == 0) {
ramp_up = 0;
ramp_down = 0;
} else {
ramp_up = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_up_usec);
ramp_down = ti_lmu_common_convert_ramp_to_index(lmu_bank->ramp_down_usec);
}
if (ramp_up < 0 || ramp_down < 0)
return -EINVAL;
ramp = (ramp_up << 4) | ramp_down;
return regmap_write(regmap, lmu_bank->runtime_ramp_reg, ramp);
}
EXPORT_SYMBOL(ti_lmu_common_set_ramp);
int ti_lmu_common_get_ramp_params(struct device *dev,
struct fwnode_handle *child,
struct ti_lmu_bank *lmu_data)
{
int ret;
ret = fwnode_property_read_u32(child, "ramp-up-us",
&lmu_data->ramp_up_usec);
if (ret)
dev_warn(dev, "ramp-up-us property missing\n");
ret = fwnode_property_read_u32(child, "ramp-down-us",
&lmu_data->ramp_down_usec);
if (ret)
dev_warn(dev, "ramp-down-us property missing\n");
return 0;
}
EXPORT_SYMBOL(ti_lmu_common_get_ramp_params);
int ti_lmu_common_get_brt_res(struct device *dev, struct fwnode_handle *child,
struct ti_lmu_bank *lmu_data)
{
int ret;
ret = device_property_read_u32(dev, "ti,brightness-resolution",
&lmu_data->max_brightness);
if (ret)
ret = fwnode_property_read_u32(child,
"ti,brightness-resolution",
&lmu_data->max_brightness);
if (lmu_data->max_brightness <= 0) {
lmu_data->max_brightness = MAX_BRIGHTNESS_8BIT;
return ret;
}
if (lmu_data->max_brightness > MAX_BRIGHTNESS_11BIT)
lmu_data->max_brightness = MAX_BRIGHTNESS_11BIT;
return 0;
}
EXPORT_SYMBOL(ti_lmu_common_get_brt_res);
MODULE_DESCRIPTION("TI LMU common LED framework");
MODULE_AUTHOR("Sebastian Reichel");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("ti-lmu-led-common");
...@@ -15,7 +15,7 @@ config LEDS_TRIGGER_TIMER ...@@ -15,7 +15,7 @@ config LEDS_TRIGGER_TIMER
This allows LEDs to be controlled by a programmable timer This allows LEDs to be controlled by a programmable timer
via sysfs. Some LED hardware can be programmed to start via sysfs. Some LED hardware can be programmed to start
blinking the LED without any further software interaction. blinking the LED without any further software interaction.
For more details read Documentation/leds/leds-class.txt. For more details read Documentation/leds/leds-class.rst.
If unsure, say Y. If unsure, say Y.
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// LED Kernel Transient Trigger // LED Kernel Transient Trigger
// //
// Transient trigger allows one shot timer activation. Please refer to // Transient trigger allows one shot timer activation. Please refer to
// Documentation/leds/ledtrig-transient.txt for details // Documentation/leds/ledtrig-transient.rst for details
// Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com> // Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
// //
// Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's // Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
......
...@@ -1336,9 +1336,8 @@ config MFD_TI_LMU ...@@ -1336,9 +1336,8 @@ config MFD_TI_LMU
select REGMAP_I2C select REGMAP_I2C
help help
Say yes here to enable support for TI LMU chips. Say yes here to enable support for TI LMU chips.
TI LMU MFD supports LM3532, LM3631, LM3632, LM3633, LM3695 and
TI LMU MFD supports LM3532, LM3631, LM3632, LM3633, LM3695 and LM3697. LM36274. It consists of backlight, LED and regulator driver.
It consists of backlight, LED and regulator driver.
It provides consistent device controls for lighting functions. It provides consistent device controls for lighting functions.
config MFD_OMAP_USB_HOST config MFD_OMAP_USB_HOST
......
...@@ -108,17 +108,14 @@ static const struct mfd_cell lm3695_devices[] = { ...@@ -108,17 +108,14 @@ static const struct mfd_cell lm3695_devices[] = {
}, },
}; };
static const struct mfd_cell lm3697_devices[] = { static const struct mfd_cell lm36274_devices[] = {
LM363X_REGULATOR(LM36274_BOOST),
LM363X_REGULATOR(LM36274_LDO_POS),
LM363X_REGULATOR(LM36274_LDO_NEG),
{ {
.name = "ti-lmu-backlight", .name = "lm36274-leds",
.id = LM3697, .id = LM36274,
.of_compatible = "ti,lm3697-backlight", .of_compatible = "ti,lm36274-backlight",
},
/* Monitoring driver for open/short circuit detection */
{
.name = "ti-lmu-fault-monitor",
.id = LM3697,
.of_compatible = "ti,lm3697-fault-monitor",
}, },
}; };
...@@ -134,7 +131,7 @@ TI_LMU_DATA(lm3631, LM3631_MAX_REG); ...@@ -134,7 +131,7 @@ TI_LMU_DATA(lm3631, LM3631_MAX_REG);
TI_LMU_DATA(lm3632, LM3632_MAX_REG); TI_LMU_DATA(lm3632, LM3632_MAX_REG);
TI_LMU_DATA(lm3633, LM3633_MAX_REG); TI_LMU_DATA(lm3633, LM3633_MAX_REG);
TI_LMU_DATA(lm3695, LM3695_MAX_REG); TI_LMU_DATA(lm3695, LM3695_MAX_REG);
TI_LMU_DATA(lm3697, LM3697_MAX_REG); TI_LMU_DATA(lm36274, LM36274_MAX_REG);
static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id) static int ti_lmu_probe(struct i2c_client *cl, const struct i2c_device_id *id)
{ {
...@@ -203,7 +200,7 @@ static const struct of_device_id ti_lmu_of_match[] = { ...@@ -203,7 +200,7 @@ static const struct of_device_id ti_lmu_of_match[] = {
{ .compatible = "ti,lm3632", .data = &lm3632_data }, { .compatible = "ti,lm3632", .data = &lm3632_data },
{ .compatible = "ti,lm3633", .data = &lm3633_data }, { .compatible = "ti,lm3633", .data = &lm3633_data },
{ .compatible = "ti,lm3695", .data = &lm3695_data }, { .compatible = "ti,lm3695", .data = &lm3695_data },
{ .compatible = "ti,lm3697", .data = &lm3697_data }, { .compatible = "ti,lm36274", .data = &lm36274_data },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, ti_lmu_of_match); MODULE_DEVICE_TABLE(of, ti_lmu_of_match);
...@@ -213,7 +210,7 @@ static const struct i2c_device_id ti_lmu_ids[] = { ...@@ -213,7 +210,7 @@ static const struct i2c_device_id ti_lmu_ids[] = {
{ "lm3632", LM3632 }, { "lm3632", LM3632 },
{ "lm3633", LM3633 }, { "lm3633", LM3633 },
{ "lm3695", LM3695 }, { "lm3695", LM3695 },
{ "lm3697", LM3697 }, { "lm36274", LM36274 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, ti_lmu_ids); MODULE_DEVICE_TABLE(i2c, ti_lmu_ids);
......
...@@ -364,7 +364,7 @@ config REGULATOR_LM363X ...@@ -364,7 +364,7 @@ config REGULATOR_LM363X
tristate "TI LM363X voltage regulators" tristate "TI LM363X voltage regulators"
depends on MFD_TI_LMU depends on MFD_TI_LMU
help help
This driver supports LM3631 and LM3632 voltage regulators for This driver supports LM3631, LM3632 and LM36274 voltage regulators for
the LCD bias. the LCD bias.
One boost output voltage is configurable and always on. One boost output voltage is configurable and always on.
Other LDOs are used for the display module. Other LDOs are used for the display module.
......
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
#define LM3632_VBOOST_MIN 4500000 #define LM3632_VBOOST_MIN 4500000
#define LM3632_VLDO_MIN 4000000 #define LM3632_VLDO_MIN 4000000
/* LM36274 */
#define LM36274_BOOST_VSEL_MAX 0x3f
#define LM36274_LDO_VSEL_MAX 0x34
#define LM36274_VOLTAGE_MIN 4000000
/* Common */ /* Common */
#define LM363X_STEP_50mV 50000 #define LM363X_STEP_50mV 50000
#define LM363X_STEP_500mV 500000 #define LM363X_STEP_500mV 500000
...@@ -214,6 +219,51 @@ static const struct regulator_desc lm363x_regulator_desc[] = { ...@@ -214,6 +219,51 @@ static const struct regulator_desc lm363x_regulator_desc[] = {
.enable_reg = LM3632_REG_BIAS_CONFIG, .enable_reg = LM3632_REG_BIAS_CONFIG,
.enable_mask = LM3632_EN_VNEG_MASK, .enable_mask = LM3632_EN_VNEG_MASK,
}, },
/* LM36274 */
{
.name = "vboost",
.of_match = "vboost",
.id = LM36274_BOOST,
.ops = &lm363x_boost_voltage_table_ops,
.n_voltages = LM36274_BOOST_VSEL_MAX,
.min_uV = LM36274_VOLTAGE_MIN,
.uV_step = LM363X_STEP_50mV,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LM36274_REG_VOUT_BOOST,
.vsel_mask = LM36274_VOUT_MASK,
},
{
.name = "ldo_vpos",
.of_match = "vpos",
.id = LM36274_LDO_POS,
.ops = &lm363x_regulator_voltage_table_ops,
.n_voltages = LM36274_LDO_VSEL_MAX,
.min_uV = LM36274_VOLTAGE_MIN,
.uV_step = LM363X_STEP_50mV,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LM36274_REG_VOUT_POS,
.vsel_mask = LM36274_VOUT_MASK,
.enable_reg = LM36274_REG_BIAS_CONFIG_1,
.enable_mask = LM36274_EN_VPOS_MASK,
},
{
.name = "ldo_vneg",
.of_match = "vneg",
.id = LM36274_LDO_NEG,
.ops = &lm363x_regulator_voltage_table_ops,
.n_voltages = LM36274_LDO_VSEL_MAX,
.min_uV = LM36274_VOLTAGE_MIN,
.uV_step = LM363X_STEP_50mV,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.vsel_reg = LM36274_REG_VOUT_NEG,
.vsel_mask = LM36274_VOUT_MASK,
.enable_reg = LM36274_REG_BIAS_CONFIG_1,
.enable_mask = LM36274_EN_VNEG_MASK,
},
}; };
static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id) static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
...@@ -226,9 +276,11 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, ...@@ -226,9 +276,11 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
*/ */
switch (id) { switch (id) {
case LM3632_LDO_POS: case LM3632_LDO_POS:
case LM36274_LDO_POS:
return gpiod_get_index_optional(dev, "enable", 0, return gpiod_get_index_optional(dev, "enable", 0,
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
case LM3632_LDO_NEG: case LM3632_LDO_NEG:
case LM36274_LDO_NEG:
return gpiod_get_index_optional(dev, "enable", 1, return gpiod_get_index_optional(dev, "enable", 1,
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
default: default:
...@@ -236,6 +288,27 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, ...@@ -236,6 +288,27 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
} }
} }
static int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
{
int ext_en_mask = 0;
switch (id) {
case LM3632_LDO_POS:
case LM3632_LDO_NEG:
ext_en_mask = LM3632_EXT_EN_MASK;
break;
case LM36274_LDO_POS:
case LM36274_LDO_NEG:
ext_en_mask = LM36274_EXT_EN_MASK;
break;
default:
return -ENODEV;
}
return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
ext_en_mask, ext_en_mask);
}
static int lm363x_regulator_probe(struct platform_device *pdev) static int lm363x_regulator_probe(struct platform_device *pdev)
{ {
struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent); struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
...@@ -260,10 +333,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev) ...@@ -260,10 +333,7 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
if (gpiod) { if (gpiod) {
cfg.ena_gpiod = gpiod; cfg.ena_gpiod = gpiod;
ret = lm363x_regulator_set_ext_en(regmap, id);
ret = regmap_update_bits(regmap, LM3632_REG_BIAS_CONFIG,
LM3632_EXT_EN_MASK,
LM3632_EXT_EN_MASK);
if (ret) { if (ret) {
gpiod_put(gpiod); gpiod_put(gpiod);
dev_err(dev, "External pin err: %d\n", ret); dev_err(dev, "External pin err: %d\n", ret);
......
/* SPDX-License-Identifier: GPL-2.0 */
// TI LMU Common Core
// Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
#ifndef _TI_LMU_COMMON_H_
#define _TI_LMU_COMMON_H_
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <uapi/linux/uleds.h>
#define LMU_11BIT_LSB_MASK (BIT(0) | BIT(1) | BIT(2))
#define LMU_11BIT_MSB_SHIFT 3
#define MAX_BRIGHTNESS_8BIT 255
#define MAX_BRIGHTNESS_11BIT 2047
struct ti_lmu_bank {
struct regmap *regmap;
int max_brightness;
u8 lsb_brightness_reg;
u8 msb_brightness_reg;
u8 runtime_ramp_reg;
u32 ramp_up_usec;
u32 ramp_down_usec;
};
int ti_lmu_common_set_brightness(struct ti_lmu_bank *lmu_bank, int brightness);
int ti_lmu_common_set_ramp(struct ti_lmu_bank *lmu_bank);
int ti_lmu_common_get_ramp_params(struct device *dev,
struct fwnode_handle *child,
struct ti_lmu_bank *lmu_data);
int ti_lmu_common_get_brt_res(struct device *dev, struct fwnode_handle *child,
struct ti_lmu_bank *lmu_data);
#endif /* _TI_LMU_COMMON_H_ */
...@@ -187,47 +187,26 @@ ...@@ -187,47 +187,26 @@
#define LM3695_MAX_REG 0x14 #define LM3695_MAX_REG 0x14
/* LM3697 */ /* LM36274 */
#define LM3697_REG_HVLED_OUTPUT_CFG 0x10 #define LM36274_REG_REV 0x01
#define LM3697_HVLED1_CFG_MASK BIT(0) #define LM36274_REG_BL_CFG_1 0x02
#define LM3697_HVLED2_CFG_MASK BIT(1) #define LM36274_REG_BL_CFG_2 0x03
#define LM3697_HVLED3_CFG_MASK BIT(2) #define LM36274_REG_BRT_LSB 0x04
#define LM3697_HVLED1_CFG_SHIFT 0 #define LM36274_REG_BRT_MSB 0x05
#define LM3697_HVLED2_CFG_SHIFT 1 #define LM36274_REG_BL_EN 0x08
#define LM3697_HVLED3_CFG_SHIFT 2
#define LM36274_REG_BIAS_CONFIG_1 0x09
#define LM36274_EXT_EN_MASK BIT(0)
#define LM36274_EN_VNEG_MASK BIT(1)
#define LM36274_EN_VPOS_MASK BIT(2)
#define LM36274_REG_BIAS_CONFIG_2 0x0a
#define LM36274_REG_BIAS_CONFIG_3 0x0b
#define LM36274_REG_VOUT_BOOST 0x0c
#define LM36274_REG_VOUT_POS 0x0d
#define LM36274_REG_VOUT_NEG 0x0e
#define LM36274_VOUT_MASK 0x3F
#define LM36274_MAX_REG 0x13
#define LM3697_REG_BL0_RAMP 0x11
#define LM3697_REG_BL1_RAMP 0x12
#define LM3697_RAMPUP_MASK 0xF0
#define LM3697_RAMPUP_SHIFT 4
#define LM3697_RAMPDN_MASK 0x0F
#define LM3697_RAMPDN_SHIFT 0
#define LM3697_REG_RAMP_CONF 0x14
#define LM3697_RAMP_MASK 0x0F
#define LM3697_RAMP_EACH 0x05
#define LM3697_REG_PWM_CFG 0x1C
#define LM3697_PWM_A_MASK BIT(0)
#define LM3697_PWM_B_MASK BIT(1)
#define LM3697_REG_IMAX_A 0x17
#define LM3697_REG_IMAX_B 0x18
#define LM3697_REG_FEEDBACK_ENABLE 0x19
#define LM3697_REG_BRT_A_LSB 0x20
#define LM3697_REG_BRT_A_MSB 0x21
#define LM3697_REG_BRT_B_LSB 0x22
#define LM3697_REG_BRT_B_MSB 0x23
#define LM3697_REG_ENABLE 0x24
#define LM3697_REG_OPEN_FAULT_STATUS 0xB0
#define LM3697_REG_SHORT_FAULT_STATUS 0xB2
#define LM3697_REG_MONITOR_ENABLE 0xB4
#define LM3697_MAX_REG 0xB4
#endif #endif
...@@ -23,7 +23,7 @@ enum ti_lmu_id { ...@@ -23,7 +23,7 @@ enum ti_lmu_id {
LM3632, LM3632,
LM3633, LM3633,
LM3695, LM3695,
LM3697, LM36274,
LMU_MAX_ID, LMU_MAX_ID,
}; };
...@@ -65,6 +65,9 @@ enum lm363x_regulator_id { ...@@ -65,6 +65,9 @@ enum lm363x_regulator_id {
LM3632_BOOST, /* Boost output */ LM3632_BOOST, /* Boost output */
LM3632_LDO_POS, /* Positive display bias output */ LM3632_LDO_POS, /* Positive display bias output */
LM3632_LDO_NEG, /* Negative display bias output */ LM3632_LDO_NEG, /* Negative display bias output */
LM36274_BOOST, /* Boost output */
LM36274_LDO_POS, /* Positive display bias output */
LM36274_LDO_NEG, /* Negative display bias output */
}; };
/** /**
......
...@@ -906,7 +906,7 @@ config NETFILTER_XT_TARGET_LED ...@@ -906,7 +906,7 @@ config NETFILTER_XT_TARGET_LED
echo netfilter-ssh > /sys/class/leds/<ledname>/trigger echo netfilter-ssh > /sys/class/leds/<ledname>/trigger
For more information on the LEDs available on your system, see For more information on the LEDs available on your system, see
Documentation/leds/leds-class.txt Documentation/leds/leds-class.rst
config NETFILTER_XT_TARGET_LOG config NETFILTER_XT_TARGET_LOG
tristate "LOG target support" tristate "LOG target support"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment