From 1bd465e6b0e2b559db47420fea686507a01cfab0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 10 Jan 2009 18:54:39 +0000 Subject: [PATCH] leds: allow led-drivers to use a variable range of brightness values This patch allows drivers to override the default maximum brightness value of 255. We take care to preserve backwards-compatibility as much as possible, so that user-space ABI doesn't change for existing drivers. LED trigger code has also been updated to use the per-LED maximum. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Richard Purdie --- drivers/leds/led-class.c | 21 ++++++++++++++++++++- drivers/leds/leds.h | 4 ++-- drivers/leds/ledtrig-default-on.c | 2 +- drivers/leds/ledtrig-heartbeat.c | 4 ++-- drivers/leds/ledtrig-ide-disk.c | 3 ++- drivers/leds/ledtrig-timer.c | 2 +- include/linux/leds.h | 1 + 7 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 52f82e3..f2cc13d 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -64,7 +64,16 @@ static ssize_t led_brightness_store(struct device *dev, return ret; } +static ssize_t led_max_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", led_cdev->max_brightness); +} + static DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store); +static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL); #ifdef CONFIG_LEDS_TRIGGERS static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); #endif @@ -138,6 +147,13 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) list_add_tail(&led_cdev->node, &leds_list); up_write(&leds_list_lock); + if (!led_cdev->max_brightness) + led_cdev->max_brightness = LED_FULL; + + rc = device_create_file(led_cdev->dev, &dev_attr_max_brightness); + if (rc) + goto err_out_attr_max; + led_update_brightness(led_cdev); #ifdef CONFIG_LEDS_TRIGGERS @@ -155,9 +171,11 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) #ifdef CONFIG_LEDS_TRIGGERS err_out_led_list: + device_remove_file(led_cdev->dev, &dev_attr_max_brightness); +#endif +err_out_attr_max: device_remove_file(led_cdev->dev, &dev_attr_brightness); list_del(&led_cdev->node); -#endif err_out: device_unregister(led_cdev->dev); return rc; @@ -172,6 +190,7 @@ EXPORT_SYMBOL_GPL(led_classdev_register); */ void led_classdev_unregister(struct led_classdev *led_cdev) { + device_remove_file(led_cdev->dev, &dev_attr_max_brightness); device_remove_file(led_cdev->dev, &dev_attr_brightness); #ifdef CONFIG_LEDS_TRIGGERS device_remove_file(led_cdev->dev, &dev_attr_trigger); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 5edbf52..2dd8ecb 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -20,8 +20,8 @@ static inline void led_set_brightness(struct led_classdev *led_cdev, enum led_brightness value) { - if (value > LED_FULL) - value = LED_FULL; + if (value > led_cdev->max_brightness) + value = led_cdev->max_brightness; led_cdev->brightness = value; if (!(led_cdev->flags & LED_SUSPENDED)) led_cdev->brightness_set(led_cdev, value); diff --git a/drivers/leds/ledtrig-default-on.c b/drivers/leds/ledtrig-default-on.c index 92995e4..a4ef54b 100644 --- a/drivers/leds/ledtrig-default-on.c +++ b/drivers/leds/ledtrig-default-on.c @@ -19,7 +19,7 @@ static void defon_trig_activate(struct led_classdev *led_cdev) { - led_set_brightness(led_cdev, LED_FULL); + led_set_brightness(led_cdev, led_cdev->max_brightness); } static struct led_trigger defon_led_trigger = { diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c index 4bf8cec..c1c1ea6 100644 --- a/drivers/leds/ledtrig-heartbeat.c +++ b/drivers/leds/ledtrig-heartbeat.c @@ -47,7 +47,7 @@ static void led_heartbeat_function(unsigned long data) msecs_to_jiffies(heartbeat_data->period); delay = msecs_to_jiffies(70); heartbeat_data->phase++; - brightness = LED_FULL; + brightness = led_cdev->max_brightness; break; case 1: delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); @@ -56,7 +56,7 @@ static void led_heartbeat_function(unsigned long data) case 2: delay = msecs_to_jiffies(70); heartbeat_data->phase++; - brightness = LED_FULL; + brightness = led_cdev->max_brightness; break; default: delay = heartbeat_data->period - heartbeat_data->period / 4 - diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c index 883a577..ec099fc 100644 --- a/drivers/leds/ledtrig-ide-disk.c +++ b/drivers/leds/ledtrig-ide-disk.c @@ -37,7 +37,8 @@ static void ledtrig_ide_timerfunc(unsigned long data) { if (ide_lastactivity != ide_activity) { ide_lastactivity = ide_activity; - led_trigger_event(ledtrig_ide, LED_FULL); + /* INT_MAX will set each LED to its maximum brightness */ + led_trigger_event(ledtrig_ide, INT_MAX); mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); } else { led_trigger_event(ledtrig_ide, LED_OFF); diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 3d65313..3b83406 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c @@ -166,7 +166,7 @@ static void timer_trig_activate(struct led_classdev *led_cdev) timer_data->brightness_on = led_get_brightness(led_cdev); if (timer_data->brightness_on == LED_OFF) - timer_data->brightness_on = LED_FULL; + timer_data->brightness_on = led_cdev->max_brightness; led_cdev->trigger_data = timer_data; init_timer(&timer_data->timer); diff --git a/include/linux/leds.h b/include/linux/leds.h index 24489da..17d277e 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -30,6 +30,7 @@ enum led_brightness { struct led_classdev { const char *name; int brightness; + int max_brightness; int flags; /* Lower 16 bits reflect status */ -- 2.7.4