leds: core: add support for RGB LED's
PATCH 1/1 leds: core: add support for RGB LED's
This patch adds support for RGB LED's to the core.
To use this extension a driver must add LED_DEV_CAP_RGB to the led_classdev flags. The callbacks to be implemented by the driver are the same as before, just enum led_brightness is used as <00000000><RRRRRRRR><GGGGGGGG><BBBBBBB> now.
A new sysfs property "rgb" allows to set the color from userspace.
The RGB extension is fully compatible with the current brightness-based API incl. triggers.
What still needs to be done:
update Documentation/leds/leds-class.txt
Signed-off-by Heiner Kallweit <[email protected]>
--- drivers/leds/led-class.c | 69 +++++++++++++++++++++++++++ drivers/leds/led-core.c | 121 ++++++++++++++++++++++++++++++++++++++++------- drivers/leds/leds.h | 16 +++++++ include/linux/leds.h | 3 ++ 4 files changed, 193 insertions(+), 16 deletions(-)
drivers/leds/led-class.c +69 -0
@@ -64,6 +64,46 @@ unlock: }static DEVICE_ATTR_RW (brightness); +static ssize_t rgb_show (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct led_classdev *led_cdev =dev_get_drvdata (dev); + +return sprintf (buf,"0x%06x\n" ,led_get_rgb_val (led_cdev)); +} + +static ssize_t rgb_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,0 , &state); +if (ret) + goto unlock; + +if (state >LED_WHITE ) { + ret = -EINVAL ; + goto unlock; + } + +led_set_rgb (led_cdev, state); + + ret = size; +unlock: +mutex_unlock (&led_cdev->led_access); +return ret; +} +static DEVICE_ATTR_RW (rgb); +static ssize_t max_brightness_show (struct device *dev,struct device_attribute *attr,char *buf) {
@@ -90,10 +130,19 @@ static struct attribute *led_class_attrs[] = { NULL, }; +static struct attribute *led_rgb_attrs[] = { + &dev_attr_rgb.attr, +NULL , +}; +static const struct attribute_group led_group = { .attrs = led_class_attrs, }; +static const struct attribute_group led_rgb_group = { + .attrs = led_rgb_attrs, +}; +static const struct attribute_group *led_groups[] = { &led_group, #ifdef CONFIG_LEDS_TRIGGERS
@@ -102,6 +151,11 @@ static const struct attribute_group *led_groups[] = { NULL, }; +static const struct attribute_group *led_rgb_groups[] = { + &led_rgb_group, +NULL , +}; +/** * led_classdev_suspend - suspend an led_classdev. * @led_cdev: the led_classdev to suspend.
@@ -190,6 +244,21 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)char name[64 ];int ret; +/* FLASH is not supported for RGB LEDs so far +* and RGB enforces max_brightness = LED_FULL. +* Initialize the color as white. +*/ +if (led_is_rgb (led_cdev)) { +if (led_cdev->flags &LED_DEV_CAP_FLASH ) { +dev_err (parent, +"RGB and FLASH mode are mutually exclusive\n" ); +return -EINVAL ; + } + led_cdev->max_brightness =LED_FULL ; + led_cdev->rgb_val =LED_WHITE ; + led_cdev->groups = led_rgb_groups; + } + ret =led_classdev_next_name (led_cdev->name, name,sizeof (name));if (ret <0 )return ret;
drivers/leds/led-core.c +105 -16
171 lines not on this page · raw message
drivers/leds/leds.h +16 -0
@@ -16,17 +16,33 @@#include <linux/rwsem.h> #include <linux/leds.h> +#define LED_UPDATE_COLOR BIT(0) +#define LED_UPDATE_BRIGHTNESS BIT(1) + +#define LED_WHITE 0xffffff +static inline int led_get_brightness (struct led_classdev *led_cdev) {return led_cdev->brightness; } +static inline u32 led_get_rgb_val (struct led_classdev *led_cdev) +{ +return led_cdev->rgb_val; +} + +static inline bool led_is_rgb (struct led_classdev *led_cdev) +{ +return (led_cdev->flags &LED_DEV_CAP_RGB ) !=0 ; +} +void led_init_core (struct led_classdev *led_cdev);void led_stop_software_blink (struct led_classdev *led_cdev);void led_set_brightness_nopm (struct led_classdev *led_cdev,enum led_brightness value);void led_set_brightness_nosleep (struct led_classdev *led_cdev,enum led_brightness value); +void led_set_rgb (struct led_classdev *led_cdev,u32 rgb_val);extern struct rw_semaphore leds_list_lock;extern struct list_head leds_list;
include/linux/leds.h +3 -0
@@ -35,6 +35,7 @@ struct led_classdev {const char *name;enum led_brightness brightness;enum led_brightness max_brightness; +u32 rgb_val;int flags;/* Lower 16 bits reflect status */
@@ -50,6 +51,7 @@ struct led_classdev {#define LED_SYSFS_DISABLE (1 << 22)#define LED_DEV_CAP_FLASH (1 << 23)#define LED_HW_PLUGGABLE (1 << 24) +#define LED_DEV_CAP_RGB (1 << 25)/* Set LED brightness level * Must not sleep. Use brightness_set_blocking for drivers
@@ -91,6 +93,7 @@ struct led_classdev {struct work_struct set_brightness_work;int delayed_set_value; +u32 delayed_rgb_value;#ifdef CONFIG_LEDS_TRIGGERS /* Protects the trigger data below */
Signature · 1 line
2.7.0