aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNémeth Márton <nm127@freemail.hu>2008-03-09 16:54:37 -0400
committerRichard Purdie <rpurdie@rpsys.net>2008-04-24 18:34:18 -0400
commit0013b23d66a2768f5babbb0ea9f03ab067a990d8 (patch)
tree14d60a50bb68e422767a268cd737f70ef4e6e19d
parentb3ba31f84ea041c0945b5904d4c407ce14b2b72c (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.txt12
-rw-r--r--drivers/leds/led-class.c3
-rw-r--r--drivers/leds/led-triggers.c12
-rw-r--r--drivers/leds/leds.h7
-rw-r--r--drivers/leds/ledtrig-timer.c23
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
20Complex triggers whilst available to all LEDs have LED specific 20Complex triggers whilst available to all LEDs have LED specific
21parameters and work on a per LED basis. The timer trigger is an example. 21parameters and work on a per LED basis. The timer trigger is an example.
22The timer trigger will periodically change the LED brightness between
23LED_OFF and the current brightness setting. The "on" and "off" time can
24be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
25You can change the brightness value of a LED independently of the timer
26trigger. However, if you set the brightness value to LED_OFF it will
27also disable the timer trigger.
22 28
23You can change triggers in a similar manner to the way an IO scheduler 29You can change triggers in a similar manner to the way an IO scheduler
24is chosen (via /sys/class/leds/<device>/trigger). Trigger specific 30is 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
63this case the driver should give back the chosen value through delay_on 69this case the driver should give back the chosen value through delay_on
64and delay_off parameters to the leds subsystem. 70and delay_off parameters to the leds subsystem.
65 71
66Any call to the brightness_set() callback function should cancel the 72Setting the brightness to zero with brightness_set() callback function
67previously programmed hardware blinking function so setting the brightness 73should completely turn off the LED and cancel the previously programmed
68to 0 can also cancel the blinking of the LED. 74hardware blinking function, if any.
69 75
70 76
71Known Issues 77Known 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
140void 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
142void led_trigger_set_default(struct led_classdev *led_cdev) 147void 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 */
233EXPORT_SYMBOL_GPL(led_trigger_set); 238EXPORT_SYMBOL_GPL(led_trigger_set);
239EXPORT_SYMBOL_GPL(led_trigger_remove);
234EXPORT_SYMBOL_GPL(led_trigger_set_default); 240EXPORT_SYMBOL_GPL(led_trigger_set_default);
235EXPORT_SYMBOL_GPL(led_trigger_show); 241EXPORT_SYMBOL_GPL(led_trigger_show);
236EXPORT_SYMBOL_GPL(led_trigger_store); 242EXPORT_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
30static inline int led_get_brightness(struct led_classdev *led_cdev)
31{
32 return led_cdev->brightness;
33}
34
30extern struct rw_semaphore leds_list_lock; 35extern struct rw_semaphore leds_list_lock;
31extern struct list_head leds_list; 36extern struct list_head leds_list;
32 37
@@ -34,9 +39,11 @@ extern struct list_head leds_list;
34void led_trigger_set_default(struct led_classdev *led_cdev); 39void led_trigger_set_default(struct led_classdev *led_cdev);
35void led_trigger_set(struct led_classdev *led_cdev, 40void led_trigger_set(struct led_classdev *led_cdev,
36 struct led_trigger *trigger); 41 struct led_trigger *trigger);
42void 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
42ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, 49ssize_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
27struct timer_trig_data { 27struct 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);