RGB support prototype
Hi!
You mentioned you was working on RGB support prototype. Could you post copy of the patches (even if unfinished)?
Thanks,
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi,
Quoted 5 lines · Pavel Machek
Hi!
You mentioned you was working on RGB support prototype. Could you post copy of the patches (even if unfinished)?
Unfortunately it is at the stage of unfinished proof of concept and I haven't managed yet to try how it fits to all API use cases we have. Nor is it in a shape ready to post to the lists.
I think we could try to discuss the design here. I'll list all the issues I encountered during the implementation:
Currently we set LED brightness with following API:
void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness);
In case of RGB LED we could have something like this:
struct led_color_triplet {
enum led_brightness red;
enum led_brightness green;
enum led_brightness blue;
};void led_rgb_set_brightness(struct led_rgb_classdev *led_rgb_cdev,
struct led_color_triplet *color);
We've agreed that LED RGB class device color could be set by writing space separated list of "r g b" color values to a sysfs "color" file.
While the above itself shouldn't raise too many doubts, they arise quickly while trying to adapt it to the internal LED core facilities:
- led_base_timer_function()
- set_brightness_delayed()
- led_blink_* API family
All these introduce problems especially with brightness/color type. I tried to add a new abstraction layer by introducing
struct led_base_cdev with a set of generic ops that could be initialized by particular type of LED but still the problem with brightness type generalization remains. One solution could be an union with fields mapping to either single or three brightness components.
Other option could be void *brightness type which could be then cast to the required brightness type basing on the LED flag.
Generally it seems that all existing LED class API should get its generic counterparts.
Other ideas are welcome.
Signature · 2 lines
Best regards, Jacek Anaszewski
Hi!
Quoted 44 lines
Quoted 2 lines
You mentioned you was working on RGB support prototype. Could you post copy of the patches (even if unfinished)?
Unfortunately it is at the stage of unfinished proof of concept and I haven't managed yet to try how it fits to all API use cases we have. Nor is it in a shape ready to post to the lists.
I think we could try to discuss the design here. I'll list all the issues I encountered during the implementation:
Currently we set LED brightness with following API:
void led_set_brightness(struct
led_classdev*led_cdev,enum led_brightness brightness);In case of RGB LED we could have something like this:
struct led_color_triplet { enum led_brightness red; enum led_brightness green; enum led_brightness blue; };void led_rgb_set_brightness(struct
led_rgb_classdev*led_rgb_cdev,struct led_color_triplet *color);We've agreed that LED RGB class device color could be set by writing space separated list of "r g b" color values to a sysfs "color" file.
While the above itself shouldn't raise too many doubts, they arise quickly while trying to adapt it to the internal LED core facilities:
-
led_base_timer_function()
-set_brightness_delayed()
- led_blink_* API familyAll these introduce problems especially with brightness/color type. I tried to add a new abstraction layer by introducing
structled_base_cdevwith a set of generic ops that could be initialized by particular type of LED but still the problem with brightness type generalization remains. One solution could be an union with fields mapping to either single or three brightness components.
Quoted 2 lines
Other option could be void *brightness type which could be then cast to the required brightness type basing on the LED flag.
Void *brightness is not really a good option.
We could pass triplet even in case of single-color LEDs, and then use just one component.
Another option would be to store color in HSV colorspace (not RGB). Then existing functions would get brightness (== value in HSV), and RGB-aware functions would operate on all 3 components. Triggers/blinking/etc. would then continue operating, without modifications.
We could even export (read-only) hue/saturation for single-color LEDs...
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
Quoted 6 lines
Quoted 2 lines
You mentioned you was working on RGB support prototype. Could you post copy of the patches (even if unfinished)?
Unfortunately it is at the stage of unfinished proof of concept and I haven't managed yet to try how it fits to all API use cases we have. Nor is it in a shape ready to post to the lists.
Well, if it compiles, it is in shape. If it does not compile, it is in shape, too :-).
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi,
Quoted 54 lines · Pavel Machek
Hi!
Quoted 44 lines
Quoted 2 lines
You mentioned you was working on RGB support prototype. Could you post copy of the patches (even if unfinished)?
Unfortunately it is at the stage of unfinished proof of concept and I haven't managed yet to try how it fits to all API use cases we have. Nor is it in a shape ready to post to the lists.
I think we could try to discuss the design here. I'll list all the issues I encountered during the implementation:
Currently we set LED brightness with following API:
void led_set_brightness(struct
led_classdev*led_cdev,enum led_brightness brightness);In case of RGB LED we could have something like this:
struct led_color_triplet { enum led_brightness red; enum led_brightness green; enum led_brightness blue; };void led_rgb_set_brightness(struct
led_rgb_classdev*led_rgb_cdev,struct led_color_triplet *color);We've agreed that LED RGB class device color could be set by writing space separated list of "r g b" color values to a sysfs "color" file.
While the above itself shouldn't raise too many doubts, they arise quickly while trying to adapt it to the internal LED core facilities:
-
led_base_timer_function()
-set_brightness_delayed()
- led_blink_* API familyAll these introduce problems especially with brightness/color type. I tried to add a new abstraction layer by introducing
structled_base_cdevwith a set of generic ops that could be initialized by particular type of LED but still the problem with brightness type generalization remains. One solution could be an union with fields mapping to either single or three brightness components.Quoted 2 lines
Other option could be void *brightness type which could be then cast to the required brightness type basing on the LED flag.
Void *brightness is not really a good option.
We could pass triplet even in case of single-color LEDs, and then use just one component.
Quoted 6 lines
Another option would be to store color in HSV colorspace (not RGB). Then existing functions would get brightness (== value in HSV), and RGB-aware functions would operate on all 3 components. Triggers/blinking/etc. would then continue operating, without modifications.
We could even export (read-only) hue/saturation for single-color LEDs...
Related patches from Heiner Kallweit are still sitting on devel branch of linux-leds.git:
https://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git/log/?h=devel
Possibly it can serve as a basis for further development.
I liked that approach because it was compatible with monochrome LEDs and triggers.
Signature · 2 lines
Best regards, Jacek Anaszewski
Hi!
Quoted 11 lines
Quoted 1 line
We could even export (read-only) hue/saturation for single-color LEDs...
Related patches from Heiner Kallweit are still sitting on devel branch of linux-leds.git:
https://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git/log/?h=devel
Possibly it can serve as a basis for further development.
I liked that approach because it was compatible with monochrome LEDs and triggers.
Yeah, I like that. I don't like the implementation and the sysfs interface.
Let me try and see if I can turn them into something better...
I'm using full 32-bits for parameters; that should give us enough precision. In particular, 32-bits is important for "brightness"; I already have light that goes from .1lm to 1000lm -- which is more than 8-bits can handle.
lp5523 conversion... is a very quick hack.
Pavel
drivers/leds/Kconfig +12 -0
@@ -19,6 +19,14 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. +config LEDS_CLASS_RGB + bool "LED RGB Class Support" + depends on LEDS_CLASS + help + This option enables support for RGB LED devices. + Sysfs attribute brightness is interpreted as a HSV color value. + For details see Documentation/leds/leds-class.txt. + config LEDS_CLASS_FLASH tristate "LED Flash Class Support" depends on LEDS_CLASS
@@ -38,6 +46,10 @@ config LEDS_BRIGHTNESS_HW_CHANGED See Documentation/ABI/testing/sysfs-class-led for details. +if LEDS_CLASS_RGB +comment "RGB LED drivers" +endif # LEDS_CLASS_RGB + comment "LED drivers" config LEDS_88PM860X
drivers/leds/Makefile +3 -1
@@ -1,6 +1,8 @@ # LED Core -obj-$(CONFIG_NEW_LEDS) += led-core.o +obj-$(CONFIG_NEW_LEDS) += led-core-objs.o +led-core-objs-y := led-core.o +led-core-objs-$(CONFIG_LEDS_CLASS_RGB) += led-rgb-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
drivers/leds/led-class.c +79 -0
91 lines not on this page · raw message
drivers/leds/led-rgb-core.c new file +60 -0
60 lines not on this page · raw message
drivers/leds/leds-lp5523.c +20 -0
@@ -802,6 +802,26 @@ static ssize_t store_master_fader_leds(struct device *dev,return ret; } +int lp5523_rgb_brightness (struct lp55xx_led *led,struct led_rgb r) +{ +struct lp55xx_chip *chip = led->chip; +int ret; + +mutex_lock (&chip->lock); + r.red >>=24 ; + r.green >>=24 ; + r.blue >>=24 ; +printk ("RGB brightness %d %d %d\n" , r.red, r.green, r.blue); + ret =lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr, r.red); +if (!ret) +lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr -1 , r.green); +if (!ret) +lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr -1 , r.blue); +mutex_unlock (&chip->lock); +return ret; + +} +static int lp5523_led_brightness (struct lp55xx_led *led) {struct lp55xx_chip *chip = led->chip;
drivers/leds/leds-lp55xx-common.c +16 -0
@@ -134,6 +134,8 @@ static struct attribute *lp55xx_led_attrs[] = { };ATTRIBUTE_GROUPS (lp55xx_led); +extern int lp5523_rgb_brightness (struct lp55xx_led *led,struct led_rgb r); +static int lp55xx_set_brightness (struct led_classdev *cdev,enum led_brightness brightness) {
@@ -141,6 +143,18 @@ static int lp55xx_set_brightness(struct led_classdev *cdev,struct lp55xx_device_config *cfg = led->chip->cfg; led->brightness = (u8 )brightness; + +if (led->chan_nr ==6 ) { +struct led_rgb r; +struct led_hsv hsv; + +printk ("RGB set request: %d %d %d\n" , cdev->brightness, cdev->hue >>24 , cdev->saturation >>24 ); + hsv.value = brightness <<24 ; + hsv.hue = cdev->hue; + hsv.saturation = cdev->saturation; + r =led_hsv_to_rgb (hsv); +return lp5523_rgb_brightness (led, r); + }return cfg->brightness_fn (led); }
@@ -176,6 +190,8 @@ static int lp55xx_init_led(struct lp55xx_led *led, led->cdev.brightness_set_blocking = lp55xx_set_brightness; led->cdev.groups = lp55xx_led_groups; +printk ("Led %d name %s\n" , chan, pdata->led_config[chan].name); +if (pdata->led_config[chan].name) { led->cdev.name = pdata->led_config[chan].name; }else {
include/linux/leds.h +23 -0
@@ -37,6 +37,8 @@ struct led_classdev {const char *name;enum led_brightness brightness;enum led_brightness max_brightness; +int hue; +int saturation;int flags;/* Lower 16 bits reflect status */
@@ -49,6 +51,7 @@ struct led_classdev {#define LED_HW_PLUGGABLE (1 << 19)#define LED_PANIC_INDICATOR (1 << 20)#define LED_BRIGHT_HW_CHANGED (1 << 21) +#define LED_DEV_CAP_RGB (1 << 24)/* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags;
@@ -238,6 +241,26 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev)return led_cdev->flags &LED_SYSFS_DISABLE ; } +struct led_hsv { +u32 hue; +u32 saturation; +u32 value; +}; + +struct led_rgb { +u32 red; +u32 green; +u32 blue; +}; + +/** +* led_hsv_to_rgb - convert a hsv color value to rgb color model +* @hsv: the hsv value to convert +* +* Returns: the resulting rgb value +*/ +struct led_rgb led_hsv_to_rgb (struct led_hsv hsv); +/* * LED Triggers */
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi!
Quoted 15 lines
Quoted 11 lines
Quoted 1 line
We could even export (read-only) hue/saturation for single-color LEDs...
Related patches from Heiner Kallweit are still sitting on devel branch of linux-leds.git:
https://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git/log/?h=devel
Possibly it can serve as a basis for further development.
I liked that approach because it was compatible with monochrome LEDs and triggers.
Yeah, I like that. I don't like the implementation and the sysfs interface.
Quoted 8 lines
Let me try and see if I can turn them into something better...
I'm using full 32-bits for parameters; that should give us enough precision. In particular, 32-bits is important for "brightness"; I already have light that goes from .1lm to 1000lm -- which is more than 8-bits can handle.
lp5523 conversion... is a very quick hack.
And here's a better version. I'll still need to adjust white to be white... but I guess that would need to be done with any solution.
I've checked, and triggers seem to work as expected (and I can select a color for them).
drivers/leds/Kconfig +12 -0
@@ -19,6 +19,14 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. +config LEDS_CLASS_RGB + bool "LED RGB Class Support" + depends on LEDS_CLASS + help + This option enables support for RGB LED devices. + Sysfs attribute brightness is interpreted as a HSV color value. + For details see Documentation/leds/leds-class.txt. + config LEDS_CLASS_FLASH tristate "LED Flash Class Support" depends on LEDS_CLASS
@@ -38,6 +46,10 @@ config LEDS_BRIGHTNESS_HW_CHANGED See Documentation/ABI/testing/sysfs-class-led for details. +if LEDS_CLASS_RGB +comment "RGB LED drivers" +endif # LEDS_CLASS_RGB + comment "LED drivers" config LEDS_88PM860X
drivers/leds/Makefile +3 -1
@@ -1,6 +1,8 @@ # LED Core -obj-$(CONFIG_NEW_LEDS) += led-core.o +obj-$(CONFIG_NEW_LEDS) += led-core-objs.o +led-core-objs-y := led-core.o +led-core-objs-$(CONFIG_LEDS_CLASS_RGB) += led-rgb-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
drivers/leds/led-class.c +79 -0
91 lines not on this page · raw message
drivers/leds/led-rgb-core.c new file +64 -0
64 lines not on this page · raw message
drivers/leds/leds-lp5523.c +20 -0
@@ -802,6 +802,26 @@ static ssize_t store_master_fader_leds(struct device *dev,return ret; } +int lp5523_rgb_brightness (struct lp55xx_led *led,struct led_rgb r) +{ +struct lp55xx_chip *chip = led->chip; +int ret; + +mutex_lock (&chip->lock); + r.red >>=24 ; + r.green >>=24 ; + r.blue >>=24 ; +printk ("RGB brightness %d %d %d\n" , r.red, r.green, r.blue); + ret =lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr, r.red); +if (!ret) +lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr -1 , r.green); +if (!ret) +lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr -2 , r.blue); +mutex_unlock (&chip->lock); +return ret; + +} +static int lp5523_led_brightness (struct lp55xx_led *led) {struct lp55xx_chip *chip = led->chip;
drivers/leds/leds-lp55xx-common.c +16 -0
@@ -134,6 +134,8 @@ static struct attribute *lp55xx_led_attrs[] = { };ATTRIBUTE_GROUPS (lp55xx_led); +extern int lp5523_rgb_brightness (struct lp55xx_led *led,struct led_rgb r); +static int lp55xx_set_brightness (struct led_classdev *cdev,enum led_brightness brightness) {
@@ -141,6 +143,18 @@ static int lp55xx_set_brightness(struct led_classdev *cdev,struct lp55xx_device_config *cfg = led->chip->cfg; led->brightness = (u8 )brightness; + +if (led->chan_nr ==6 ) { +struct led_rgb r; +struct led_hsv hsv; + +printk ("RGB set request: %d %d %d\n" , cdev->brightness, cdev->hue >>24 , cdev->saturation >>24 ); + hsv.value = brightness <<24 ; + hsv.hue = cdev->hue; + hsv.saturation = cdev->saturation; + r =led_hsv_to_rgb (hsv); +return lp5523_rgb_brightness (led, r); + }return cfg->brightness_fn (led); }
@@ -176,6 +190,8 @@ static int lp55xx_init_led(struct lp55xx_led *led, led->cdev.brightness_set_blocking = lp55xx_set_brightness; led->cdev.groups = lp55xx_led_groups; +printk ("Led %d name %s\n" , chan, pdata->led_config[chan].name); +if (pdata->led_config[chan].name) { led->cdev.name = pdata->led_config[chan].name; }else {
include/linux/leds.h +23 -0
@@ -37,6 +37,8 @@ struct led_classdev {const char *name;enum led_brightness brightness;enum led_brightness max_brightness; +int hue; +int saturation;int flags;/* Lower 16 bits reflect status */
@@ -49,6 +51,7 @@ struct led_classdev {#define LED_HW_PLUGGABLE (1 << 19)#define LED_PANIC_INDICATOR (1 << 20)#define LED_BRIGHT_HW_CHANGED (1 << 21) +#define LED_DEV_CAP_RGB (1 << 24)/* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags;
@@ -238,6 +241,26 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev)return led_cdev->flags &LED_SYSFS_DISABLE ; } +struct led_hsv { +u32 hue; +u32 saturation; +u32 value; +}; + +struct led_rgb { +u32 red; +u32 green; +u32 blue; +}; + +/** +* led_hsv_to_rgb - convert a hsv color value to rgb color model +* @hsv: the hsv value to convert +* +* Returns: the resulting rgb value +*/ +struct led_rgb led_hsv_to_rgb (struct led_hsv hsv); +/* * LED Triggers */
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Hi Pavel,
Thanks for your work. Few comments below.
Quoted 83 lines · Pavel Machek
Hi!
Quoted 15 lines
Quoted 11 lines
Quoted 1 line
We could even export (read-only) hue/saturation for single-color LEDs...
Related patches from Heiner Kallweit are still sitting on devel branch of linux-leds.git:
https://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git/log/?h=devel
Possibly it can serve as a basis for further development.
I liked that approach because it was compatible with monochrome LEDs and triggers.
Yeah, I like that. I don't like the implementation and the sysfs interface.
Quoted 8 lines
Let me try and see if I can turn them into something better...
I'm using full 32-bits for parameters; that should give us enough precision. In particular, 32-bits is important for "brightness"; I already have light that goes from .1lm to 1000lm -- which is more than 8-bits can handle.
lp5523 conversion... is a very quick hack.
And here's a better version. I'll still need to adjust white to be white... but I guess that would need to be done with any solution.
I've checked, and triggers seem to work as expected (and I can select a color for them).
Signed-off-by Pavel Machek <[email protected]>drivers/leds/Kconfig +12
-0@@ -19,6 +19,14 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. +config LEDS_CLASS_RGB + bool "LED RGB Class Support" + depends on LEDS_CLASS + help + This option enables support for RGB LED devices. + Sysfs attribute brightness is interpreted as a HSV color value. + For details see Documentation/leds/leds-class.txt. + config LEDS_CLASS_FLASH tristate "LED Flash Class Support" depends on LEDS_CLASS@@ -38,6 +46,10 @@ config LEDS_BRIGHTNESS_HW_CHANGED See Documentation/ABI/testing/sysfs-class-led for details. +if LEDS_CLASS_RGB +comment "RGB LED drivers" +endif # LEDS_CLASS_RGB + comment "LED drivers" config LEDS_88PM860Xdrivers/leds/Makefile +3
-1@@ -1,6 +1,8 @@ # LED Core -obj-$(CONFIG_NEW_LEDS) += led-core.o +obj-$(CONFIG_NEW_LEDS) += led-core-objs.o +led-core-objs-y := led-core.o +led-core-objs-$(CONFIG_LEDS_CLASS_RGB) += led-rgb-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.odrivers/leds/led-class.c +0
-0
drivers/leds/led-class.c static ssize_t brightness_store(struct device *dev, · line 74
Quoted 10 lines
drivers/leds/led-class.c +7
-0@@ -65,6 +65,83 @@ static ssize_t brightness_store(struct device *dev, }static DEVICE_ATTR_RW (brightness); +static ssize_t saturation_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct led_classdev *led_cdev =dev_get_drvdata (dev); + +/* no lock needed for this */ +led_update_brightness (led_cdev);
We will need to update documentation of brightness_get to require updating hue and saturation for RGB LED drivers.
Also hue and saturation attributes will need related ABI documentation entries. From what I see you're proposing that hue and sat would be written to the device on the occasion of brightness setting, right? We're tossing this responsibility to to drivers, without exposing an API for it, so it would have to be highlighted.
Quoted 110 lines
drivers/leds/led-class.c +72
-0+ +return sprintf (buf,"%u\n" , led_cdev->saturation); +} + +static ssize_t saturation_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t size) +{ +struct led_classdev *led_cdev =dev_get_drvdata (dev); +unsigned long state; +ssize_t ret; + +mutex_lock (&led_cdev->led_access); + +if (led_sysfs_is_disabled (led_cdev)) { + ret = -EBUSY ; + goto unlock; + } + + ret =kstrtoul (buf,10 , &state); +if (ret) + goto unlock; + + led_cdev->saturation = state; + + ret = size; +unlock: +mutex_unlock (&led_cdev->led_access); +return ret; +} +static DEVICE_ATTR_RW (saturation); + +static ssize_t hue_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct led_classdev *led_cdev =dev_get_drvdata (dev); + +/* no lock needed for this */ +led_update_brightness (led_cdev); + +return sprintf (buf,"%u\n" , led_cdev->hue); +} + +static ssize_t hue_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t size) +{ +struct led_classdev *led_cdev =dev_get_drvdata (dev); +unsigned long state; +ssize_t ret; + +mutex_lock (&led_cdev->led_access); + +if (led_sysfs_is_disabled (led_cdev)) { + ret = -EBUSY ; + goto unlock; + } + + ret =kstrtoul (buf,10 , &state); +if (ret) + goto unlock; + + led_cdev->hue = state; + + ret = size; +unlock: +mutex_unlock (&led_cdev->led_access); +return ret; +} +static DEVICE_ATTR_RW (hue); + +static ssize_t max_brightness_show (struct device *dev,struct device_attribute *attr,char *buf) {@@ -88,6 +165,8 @@ static const struct attribute_group led_trigger_group = {static struct attribute *led_class_attrs[] = { &dev_attr_brightness.attr, &dev_attr_max_brightness.attr, + &dev_attr_hue.attr, + &dev_attr_saturation.attr,NULL , };drivers/leds/led-rgb-core.c new file +22
-0@@ -0,0 +1,64 @@ +/* +* LED RGB Class Support +* +* Author: Heiner Kallweit <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ + +#include <linux/leds.h> +#include "leds.h" + +struct led_rgb led_hsv_to_rgb (struct led_hsv hsv) +{ +unsigned int h = hsv.hue >>24 ; +unsigned int s = hsv.saturation >>24 ; +unsigned int v = hsv.value >>24 ; +unsigned int f, p, q, t, r, g, b; +struct led_rgb res; +
drivers/leds/led-rgb-core.c line 32
Quoted 10 lines
drivers/leds/led-rgb-core.c new file +10
-0+if (!v) { + res.red =0 ; + res.green =0 ; + res.blue =0 ; +return res; + } +if (!s) { + res.red = v <<24 ; + res.green = v <<24 ; + res.blue = v <<24 ;
Why the shifting?
Quoted 154 lines
drivers/leds/led-rgb-core.c new file +32
-0+return res; + } + + f =DIV_ROUND_CLOSEST ((h %42 ) *255 ,42 ); + p = v -DIV_ROUND_CLOSEST (s * v,255 ); + q = v -DIV_ROUND_CLOSEST (f * s * v,255 *255 ); + t = v -DIV_ROUND_CLOSEST ((255 - f) * s * v,255 *255 ); + +switch (h /42 ) { +case 0 : + r = v; g = t; b = p;break ; +case 1 : + r = q; g = v; b = p;break ; +case 2 : + r = p; g = v; b = t;break ; +case 3 : + r = p; g = q; b = v;break ; +case 4 : + r = t; g = p; b = v;break ; +case 5 : + r = v; g = p; b = q;break ; + } + +printk ("hsv_to: h %5d, s %5d, v %5d -> %5d, %5d, %5d\n" , + h*390 , s*390 , v*390 , r*390 , g*390 , b*390 ); + + res.red = r <<24 ; + res.green = g <<24 ; + res.blue = b <<24 ; +return res; +} +EXPORT_SYMBOL_GPL (led_hsv_to_rgb);drivers/leds/leds-lp5523.c +20
-0@@ -802,6 +802,26 @@ static ssize_t store_master_fader_leds(struct device *dev,return ret; } +int lp5523_rgb_brightness (struct lp55xx_led *led,struct led_rgb r) +{ +struct lp55xx_chip *chip = led->chip; +int ret; + +mutex_lock (&chip->lock); + r.red >>=24 ; + r.green >>=24 ; + r.blue >>=24 ; +printk ("RGB brightness %d %d %d\n" , r.red, r.green, r.blue); + ret =lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr, r.red); +if (!ret) +lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr -1 , r.green); +if (!ret) +lp55xx_write (chip,LP5523_REG_LED_PWM_BASE + led->chan_nr -2 , r.blue); +mutex_unlock (&chip->lock); +return ret; + +} +static int lp5523_led_brightness (struct lp55xx_led *led) {struct lp55xx_chip *chip = led->chip;drivers/leds/leds-lp55xx-common.c +16
-0@@ -134,6 +134,8 @@ static struct attribute *lp55xx_led_attrs[] = { };ATTRIBUTE_GROUPS (lp55xx_led); +extern int lp5523_rgb_brightness (struct lp55xx_led *led,struct led_rgb r); +static int lp55xx_set_brightness (struct led_classdev *cdev,enum led_brightness brightness) {@@ -141,6 +143,18 @@ static int lp55xx_set_brightness(struct led_classdev *cdev,struct lp55xx_device_config *cfg = led->chip->cfg; led->brightness = (u8 )brightness; + +if (led->chan_nr ==6 ) { +struct led_rgb r; +struct led_hsv hsv; + +printk ("RGB set request: %d %d %d\n" , cdev->brightness, cdev->hue >>24 , cdev->saturation >>24 ); + hsv.value = brightness <<24 ; + hsv.hue = cdev->hue; + hsv.saturation = cdev->saturation; + r =led_hsv_to_rgb (hsv); +return lp5523_rgb_brightness (led, r); + }return cfg->brightness_fn (led); }@@ -176,6 +190,8 @@ static int lp55xx_init_led(struct lp55xx_led *led, led->cdev.brightness_set_blocking = lp55xx_set_brightness; led->cdev.groups = lp55xx_led_groups; +printk ("Led %d name %s\n" , chan, pdata->led_config[chan].name); +if (pdata->led_config[chan].name) { led->cdev.name = pdata->led_config[chan].name; }else {include/linux/leds.h +23
-0@@ -37,6 +37,8 @@ struct led_classdev {const char *name;enum led_brightness brightness;enum led_brightness max_brightness; +int hue; +int saturation;int flags;/* Lower 16 bits reflect status */ @@ -49,6 +51,7 @@ struct led_classdev {#define LED_HW_PLUGGABLE (1 << 19)#define LED_PANIC_INDICATOR (1 << 20)#define LED_BRIGHT_HW_CHANGED (1 << 21) +#define LED_DEV_CAP_RGB (1 << 24)/* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags;@@ -238,6 +241,26 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev)return led_cdev->flags &LED_SYSFS_DISABLE ; } +struct led_hsv { +u32 hue; +u32 saturation; +u32 value; +}; + +struct led_rgb { +u32 red; +u32 green; +u32 blue; +}; + +/** +* led_hsv_to_rgb - convert a hsv color value to rgb color model +* @hsv: the hsv value to convert +* +* Returns: the resulting rgb value +*/ +struct led_rgb led_hsv_to_rgb (struct led_hsv hsv); +/* * LED Triggers */
Signature · 2 lines
Best regards, Jacek Anaszewski