diff options
author | Németh Márton <nm127@freemail.hu> | 2008-03-09 16:54:37 -0400 |
---|---|---|
committer | Richard Purdie <rpurdie@rpsys.net> | 2008-04-24 18:34:18 -0400 |
commit | 0013b23d66a2768f5babbb0ea9f03ab067a990d8 (patch) | |
tree | 14d60a50bb68e422767a268cd737f70ef4e6e19d | |
parent | b3ba31f84ea041c0945b5904d4c407ce14b2b72c (diff) |
leds: disable triggers on brightness set
Disable any active triggers when the brightness attribute is
set to zero.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Márton Németh <nm127@freemail.hu>
Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
-rw-r--r-- | Documentation/leds-class.txt | 12 | ||||
-rw-r--r-- | drivers/leds/led-class.c | 3 | ||||
-rw-r--r-- | drivers/leds/led-triggers.c | 12 | ||||
-rw-r--r-- | drivers/leds/leds.h | 7 | ||||
-rw-r--r-- | drivers/leds/ledtrig-timer.c | 23 |
5 files changed, 47 insertions, 10 deletions
diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt index 56757c751d6f..18860ad9935a 100644 --- a/Documentation/leds-class.txt +++ b/Documentation/leds-class.txt | |||
@@ -19,6 +19,12 @@ optimises away. | |||
19 | 19 | ||
20 | Complex triggers whilst available to all LEDs have LED specific | 20 | Complex triggers whilst available to all LEDs have LED specific |
21 | parameters and work on a per LED basis. The timer trigger is an example. | 21 | parameters and work on a per LED basis. The timer trigger is an example. |
22 | The timer trigger will periodically change the LED brightness between | ||
23 | LED_OFF and the current brightness setting. The "on" and "off" time can | ||
24 | be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds. | ||
25 | You can change the brightness value of a LED independently of the timer | ||
26 | trigger. However, if you set the brightness value to LED_OFF it will | ||
27 | also disable the timer trigger. | ||
22 | 28 | ||
23 | You can change triggers in a similar manner to the way an IO scheduler | 29 | You can change triggers in a similar manner to the way an IO scheduler |
24 | is chosen (via /sys/class/leds/<device>/trigger). Trigger specific | 30 | is chosen (via /sys/class/leds/<device>/trigger). Trigger specific |
@@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In | |||
63 | this case the driver should give back the chosen value through delay_on | 69 | this case the driver should give back the chosen value through delay_on |
64 | and delay_off parameters to the leds subsystem. | 70 | and delay_off parameters to the leds subsystem. |
65 | 71 | ||
66 | Any call to the brightness_set() callback function should cancel the | 72 | Setting the brightness to zero with brightness_set() callback function |
67 | previously programmed hardware blinking function so setting the brightness | 73 | should completely turn off the LED and cancel the previously programmed |
68 | to 0 can also cancel the blinking of the LED. | 74 | hardware blinking function, if any. |
69 | 75 | ||
70 | 76 | ||
71 | Known Issues | 77 | Known Issues |
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 63aad90247c4..a8dd59ebedf8 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c | |||
@@ -51,6 +51,9 @@ static ssize_t led_brightness_store(struct device *dev, | |||
51 | 51 | ||
52 | if (count == size) { | 52 | if (count == size) { |
53 | ret = count; | 53 | ret = count; |
54 | |||
55 | if (state == LED_OFF) | ||
56 | led_trigger_remove(led_cdev); | ||
54 | led_set_brightness(led_cdev, state); | 57 | led_set_brightness(led_cdev, state); |
55 | } | 58 | } |
56 | 59 | ||
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 13c9026d68af..21dd96909444 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c | |||
@@ -45,9 +45,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, | |||
45 | trigger_name[len - 1] = '\0'; | 45 | trigger_name[len - 1] = '\0'; |
46 | 46 | ||
47 | if (!strcmp(trigger_name, "none")) { | 47 | if (!strcmp(trigger_name, "none")) { |
48 | down_write(&led_cdev->trigger_lock); | 48 | led_trigger_remove(led_cdev); |
49 | led_trigger_set(led_cdev, NULL); | ||
50 | up_write(&led_cdev->trigger_lock); | ||
51 | return count; | 49 | return count; |
52 | } | 50 | } |
53 | 51 | ||
@@ -139,6 +137,13 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) | |||
139 | led_cdev->trigger = trigger; | 137 | led_cdev->trigger = trigger; |
140 | } | 138 | } |
141 | 139 | ||
140 | void led_trigger_remove(struct led_classdev *led_cdev) | ||
141 | { | ||
142 | down_write(&led_cdev->trigger_lock); | ||
143 | led_trigger_set(led_cdev, NULL); | ||
144 | up_write(&led_cdev->trigger_lock); | ||
145 | } | ||
146 | |||
142 | void led_trigger_set_default(struct led_classdev *led_cdev) | 147 | void led_trigger_set_default(struct led_classdev *led_cdev) |
143 | { | 148 | { |
144 | struct led_trigger *trig; | 149 | struct led_trigger *trig; |
@@ -231,6 +236,7 @@ void led_trigger_unregister_simple(struct led_trigger *trigger) | |||
231 | 236 | ||
232 | /* Used by LED Class */ | 237 | /* Used by LED Class */ |
233 | EXPORT_SYMBOL_GPL(led_trigger_set); | 238 | EXPORT_SYMBOL_GPL(led_trigger_set); |
239 | EXPORT_SYMBOL_GPL(led_trigger_remove); | ||
234 | EXPORT_SYMBOL_GPL(led_trigger_set_default); | 240 | EXPORT_SYMBOL_GPL(led_trigger_set_default); |
235 | EXPORT_SYMBOL_GPL(led_trigger_show); | 241 | EXPORT_SYMBOL_GPL(led_trigger_show); |
236 | EXPORT_SYMBOL_GPL(led_trigger_store); | 242 | EXPORT_SYMBOL_GPL(led_trigger_store); |
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 12b6fe93b135..0214799639f7 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h | |||
@@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev, | |||
27 | led_cdev->brightness_set(led_cdev, value); | 27 | led_cdev->brightness_set(led_cdev, value); |
28 | } | 28 | } |
29 | 29 | ||
30 | static inline int led_get_brightness(struct led_classdev *led_cdev) | ||
31 | { | ||
32 | return led_cdev->brightness; | ||
33 | } | ||
34 | |||
30 | extern struct rw_semaphore leds_list_lock; | 35 | extern struct rw_semaphore leds_list_lock; |
31 | extern struct list_head leds_list; | 36 | extern struct list_head leds_list; |
32 | 37 | ||
@@ -34,9 +39,11 @@ extern struct list_head leds_list; | |||
34 | void led_trigger_set_default(struct led_classdev *led_cdev); | 39 | void led_trigger_set_default(struct led_classdev *led_cdev); |
35 | void led_trigger_set(struct led_classdev *led_cdev, | 40 | void led_trigger_set(struct led_classdev *led_cdev, |
36 | struct led_trigger *trigger); | 41 | struct led_trigger *trigger); |
42 | void led_trigger_remove(struct led_classdev *led_cdev); | ||
37 | #else | 43 | #else |
38 | #define led_trigger_set_default(x) do {} while(0) | 44 | #define led_trigger_set_default(x) do {} while(0) |
39 | #define led_trigger_set(x, y) do {} while(0) | 45 | #define led_trigger_set(x, y) do {} while(0) |
46 | #define led_trigger_remove(x) do {} while(0) | ||
40 | #endif | 47 | #endif |
41 | 48 | ||
42 | ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, | 49 | ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, |
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 82c55d6e4902..706297765d93 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include "leds.h" | 25 | #include "leds.h" |
26 | 26 | ||
27 | struct timer_trig_data { | 27 | struct timer_trig_data { |
28 | int brightness_on; /* LED brightness during "on" period. | ||
29 | * (LED_OFF < brightness_on <= LED_FULL) | ||
30 | */ | ||
28 | unsigned long delay_on; /* milliseconds on */ | 31 | unsigned long delay_on; /* milliseconds on */ |
29 | unsigned long delay_off; /* milliseconds off */ | 32 | unsigned long delay_off; /* milliseconds off */ |
30 | struct timer_list timer; | 33 | struct timer_list timer; |
@@ -34,17 +37,26 @@ static void led_timer_function(unsigned long data) | |||
34 | { | 37 | { |
35 | struct led_classdev *led_cdev = (struct led_classdev *) data; | 38 | struct led_classdev *led_cdev = (struct led_classdev *) data; |
36 | struct timer_trig_data *timer_data = led_cdev->trigger_data; | 39 | struct timer_trig_data *timer_data = led_cdev->trigger_data; |
37 | unsigned long brightness = LED_OFF; | 40 | unsigned long brightness; |
38 | unsigned long delay = timer_data->delay_off; | 41 | unsigned long delay; |
39 | 42 | ||
40 | if (!timer_data->delay_on || !timer_data->delay_off) { | 43 | if (!timer_data->delay_on || !timer_data->delay_off) { |
41 | led_set_brightness(led_cdev, LED_OFF); | 44 | led_set_brightness(led_cdev, LED_OFF); |
42 | return; | 45 | return; |
43 | } | 46 | } |
44 | 47 | ||
45 | if (!led_cdev->brightness) { | 48 | brightness = led_get_brightness(led_cdev); |
46 | brightness = LED_FULL; | 49 | if (!brightness) { |
50 | /* Time to switch the LED on. */ | ||
51 | brightness = timer_data->brightness_on; | ||
47 | delay = timer_data->delay_on; | 52 | delay = timer_data->delay_on; |
53 | } else { | ||
54 | /* Store the current brightness value to be able | ||
55 | * to restore it when the delay_off period is over. | ||
56 | */ | ||
57 | timer_data->brightness_on = brightness; | ||
58 | brightness = LED_OFF; | ||
59 | delay = timer_data->delay_off; | ||
48 | } | 60 | } |
49 | 61 | ||
50 | led_set_brightness(led_cdev, brightness); | 62 | led_set_brightness(led_cdev, brightness); |
@@ -156,6 +168,9 @@ static void timer_trig_activate(struct led_classdev *led_cdev) | |||
156 | if (!timer_data) | 168 | if (!timer_data) |
157 | return; | 169 | return; |
158 | 170 | ||
171 | timer_data->brightness_on = led_get_brightness(led_cdev); | ||
172 | if (timer_data->brightness_on == LED_OFF) | ||
173 | timer_data->brightness_on = LED_FULL; | ||
159 | led_cdev->trigger_data = timer_data; | 174 | led_cdev->trigger_data = timer_data; |
160 | 175 | ||
161 | init_timer(&timer_data->timer); | 176 | init_timer(&timer_data->timer); |