Mailing List Archive

led: hw-trigger, global brightness and multi-colored leds
Hello,

on the Turris Omnia[1] the LEDs are controllable via an i2c device. Each
LED can be either in "manual mode" or in a mode I'd call "native mode"
which is the default. In this native mode the LED being on or off
depends on an input line that is controlled by another hardware. So a
LED signals for example activity on the WAN ethernet port without any
software intervention, but can be used as a normal LED, too, when in
"manual mode" where it can be switched on and off by a register write.

Another feature of the LED device is that there is a global brightness
register that influences all LED's brightness (if on) independent of the
operating mode.

Further the color of each LED can be set to an RGB triplet.

Now I wonder how to match these two features to the LED device model. Do
you have an idea? The first one is the most important one, as the
brightness and color can simply be ignored for a first driver, but I'd
rater not loose the "native mode".

Best regards
Uwe

[1] https://omnia.turris.cz/en/
Re: led: hw-trigger, global brightness and multi-colored leds [ In reply to ]
Hi!

> on the Turris Omnia[1] the LEDs are controllable via an i2c device. Each
> LED can be either in "manual mode" or in a mode I'd call "native mode"
> which is the default. In this native mode the LED being on or off
> depends on an input line that is controlled by another hardware. So a
> LED signals for example activity on the WAN ethernet port without any
> software intervention, but can be used as a normal LED, too, when in
> "manual mode" where it can be switched on and off by a register
> write.

"Native mode" is quite common. We have it for example on Nokia N900
here (charger has hw option to automatically control the LED).

I believe reasonable solution would be to have "hardware" trigger, and
have it selected by default. When active, LED would be controlled by
hardware.

> Another feature of the LED device is that there is a global brightness
> register that influences all LED's brightness (if on) independent of the
> operating mode.

We can't describe that easily.

> Further the color of each LED can be set to an RGB triplet.

We normally handle RGB LED as three independend LEDs, like
notify::red, notify::green, notify::blue. Again, example is Nokia N900
or Motorola Droid 4.

Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: led: hw-trigger, global brightness and multi-colored leds [ In reply to ]
Hello Pavel,

On 05/02/2018 11:21 PM, Pavel Machek wrote:
>> on the Turris Omnia[1] the LEDs are controllable via an i2c device. Each
>> LED can be either in "manual mode" or in a mode I'd call "native mode"
>> which is the default. In this native mode the LED being on or off
>> depends on an input line that is controlled by another hardware. So a
>> LED signals for example activity on the WAN ethernet port without any
>> software intervention, but can be used as a normal LED, too, when in
>> "manual mode" where it can be switched on and off by a register
>> write.
>
> "Native mode" is quite common. We have it for example on Nokia N900
> here (charger has hw option to automatically control the LED).

git grep -i n900 -- drivers/leds doesn't yield any output. Do I miss
anything?

> I believe reasonable solution would be to have "hardware" trigger, and
> have it selected by default. When active, LED would be controlled by
> hardware.

There is no prior art for that available as source code, right?

>> Another feature of the LED device is that there is a global brightness
>> register that influences all LED's brightness (if on) independent of the
>> operating mode.
>
> We can't describe that easily.

Given that I can give an RGB value (i.e. 3x 8 bit) for the LED, I can
change brightness per LED. Have to play around a bit.

>> Further the color of each LED can be set to an RGB triplet.
>
> We normally handle RGB LED as three independend LEDs, like
> notify::red, notify::green, notify::blue. Again, example is Nokia N900
> or Motorola Droid 4.

I cannot find source code for LEDs on the Droid 4 either.

An ugly property here is that the hardware trigger only operates on all
three colors at once. Hmm, will think a bit about the way to go.

Best regards and thanks for your input,
Uwe
Re: led: hw-trigger, global brightness and multi-colored leds [ In reply to ]
Hi Uwe and Pavel,

On 05/03/2018 08:49 PM, Uwe Kleine-K?nig wrote:
> Hello Pavel,
>
> On 05/02/2018 11:21 PM, Pavel Machek wrote:
>>> on the Turris Omnia[1] the LEDs are controllable via an i2c device. Each
>>> LED can be either in "manual mode" or in a mode I'd call "native mode"
>>> which is the default. In this native mode the LED being on or off
>>> depends on an input line that is controlled by another hardware. So a
>>> LED signals for example activity on the WAN ethernet port without any
>>> software intervention, but can be used as a normal LED, too, when in
>>> "manual mode" where it can be switched on and off by a register
>>> write.
>>
>> "Native mode" is quite common. We have it for example on Nokia N900
>> here (charger has hw option to automatically control the LED).
>
> git grep -i n900 -- drivers/leds doesn't yield any output. Do I miss
> anything?
>
>> I believe reasonable solution would be to have "hardware" trigger, and
>> have it selected by default. When active, LED would be controlled by
>> hardware.

The question is whether there is a way for a driver to tell whether
the device is in the manual or in the native mode. If yes,
then we could just return -EBUSY on any attempt of brightness setting
when in the native mode.

Also, if it is possible to detect brightness changes originating
from hardware, then we have an optional brightness_hw_changed sysfs
file supporting POLLPRI events
(compare drivers/platform/x86/thinkpad_acpi.c).

If we can't tell whether the LED is in native or manual mode,
but it is possible to read the current brightness from a register, then
implementing brightness_get op will allow to detect it indirectly (to
some extent since we cannot guarantee that brightness is not changed
by another process).

In each case I'd rather not use trigger mechanism here, which is
defined as __kernel__ based source of LED events.

> There is no prior art for that available as source code, right?
>
>>> Another feature of the LED device is that there is a global brightness
>>> register that influences all LED's brightness (if on) independent of the
>>> operating mode.
>>
>> We can't describe that easily.
>
> Given that I can give an RGB value (i.e. 3x 8 bit) for the LED, I can
> change brightness per LED. Have to play around a bit.
>
>>> Further the color of each LED can be set to an RGB triplet.
>>
>> We normally handle RGB LED as three independend LEDs, like
>> notify::red, notify::green, notify::blue. Again, example is Nokia N900
>> or Motorola Droid 4.
>
> I cannot find source code for LEDs on the Droid 4 either.
>
> An ugly property here is that the hardware trigger only operates on all
> three colors at once. Hmm, will think a bit about the way to go.
>
> Best regards and thanks for your input,
> Uwe
>

--
Best regards,
Jacek Anaszewski
Re: led: hw-trigger, global brightness and multi-colored leds [ In reply to ]
Hi!

> > "Native mode" is quite common. We have it for example on Nokia N900
> > here (charger has hw option to automatically control the LED).
>
> git grep -i n900 -- drivers/leds doesn't yield any output. Do I miss
> anything?

Try grepping arch/arm/boot/..*.dts :-).

drivers/leds/leds-lp5523.c

But the hardware/software switch is pretty well hidden. In the charger
code, probably. Aha, here:

echo 0 > /sys/class/power_supply/bq24150a-0/stat_pin_enable

That one influences R and G channels of the RGB LED.

> >> Another feature of the LED device is that there is a global brightness
> >> register that influences all LED's brightness (if on) independent of the
> >> operating mode.
> >
> > We can't describe that easily.
>
> Given that I can give an RGB value (i.e. 3x 8 bit) for the LED, I can
> change brightness per LED. Have to play around a bit.

Ok, so do we need global brightness support at all?

> >> Further the color of each LED can be set to an RGB triplet.
> >
> > We normally handle RGB LED as three independend LEDs, like
> > notify::red, notify::green, notify::blue. Again, example is Nokia N900
> > or Motorola Droid 4.
>
> I cannot find source code for LEDs on the Droid 4 either.

That would be

arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
motorola,cpcap-led-red

> An ugly property here is that the hardware trigger only operates on all
> three colors at once. Hmm, will think a bit about the way to go.

Fun.

So... it would be nice to treat RGB LED as one LED, not three. I even
made some patches in that direction, but I went to HSV colors and that
did not work well.

Sorry, I should sleep.

Good luck,
Pavel



--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: led: hw-trigger, global brightness and multi-colored leds [ In reply to ]
Hi!

On Wed, May 2, 2018 at 5:11 PM, Uwe Kleine-König <uwe@kleine-koenig.org> wrote:
> Hello,
>
> on the Turris Omnia[1] the LEDs are controllable via an i2c device.
...
> Now I wonder how to match these two features to the LED device model. Do
> you have an idea?

That is an interesting question - I was quite clueless about that two
years ago - when I wrote the driver for Omnia LEDs
(https://github.com/tmshlvck/omnia-linux/blob/omnia/drivers/leds/leds-omnia.c).
I didn't even made an attempt to send it to upstream because it
obviously does not fit to the LED device model.

The fundamental problems were:

1) Sending commands over I2C to the MCU that drives LEDs is quite
slow. Therefore the interface is optimized for doing incremental
changes and batch changes. (Btw. the protocol description is here
https://gitlab.labs.nic.cz/hw/omnia_hw_ctrl/blob/master/turris_omnia_i2c_desc.adoc
).

2) "native" or autonomous mode means that MCU that drives LEDs take
independently wired (on/off) input from switch, PHY or PCI cards
without any kernel interaction, but color settings and brightness for
each individual LED are still active, just the on/off/blink trigger is
autonomous.

3) There is a global brightness (autonomous PWM control for cathode of
all LEDs - the best method for LED dimming, running on few MHz).

4) Per-LED brightness works, however PWM is running on just few
hundreds of kHz and when all LEDs are dimmed and you watch carefully,
you can see intermittent flickering.

5) The abstraction in the protocol (mentioned in (1)) is actually
counting 3 LEDs (separate RGB) as one arbitrary-color LED. The reason
was to save bandwidth on I2C I guess, because color is expected to
change less frequently than brightness.

But I also have good news: The FW of the MCU is also OSS (see the repo
in the link (1)). There is a method for flashing the MCU over I2C from
Linux and there is JTAG connector for the MCU, in case un-bricking is
needed. Therefore the LED protocol can be changed to be more sensible
and/or it is even possible to emulate some existing HW LED driver chip
in Omnia MCU and reuse OSS driver for that chip.

Tomas