N900 Hardware LED

(Yes, sysfs is stable, no, you do not need to wait between accessing /sys. Driver takes care of delays.)
(Software: show sysfs ls -l)
 
(One intermediate revision not shown)
Line 7: Line 7:
* <code>disabled</code>: The channel is disabled - not running
* <code>disabled</code>: The channel is disabled - not running
* <code>load</code>: In that state, there are two more files in that directory:  
* <code>load</code>: In that state, there are two more files in that directory:  
-
** engine1_LEDs is in the form "0000rgb00" (9 digits, "1" or "0"), where rgb control which LEDs should participate. The 6 "0" in the above pattern correspond to the 6 kbd white LEDs controlled by MCE via engine3, so readout of engine3_leds gives 111100011 ;-)
+
** engine1_LEDs is in the form "0000bgr00" (9 digits, "1" or "0"), where rgb control which LEDs should participate. The 6 "0" in the above pattern correspond to the 6 kbd white LEDs controlled by MCE via engine3, so readout of engine3_leds gives 111100011 ;-)
** engine1_load accepts a string as specified above (e.g. 9d804000427f0d7f7f007f0042000000). LP5523 has an absolute storage of 96 steps a 16bits, which can dynamically partitioned between the three engines. (Supports 32-96 steps per engine, dynamically-assigned, alas the lp5523.ko driver is braindamaged and doesn't support more than 16 instructions per engine)
** engine1_load accepts a string as specified above (e.g. 9d804000427f0d7f7f007f0042000000). LP5523 has an absolute storage of 96 steps a 16bits, which can dynamically partitioned between the three engines. (Supports 32-96 steps per engine, dynamically-assigned, alas the lp5523.ko driver is braindamaged and doesn't support more than 16 instructions per engine)
After that, when the state is changed to "run", the program will be ran by the controller.  
After that, when the state is changed to "run", the program will be ran by the controller.  
Line 35: Line 35:
==Software==
==Software==
-
 
+
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# echo load >engine1_mode
 +
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# echo load >engine2_mode
 +
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# echo load >engine3_mode
 +
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# ls -l
 +
insgesamt 0
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 bus -> ../../../../bus/i2c
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 driver -> ../../../../bus/i2c/drivers/lp5523
 +
-rw-rw-rw- 1 root root 4096 2022-12-15 16:34 engine1_leds
 +
--w--w--w- 1 root root 4096 2022-12-15 16:34 engine1_load
 +
-rw-rw-rw- 1 root root 4096 2022-12-15 16:34 engine1_mode
 +
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine2_leds
 +
--w--w--w- 1 root root 4096 2022-12-15 16:36 engine2_load
 +
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine2_mode
 +
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine3_leds
 +
--w--w--w- 1 root root 4096 2022-12-15 16:36 engine3_load
 +
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine3_mode
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:b -> ../../../leds/lp5523:b
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:g -> ../../../leds/lp5523:g
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb1 -> ../../../leds/lp5523:kb1
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb2 -> ../../../leds/lp5523:kb2
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb3 -> ../../../leds/lp5523:kb3
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb4 -> ../../../leds/lp5523:kb4
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb5 -> ../../../leds/lp5523:kb5
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb6 -> ../../../leds/lp5523:kb6
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:r -> ../../../leds/lp5523:r
 +
-r--r--r-- 1 root root 4096 2022-12-15 16:31 modalias
 +
-r--r--r-- 1 root root 4096 2022-12-15 16:31 name
 +
drwxr-xr-x 2 root root    0 2022-12-15 16:31 power
 +
-r--r--r-- 1 root root 4096 2022-12-15 16:31 selftest
 +
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 subsystem -> ../../../../bus/i2c
 +
-rw-r--r-- 1 root root 4096 2022-12-15 16:31 uevent
== References ==
== References ==

Latest revision as of 16:00, 15 December 2022

[edit] Hardware

The N900 has LP5523 [1] [2], which has 3 engines like LP5521 (compatible though augmented instruction set) but can drive 9 LEDs via a multiplexer which maps each LED to one of the 3 engines. A LED also can be unassigned to any engine, in which case you can control it by writing to the corresponding brightness sysnode) which handles the keyboard and notification LED. (not the flash LEDs and red indicator light next to those, and also not the Infrared-LED used for CIR)

The controller can be programmed via "/sys/class/i2c-adapter/i2c-2/2-0032". In that directory there are three files corresponding to the three channels: engine1_mode, engine2_mode and engine3_mode. Each file "stores" one of run, load, disabled (it seems that there is another mode "direct" but it doesn't work)(direct mode requires explicit writes to PWM, current and multiplexing registers, which may not be supported in the code...):

  • run: The program runs
  • disabled: The channel is disabled - not running
  • load: In that state, there are two more files in that directory:
    • engine1_LEDs is in the form "0000bgr00" (9 digits, "1" or "0"), where rgb control which LEDs should participate. The 6 "0" in the above pattern correspond to the 6 kbd white LEDs controlled by MCE via engine3, so readout of engine3_leds gives 111100011 ;-)
    • engine1_load accepts a string as specified above (e.g. 9d804000427f0d7f7f007f0042000000). LP5523 has an absolute storage of 96 steps a 16bits, which can dynamically partitioned between the three engines. (Supports 32-96 steps per engine, dynamically-assigned, alas the lp5523.ko driver is braindamaged and doesn't support more than 16 instructions per engine)

After that, when the state is changed to "run", the program will be ran by the controller.

In order for the LEDs to work, the led_current of the appropriate LEDs need to be set to non-zero values. This is accomplished by writing to files LEDs:lp5523:[bgr]/led_current under the same directory. Default values from kernel module init are suitable.

Despite the line

#define LP5523_DEFAULT_CURRENT          50 /* microAmps */

suggesting different, the units in there are 0.1 mA (100 µA per step is correct). So the driver init default "50" for all LEDs is 5 mA, and mce seems to set current to 0.2 mA (value 2 in the led_current sysnode) for B and G, and either to 0.2 mA or 0.8 mA for R. Probably settings as high as 100 for 10 mA are safe for the RGB LED, higher values might destroy the LED. (yes, correct, the RGB could be damaged from heat if set to more than 10 mA on all 3 LEDs)


BEWARE!

register addr 0x3B: GPO
LP5523 has one General Purpose Output pin (GPO).
Status of the pin can be controlled with this register. Also,
INT pin can be configured to function as a GPO by setting
the bit INT_CONF. When INT is configured to function as
a GPO, output level is defined by the VDD voltage.
3B — Bit [2] INT_CONF
0 = INT pin is set to function as an interrupt pin (default).
1 = INT pin is configured to function as a GPO.

INT is routed directly to a SOC GPIO that is not designed to take voltages >1.8V ! So setting 0x3B:2 to 1 may fry your CPU

[edit] Software

IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# echo load >engine1_mode
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# echo load >engine2_mode
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# echo load >engine3_mode
IroN900:/sys/class/i2c-adapter/i2c-2/2-0032# ls -l
insgesamt 0
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 bus -> ../../../../bus/i2c
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 driver -> ../../../../bus/i2c/drivers/lp5523
-rw-rw-rw- 1 root root 4096 2022-12-15 16:34 engine1_leds
--w--w--w- 1 root root 4096 2022-12-15 16:34 engine1_load
-rw-rw-rw- 1 root root 4096 2022-12-15 16:34 engine1_mode
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine2_leds
--w--w--w- 1 root root 4096 2022-12-15 16:36 engine2_load
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine2_mode
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine3_leds
--w--w--w- 1 root root 4096 2022-12-15 16:36 engine3_load
-rw-rw-rw- 1 root root 4096 2022-12-15 16:36 engine3_mode
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:b -> ../../../leds/lp5523:b
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:g -> ../../../leds/lp5523:g
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb1 -> ../../../leds/lp5523:kb1
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb2 -> ../../../leds/lp5523:kb2
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb3 -> ../../../leds/lp5523:kb3
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb4 -> ../../../leds/lp5523:kb4
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb5 -> ../../../leds/lp5523:kb5
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:kb6 -> ../../../leds/lp5523:kb6
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 leds:lp5523:r -> ../../../leds/lp5523:r
-r--r--r-- 1 root root 4096 2022-12-15 16:31 modalias
-r--r--r-- 1 root root 4096 2022-12-15 16:31 name
drwxr-xr-x 2 root root    0 2022-12-15 16:31 power
-r--r--r-- 1 root root 4096 2022-12-15 16:31 selftest
lrwxrwxrwx 1 root root    0 2022-12-15 16:31 subsystem -> ../../../../bus/i2c
-rw-r--r-- 1 root root 4096 2022-12-15 16:31 uevent

[edit] References

also see LED_patterns of which this page is a "fork" without cleaning the original page, so now there are two versions with almost identical but slightly complementary info

Since beginning of 2012 a datasheet for LP5523 is available from TI: http://www.ti.com/product/lp5523 Direct link: http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=snvs550d&fileType=pdf

  1. http://www.national.com/pf/LP/LP5523.html
  2. http://mxr.maemo.org/fremantle/source/kernel/drivers/leds/leds-lp5523.c