aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/leds-class.txt12
-rw-r--r--drivers/leds/Kconfig17
-rw-r--r--drivers/leds/Makefile2
-rw-r--r--drivers/leds/led-class.c12
-rw-r--r--drivers/leds/led-core.c4
-rw-r--r--drivers/leds/led-triggers.c120
-rw-r--r--drivers/leds/leds-clevo-mail.c16
-rw-r--r--drivers/leds/leds-cobalt-qube.c2
-rw-r--r--drivers/leds/leds-cobalt-raq.c6
-rw-r--r--drivers/leds/leds-corgi.c11
-rw-r--r--drivers/leds/leds-fsg.c261
-rw-r--r--drivers/leds/leds-gpio.c15
-rw-r--r--drivers/leds/leds-h1940.c64
-rw-r--r--drivers/leds/leds-hp6xx.c6
-rw-r--r--drivers/leds/leds-s3c24xx.c4
-rw-r--r--drivers/leds/leds-spitz.c11
-rw-r--r--drivers/leds/leds.h11
-rw-r--r--drivers/leds/ledtrig-default-on.c45
-rw-r--r--drivers/leds/ledtrig-ide-disk.c2
-rw-r--r--drivers/leds/ledtrig-timer.c35
-rw-r--r--include/linux/leds.h6
21 files changed, 536 insertions, 126 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/Kconfig b/drivers/leds/Kconfig
index eb97c4113d78..86a369bc57d6 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -65,6 +65,12 @@ config LEDS_NET48XX
65 This option enables support for the Soekris net4801 and net4826 error 65 This option enables support for the Soekris net4801 and net4826 error
66 LED. 66 LED.
67 67
68config LEDS_FSG
69 tristate "LED Support for the Freecom FSG-3"
70 depends on LEDS_CLASS && MACH_FSG
71 help
72 This option enables support for the LEDs on the Freecom FSG-3.
73
68config LEDS_WRAP 74config LEDS_WRAP
69 tristate "LED Support for the WRAP series LEDs" 75 tristate "LED Support for the WRAP series LEDs"
70 depends on LEDS_CLASS && SCx200_GPIO 76 depends on LEDS_CLASS && SCx200_GPIO
@@ -127,6 +133,7 @@ config LEDS_CLEVO_MAIL
127 133
128 This module can drive the mail LED for the following notebooks: 134 This module can drive the mail LED for the following notebooks:
129 135
136 Clevo D400P
130 Clevo D410J 137 Clevo D410J
131 Clevo D410V 138 Clevo D410V
132 Clevo D400V/D470V (not tested, but might work) 139 Clevo D400V/D470V (not tested, but might work)
@@ -134,6 +141,9 @@ config LEDS_CLEVO_MAIL
134 Clevo M5x0N (not tested, but might work) 141 Clevo M5x0N (not tested, but might work)
135 Positivo Mobile (Clevo M5x0V) 142 Positivo Mobile (Clevo M5x0V)
136 143
144 If your model is not listed here you can try the "nodetect"
145 module paramter.
146
137 To compile this driver as a module, choose M here: the 147 To compile this driver as a module, choose M here: the
138 module will be called leds-clevo-mail. 148 module will be called leds-clevo-mail.
139 149
@@ -173,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
173 load average. 183 load average.
174 If unsure, say Y. 184 If unsure, say Y.
175 185
186config LEDS_TRIGGER_DEFAULT_ON
187 tristate "LED Default ON Trigger"
188 depends on LEDS_TRIGGERS
189 help
190 This allows LEDs to be initialised in the ON state.
191 If unsure, say Y.
192
176endif # NEW_LEDS 193endif # NEW_LEDS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e54f42da21a2..973d626f5f4a 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -20,8 +20,10 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
20obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o 20obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
21obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 21obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
23obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
23 24
24# LED Triggers 25# LED Triggers
25obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 26obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
26obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o 27obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
27obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o 28obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
29obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 63aad90247c4..ac05a928f764 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -24,6 +24,12 @@
24 24
25static struct class *leds_class; 25static struct class *leds_class;
26 26
27static void led_update_brightness(struct led_classdev *led_cdev)
28{
29 if (led_cdev->brightness_get)
30 led_cdev->brightness = led_cdev->brightness_get(led_cdev);
31}
32
27static ssize_t led_brightness_show(struct device *dev, 33static ssize_t led_brightness_show(struct device *dev,
28 struct device_attribute *attr, char *buf) 34 struct device_attribute *attr, char *buf)
29{ 35{
@@ -31,6 +37,7 @@ static ssize_t led_brightness_show(struct device *dev,
31 ssize_t ret = 0; 37 ssize_t ret = 0;
32 38
33 /* no lock needed for this */ 39 /* no lock needed for this */
40 led_update_brightness(led_cdev);
34 sprintf(buf, "%u\n", led_cdev->brightness); 41 sprintf(buf, "%u\n", led_cdev->brightness);
35 ret = strlen(buf) + 1; 42 ret = strlen(buf) + 1;
36 43
@@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,
51 58
52 if (count == size) { 59 if (count == size) {
53 ret = count; 60 ret = count;
61
62 if (state == LED_OFF)
63 led_trigger_remove(led_cdev);
54 led_set_brightness(led_cdev, state); 64 led_set_brightness(led_cdev, state);
55 } 65 }
56 66
@@ -110,6 +120,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
110 list_add_tail(&led_cdev->node, &leds_list); 120 list_add_tail(&led_cdev->node, &leds_list);
111 up_write(&leds_list_lock); 121 up_write(&leds_list_lock);
112 122
123 led_update_brightness(led_cdev);
124
113#ifdef CONFIG_LEDS_TRIGGERS 125#ifdef CONFIG_LEDS_TRIGGERS
114 init_rwsem(&led_cdev->trigger_lock); 126 init_rwsem(&led_cdev->trigger_lock);
115 127
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 5d1ca10524b6..016d19f5486f 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -19,7 +19,7 @@
19#include "leds.h" 19#include "leds.h"
20 20
21DECLARE_RWSEM(leds_list_lock); 21DECLARE_RWSEM(leds_list_lock);
22LIST_HEAD(leds_list); 22EXPORT_SYMBOL_GPL(leds_list_lock);
23 23
24LIST_HEAD(leds_list);
24EXPORT_SYMBOL_GPL(leds_list); 25EXPORT_SYMBOL_GPL(leds_list);
25EXPORT_SYMBOL_GPL(leds_list_lock);
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 13c9026d68af..0f242b3f09b6 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -29,6 +29,8 @@
29static DECLARE_RWSEM(triggers_list_lock); 29static DECLARE_RWSEM(triggers_list_lock);
30static LIST_HEAD(trigger_list); 30static LIST_HEAD(trigger_list);
31 31
32 /* Used by LED Class */
33
32ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, 34ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
33 const char *buf, size_t count) 35 const char *buf, size_t count)
34{ 36{
@@ -45,9 +47,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
45 trigger_name[len - 1] = '\0'; 47 trigger_name[len - 1] = '\0';
46 48
47 if (!strcmp(trigger_name, "none")) { 49 if (!strcmp(trigger_name, "none")) {
48 down_write(&led_cdev->trigger_lock); 50 led_trigger_remove(led_cdev);
49 led_trigger_set(led_cdev, NULL);
50 up_write(&led_cdev->trigger_lock);
51 return count; 51 return count;
52 } 52 }
53 53
@@ -66,7 +66,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
66 66
67 return -EINVAL; 67 return -EINVAL;
68} 68}
69 69EXPORT_SYMBOL_GPL(led_trigger_store);
70 70
71ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, 71ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
72 char *buf) 72 char *buf)
@@ -96,24 +96,7 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
96 len += sprintf(len+buf, "\n"); 96 len += sprintf(len+buf, "\n");
97 return len; 97 return len;
98} 98}
99 99EXPORT_SYMBOL_GPL(led_trigger_show);
100void led_trigger_event(struct led_trigger *trigger,
101 enum led_brightness brightness)
102{
103 struct list_head *entry;
104
105 if (!trigger)
106 return;
107
108 read_lock(&trigger->leddev_list_lock);
109 list_for_each(entry, &trigger->led_cdevs) {
110 struct led_classdev *led_cdev;
111
112 led_cdev = list_entry(entry, struct led_classdev, trig_list);
113 led_set_brightness(led_cdev, brightness);
114 }
115 read_unlock(&trigger->leddev_list_lock);
116}
117 100
118/* Caller must ensure led_cdev->trigger_lock held */ 101/* Caller must ensure led_cdev->trigger_lock held */
119void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) 102void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
@@ -124,7 +107,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
124 if (led_cdev->trigger) { 107 if (led_cdev->trigger) {
125 write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); 108 write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
126 list_del(&led_cdev->trig_list); 109 list_del(&led_cdev->trig_list);
127 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); 110 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
111 flags);
128 if (led_cdev->trigger->deactivate) 112 if (led_cdev->trigger->deactivate)
129 led_cdev->trigger->deactivate(led_cdev); 113 led_cdev->trigger->deactivate(led_cdev);
130 led_set_brightness(led_cdev, LED_OFF); 114 led_set_brightness(led_cdev, LED_OFF);
@@ -138,6 +122,15 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
138 } 122 }
139 led_cdev->trigger = trigger; 123 led_cdev->trigger = trigger;
140} 124}
125EXPORT_SYMBOL_GPL(led_trigger_set);
126
127void led_trigger_remove(struct led_classdev *led_cdev)
128{
129 down_write(&led_cdev->trigger_lock);
130 led_trigger_set(led_cdev, NULL);
131 up_write(&led_cdev->trigger_lock);
132}
133EXPORT_SYMBOL_GPL(led_trigger_remove);
141 134
142void led_trigger_set_default(struct led_classdev *led_cdev) 135void led_trigger_set_default(struct led_classdev *led_cdev)
143{ 136{
@@ -155,6 +148,9 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
155 up_write(&led_cdev->trigger_lock); 148 up_write(&led_cdev->trigger_lock);
156 up_read(&triggers_list_lock); 149 up_read(&triggers_list_lock);
157} 150}
151EXPORT_SYMBOL_GPL(led_trigger_set_default);
152
153/* LED Trigger Interface */
158 154
159int led_trigger_register(struct led_trigger *trigger) 155int led_trigger_register(struct led_trigger *trigger)
160{ 156{
@@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)
181 177
182 return 0; 178 return 0;
183} 179}
184 180EXPORT_SYMBOL_GPL(led_trigger_register);
185void led_trigger_register_simple(const char *name, struct led_trigger **tp)
186{
187 struct led_trigger *trigger;
188 int err;
189
190 trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
191
192 if (trigger) {
193 trigger->name = name;
194 err = led_trigger_register(trigger);
195 if (err < 0)
196 printk(KERN_WARNING "LED trigger %s failed to register"
197 " (%d)\n", name, err);
198 } else
199 printk(KERN_WARNING "LED trigger %s failed to register"
200 " (no memory)\n", name);
201
202 *tp = trigger;
203}
204 181
205void led_trigger_unregister(struct led_trigger *trigger) 182void led_trigger_unregister(struct led_trigger *trigger)
206{ 183{
@@ -221,6 +198,49 @@ void led_trigger_unregister(struct led_trigger *trigger)
221 } 198 }
222 up_read(&leds_list_lock); 199 up_read(&leds_list_lock);
223} 200}
201EXPORT_SYMBOL_GPL(led_trigger_unregister);
202
203/* Simple LED Tigger Interface */
204
205void led_trigger_event(struct led_trigger *trigger,
206 enum led_brightness brightness)
207{
208 struct list_head *entry;
209
210 if (!trigger)
211 return;
212
213 read_lock(&trigger->leddev_list_lock);
214 list_for_each(entry, &trigger->led_cdevs) {
215 struct led_classdev *led_cdev;
216
217 led_cdev = list_entry(entry, struct led_classdev, trig_list);
218 led_set_brightness(led_cdev, brightness);
219 }
220 read_unlock(&trigger->leddev_list_lock);
221}
222EXPORT_SYMBOL_GPL(led_trigger_event);
223
224void led_trigger_register_simple(const char *name, struct led_trigger **tp)
225{
226 struct led_trigger *trigger;
227 int err;
228
229 trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
230
231 if (trigger) {
232 trigger->name = name;
233 err = led_trigger_register(trigger);
234 if (err < 0)
235 printk(KERN_WARNING "LED trigger %s failed to register"
236 " (%d)\n", name, err);
237 } else
238 printk(KERN_WARNING "LED trigger %s failed to register"
239 " (no memory)\n", name);
240
241 *tp = trigger;
242}
243EXPORT_SYMBOL_GPL(led_trigger_register_simple);
224 244
225void led_trigger_unregister_simple(struct led_trigger *trigger) 245void led_trigger_unregister_simple(struct led_trigger *trigger)
226{ 246{
@@ -228,21 +248,7 @@ void led_trigger_unregister_simple(struct led_trigger *trigger)
228 led_trigger_unregister(trigger); 248 led_trigger_unregister(trigger);
229 kfree(trigger); 249 kfree(trigger);
230} 250}
231
232/* Used by LED Class */
233EXPORT_SYMBOL_GPL(led_trigger_set);
234EXPORT_SYMBOL_GPL(led_trigger_set_default);
235EXPORT_SYMBOL_GPL(led_trigger_show);
236EXPORT_SYMBOL_GPL(led_trigger_store);
237
238/* LED Trigger Interface */
239EXPORT_SYMBOL_GPL(led_trigger_register);
240EXPORT_SYMBOL_GPL(led_trigger_unregister);
241
242/* Simple LED Tigger Interface */
243EXPORT_SYMBOL_GPL(led_trigger_register_simple);
244EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); 251EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
245EXPORT_SYMBOL_GPL(led_trigger_event);
246 252
247MODULE_AUTHOR("Richard Purdie"); 253MODULE_AUTHOR("Richard Purdie");
248MODULE_LICENSE("GPL"); 254MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index 5750b08b601f..eb3415e88f43 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -14,7 +14,7 @@
14#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A 14#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
15#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083 15#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
16 16
17MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>"); 17MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
18MODULE_DESCRIPTION("Clevo mail LED driver"); 18MODULE_DESCRIPTION("Clevo mail LED driver");
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20 20
@@ -69,6 +69,16 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
69 }, 69 },
70 { 70 {
71 .callback = clevo_mail_led_dmi_callback, 71 .callback = clevo_mail_led_dmi_callback,
72 .ident = "Clevo D400P",
73 .matches = {
74 DMI_MATCH(DMI_BOARD_VENDOR, "Clevo"),
75 DMI_MATCH(DMI_BOARD_NAME, "D400P"),
76 DMI_MATCH(DMI_BOARD_VERSION, "Rev.A"),
77 DMI_MATCH(DMI_PRODUCT_VERSION, "0106")
78 }
79 },
80 {
81 .callback = clevo_mail_led_dmi_callback,
72 .ident = "Clevo D410V", 82 .ident = "Clevo D410V",
73 .matches = { 83 .matches = {
74 DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."), 84 DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
@@ -93,8 +103,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev,
93} 103}
94 104
95static int clevo_mail_led_blink(struct led_classdev *led_cdev, 105static int clevo_mail_led_blink(struct led_classdev *led_cdev,
96 unsigned long* delay_on, 106 unsigned long *delay_on,
97 unsigned long* delay_off) 107 unsigned long *delay_off)
98{ 108{
99 int status = -EINVAL; 109 int status = -EINVAL;
100 110
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 096881a11b1a..059aa2924b1c 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -18,7 +18,7 @@ static void __iomem *led_port;
18static u8 led_value; 18static u8 led_value;
19 19
20static void qube_front_led_set(struct led_classdev *led_cdev, 20static void qube_front_led_set(struct led_classdev *led_cdev,
21 enum led_brightness brightness) 21 enum led_brightness brightness)
22{ 22{
23 if (brightness) 23 if (brightness)
24 led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT; 24 led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index 6ebfff341e6c..ff0e8c3fbf9b 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -15,7 +15,7 @@
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */ 19 */
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/io.h> 21#include <linux/io.h>
@@ -33,7 +33,7 @@ static u8 led_value;
33static DEFINE_SPINLOCK(led_value_lock); 33static DEFINE_SPINLOCK(led_value_lock);
34 34
35static void raq_web_led_set(struct led_classdev *led_cdev, 35static void raq_web_led_set(struct led_classdev *led_cdev,
36 enum led_brightness brightness) 36 enum led_brightness brightness)
37{ 37{
38 unsigned long flags; 38 unsigned long flags;
39 39
@@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
54}; 54};
55 55
56static void raq_power_off_led_set(struct led_classdev *led_cdev, 56static void raq_power_off_led_set(struct led_classdev *led_cdev,
57 enum led_brightness brightness) 57 enum led_brightness brightness)
58{ 58{
59 unsigned long flags; 59 unsigned long flags;
60 60
diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
index 29e931f89f9c..a709704b9f93 100644
--- a/drivers/leds/leds-corgi.c
+++ b/drivers/leds/leds-corgi.c
@@ -21,7 +21,8 @@
21#include <asm/arch/pxa-regs.h> 21#include <asm/arch/pxa-regs.h>
22#include <asm/hardware/scoop.h> 22#include <asm/hardware/scoop.h>
23 23
24static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) 24static void corgiled_amber_set(struct led_classdev *led_cdev,
25 enum led_brightness value)
25{ 26{
26 if (value) 27 if (value)
27 GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); 28 GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
@@ -29,7 +30,8 @@ static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
29 GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); 30 GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
30} 31}
31 32
32static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value) 33static void corgiled_green_set(struct led_classdev *led_cdev,
34 enum led_brightness value)
33{ 35{
34 if (value) 36 if (value)
35 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); 37 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
@@ -53,7 +55,8 @@ static struct led_classdev corgi_green_led = {
53static int corgiled_suspend(struct platform_device *dev, pm_message_t state) 55static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
54{ 56{
55#ifdef CONFIG_LEDS_TRIGGERS 57#ifdef CONFIG_LEDS_TRIGGERS
56 if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge")) 58 if (corgi_amber_led.trigger &&
59 strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
57#endif 60#endif
58 led_classdev_suspend(&corgi_amber_led); 61 led_classdev_suspend(&corgi_amber_led);
59 led_classdev_suspend(&corgi_green_led); 62 led_classdev_suspend(&corgi_green_led);
@@ -110,7 +113,7 @@ static int __init corgiled_init(void)
110 113
111static void __exit corgiled_exit(void) 114static void __exit corgiled_exit(void)
112{ 115{
113 platform_driver_unregister(&corgiled_driver); 116 platform_driver_unregister(&corgiled_driver);
114} 117}
115 118
116module_init(corgiled_init); 119module_init(corgiled_init);
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
new file mode 100644
index 000000000000..a7421b8c47d8
--- /dev/null
+++ b/drivers/leds/leds-fsg.c
@@ -0,0 +1,261 @@
1/*
2 * LED Driver for the Freecom FSG-3
3 *
4 * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au>
5 *
6 * Author: Rod Whitby <rod@whitby.id.au>
7 *
8 * Based on leds-spitz.c
9 * Copyright 2005-2006 Openedhand Ltd.
10 * Author: Richard Purdie <rpurdie@openedhand.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/platform_device.h>
21#include <linux/leds.h>
22#include <asm/arch/hardware.h>
23#include <asm/io.h>
24
25static short __iomem *latch_address;
26static unsigned short latch_value;
27
28
29static void fsg_led_wlan_set(struct led_classdev *led_cdev,
30 enum led_brightness value)
31{
32 if (value) {
33 latch_value &= ~(1 << FSG_LED_WLAN_BIT);
34 *latch_address = latch_value;
35 } else {
36 latch_value |= (1 << FSG_LED_WLAN_BIT);
37 *latch_address = latch_value;
38 }
39}
40
41static void fsg_led_wan_set(struct led_classdev *led_cdev,
42 enum led_brightness value)
43{
44 if (value) {
45 latch_value &= ~(1 << FSG_LED_WAN_BIT);
46 *latch_address = latch_value;
47 } else {
48 latch_value |= (1 << FSG_LED_WAN_BIT);
49 *latch_address = latch_value;
50 }
51}
52
53static void fsg_led_sata_set(struct led_classdev *led_cdev,
54 enum led_brightness value)
55{
56 if (value) {
57 latch_value &= ~(1 << FSG_LED_SATA_BIT);
58 *latch_address = latch_value;
59 } else {
60 latch_value |= (1 << FSG_LED_SATA_BIT);
61 *latch_address = latch_value;
62 }
63}
64
65static void fsg_led_usb_set(struct led_classdev *led_cdev,
66 enum led_brightness value)
67{
68 if (value) {
69 latch_value &= ~(1 << FSG_LED_USB_BIT);
70 *latch_address = latch_value;
71 } else {
72 latch_value |= (1 << FSG_LED_USB_BIT);
73 *latch_address = latch_value;
74 }
75}
76
77static void fsg_led_sync_set(struct led_classdev *led_cdev,
78 enum led_brightness value)
79{
80 if (value) {
81 latch_value &= ~(1 << FSG_LED_SYNC_BIT);
82 *latch_address = latch_value;
83 } else {
84 latch_value |= (1 << FSG_LED_SYNC_BIT);
85 *latch_address = latch_value;
86 }
87}
88
89static void fsg_led_ring_set(struct led_classdev *led_cdev,
90 enum led_brightness value)
91{
92 if (value) {
93 latch_value &= ~(1 << FSG_LED_RING_BIT);
94 *latch_address = latch_value;
95 } else {
96 latch_value |= (1 << FSG_LED_RING_BIT);
97 *latch_address = latch_value;
98 }
99}
100
101
102
103static struct led_classdev fsg_wlan_led = {
104 .name = "fsg:blue:wlan",
105 .brightness_set = fsg_led_wlan_set,
106};
107
108static struct led_classdev fsg_wan_led = {
109 .name = "fsg:blue:wan",
110 .brightness_set = fsg_led_wan_set,
111};
112
113static struct led_classdev fsg_sata_led = {
114 .name = "fsg:blue:sata",
115 .brightness_set = fsg_led_sata_set,
116};
117
118static struct led_classdev fsg_usb_led = {
119 .name = "fsg:blue:usb",
120 .brightness_set = fsg_led_usb_set,
121};
122
123static struct led_classdev fsg_sync_led = {
124 .name = "fsg:blue:sync",
125 .brightness_set = fsg_led_sync_set,
126};
127
128static struct led_classdev fsg_ring_led = {
129 .name = "fsg:blue:ring",
130 .brightness_set = fsg_led_ring_set,
131};
132
133
134
135#ifdef CONFIG_PM
136static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
137{
138 led_classdev_suspend(&fsg_wlan_led);
139 led_classdev_suspend(&fsg_wan_led);
140 led_classdev_suspend(&fsg_sata_led);
141 led_classdev_suspend(&fsg_usb_led);
142 led_classdev_suspend(&fsg_sync_led);
143 led_classdev_suspend(&fsg_ring_led);
144 return 0;
145}
146
147static int fsg_led_resume(struct platform_device *dev)
148{
149 led_classdev_resume(&fsg_wlan_led);
150 led_classdev_resume(&fsg_wan_led);
151 led_classdev_resume(&fsg_sata_led);
152 led_classdev_resume(&fsg_usb_led);
153 led_classdev_resume(&fsg_sync_led);
154 led_classdev_resume(&fsg_ring_led);
155 return 0;
156}
157#endif
158
159
160static int fsg_led_probe(struct platform_device *pdev)
161{
162 int ret;
163
164 ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
165 if (ret < 0)
166 goto failwlan;
167
168 ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
169 if (ret < 0)
170 goto failwan;
171
172 ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
173 if (ret < 0)
174 goto failsata;
175
176 ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
177 if (ret < 0)
178 goto failusb;
179
180 ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
181 if (ret < 0)
182 goto failsync;
183
184 ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
185 if (ret < 0)
186 goto failring;
187
188 /* Map the LED chip select address space */
189 latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
190 if (!latch_address) {
191 ret = -ENOMEM;
192 goto failremap;
193 }
194
195 latch_value = 0xffff;
196 *latch_address = latch_value;
197
198 return ret;
199
200 failremap:
201 led_classdev_unregister(&fsg_ring_led);
202 failring:
203 led_classdev_unregister(&fsg_sync_led);
204 failsync:
205 led_classdev_unregister(&fsg_usb_led);
206 failusb:
207 led_classdev_unregister(&fsg_sata_led);
208 failsata:
209 led_classdev_unregister(&fsg_wan_led);
210 failwan:
211 led_classdev_unregister(&fsg_wlan_led);
212 failwlan:
213
214 return ret;
215}
216
217static int fsg_led_remove(struct platform_device *pdev)
218{
219 iounmap(latch_address);
220
221 led_classdev_unregister(&fsg_wlan_led);
222 led_classdev_unregister(&fsg_wan_led);
223 led_classdev_unregister(&fsg_sata_led);
224 led_classdev_unregister(&fsg_usb_led);
225 led_classdev_unregister(&fsg_sync_led);
226 led_classdev_unregister(&fsg_ring_led);
227
228 return 0;
229}
230
231
232static struct platform_driver fsg_led_driver = {
233 .probe = fsg_led_probe,
234 .remove = fsg_led_remove,
235#ifdef CONFIG_PM
236 .suspend = fsg_led_suspend,
237 .resume = fsg_led_resume,
238#endif
239 .driver = {
240 .name = "fsg-led",
241 },
242};
243
244
245static int __init fsg_led_init(void)
246{
247 return platform_driver_register(&fsg_led_driver);
248}
249
250static void __exit fsg_led_exit(void)
251{
252 platform_driver_unregister(&fsg_led_driver);
253}
254
255
256module_init(fsg_led_init);
257module_exit(fsg_led_exit);
258
259MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
260MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
261MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 1aae8b332134..b13bd2950e95 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -24,6 +24,8 @@ struct gpio_led_data {
24 u8 new_level; 24 u8 new_level;
25 u8 can_sleep; 25 u8 can_sleep;
26 u8 active_low; 26 u8 active_low;
27 int (*platform_gpio_blink_set)(unsigned gpio,
28 unsigned long *delay_on, unsigned long *delay_off);
27}; 29};
28 30
29static void gpio_led_work(struct work_struct *work) 31static void gpio_led_work(struct work_struct *work)
@@ -60,6 +62,15 @@ static void gpio_led_set(struct led_classdev *led_cdev,
60 gpio_set_value(led_dat->gpio, level); 62 gpio_set_value(led_dat->gpio, level);
61} 63}
62 64
65static int gpio_blink_set(struct led_classdev *led_cdev,
66 unsigned long *delay_on, unsigned long *delay_off)
67{
68 struct gpio_led_data *led_dat =
69 container_of(led_cdev, struct gpio_led_data, cdev);
70
71 return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off);
72}
73
63static int gpio_led_probe(struct platform_device *pdev) 74static int gpio_led_probe(struct platform_device *pdev)
64{ 75{
65 struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 76 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
@@ -88,6 +99,10 @@ static int gpio_led_probe(struct platform_device *pdev)
88 led_dat->gpio = cur_led->gpio; 99 led_dat->gpio = cur_led->gpio;
89 led_dat->can_sleep = gpio_cansleep(cur_led->gpio); 100 led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
90 led_dat->active_low = cur_led->active_low; 101 led_dat->active_low = cur_led->active_low;
102 if (pdata->gpio_blink_set) {
103 led_dat->platform_gpio_blink_set = pdata->gpio_blink_set;
104 led_dat->cdev.blink_set = gpio_blink_set;
105 }
91 led_dat->cdev.brightness_set = gpio_led_set; 106 led_dat->cdev.brightness_set = gpio_led_set;
92 led_dat->cdev.brightness = LED_OFF; 107 led_dat->cdev.brightness = LED_OFF;
93 108
diff --git a/drivers/leds/leds-h1940.c b/drivers/leds/leds-h1940.c
index 6e51c9b61027..bcec42230389 100644
--- a/drivers/leds/leds-h1940.c
+++ b/drivers/leds/leds-h1940.c
@@ -26,20 +26,20 @@
26void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value) 26void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
27{ 27{
28 switch (value) { 28 switch (value) {
29 case LED_HALF: 29 case LED_HALF:
30 h1940_latch_control(0,H1940_LATCH_LED_FLASH); 30 h1940_latch_control(0, H1940_LATCH_LED_FLASH);
31 s3c2410_gpio_setpin(S3C2410_GPA7,1); 31 s3c2410_gpio_setpin(S3C2410_GPA7, 1);
32 break; 32 break;
33 case LED_FULL: 33 case LED_FULL:
34 h1940_latch_control(0,H1940_LATCH_LED_GREEN); 34 h1940_latch_control(0, H1940_LATCH_LED_GREEN);
35 s3c2410_gpio_setpin(S3C2410_GPA7,1); 35 s3c2410_gpio_setpin(S3C2410_GPA7, 1);
36 break; 36 break;
37 default: 37 default:
38 case LED_OFF: 38 case LED_OFF:
39 h1940_latch_control(H1940_LATCH_LED_FLASH,0); 39 h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
40 h1940_latch_control(H1940_LATCH_LED_GREEN,0); 40 h1940_latch_control(H1940_LATCH_LED_GREEN, 0);
41 s3c2410_gpio_setpin(S3C2410_GPA7,0); 41 s3c2410_gpio_setpin(S3C2410_GPA7, 0);
42 break; 42 break;
43 } 43 }
44} 44}
45 45
@@ -55,20 +55,20 @@ static struct led_classdev h1940_greenled = {
55void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value) 55void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
56{ 56{
57 switch (value) { 57 switch (value) {
58 case LED_HALF: 58 case LED_HALF:
59 h1940_latch_control(0,H1940_LATCH_LED_FLASH); 59 h1940_latch_control(0, H1940_LATCH_LED_FLASH);
60 s3c2410_gpio_setpin(S3C2410_GPA1,1); 60 s3c2410_gpio_setpin(S3C2410_GPA1, 1);
61 break; 61 break;
62 case LED_FULL: 62 case LED_FULL:
63 h1940_latch_control(0,H1940_LATCH_LED_RED); 63 h1940_latch_control(0, H1940_LATCH_LED_RED);
64 s3c2410_gpio_setpin(S3C2410_GPA1,1); 64 s3c2410_gpio_setpin(S3C2410_GPA1, 1);
65 break; 65 break;
66 default: 66 default:
67 case LED_OFF: 67 case LED_OFF:
68 h1940_latch_control(H1940_LATCH_LED_FLASH,0); 68 h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
69 h1940_latch_control(H1940_LATCH_LED_RED,0); 69 h1940_latch_control(H1940_LATCH_LED_RED, 0);
70 s3c2410_gpio_setpin(S3C2410_GPA1,0); 70 s3c2410_gpio_setpin(S3C2410_GPA1, 0);
71 break; 71 break;
72 } 72 }
73} 73}
74 74
@@ -86,11 +86,11 @@ void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
86{ 86{
87 if (value) { 87 if (value) {
88 /* flashing Blue */ 88 /* flashing Blue */
89 h1940_latch_control(0,H1940_LATCH_LED_FLASH); 89 h1940_latch_control(0, H1940_LATCH_LED_FLASH);
90 s3c2410_gpio_setpin(S3C2410_GPA3,1); 90 s3c2410_gpio_setpin(S3C2410_GPA3, 1);
91 } else { 91 } else {
92 h1940_latch_control(H1940_LATCH_LED_FLASH,0); 92 h1940_latch_control(H1940_LATCH_LED_FLASH, 0);
93 s3c2410_gpio_setpin(S3C2410_GPA3,0); 93 s3c2410_gpio_setpin(S3C2410_GPA3, 0);
94 } 94 }
95 95
96} 96}
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index 870f5a3789e8..844d5979c904 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -17,7 +17,8 @@
17#include <asm/hd64461.h> 17#include <asm/hd64461.h>
18#include <asm/hp6xx.h> 18#include <asm/hp6xx.h>
19 19
20static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value) 20static void hp6xxled_green_set(struct led_classdev *led_cdev,
21 enum led_brightness value)
21{ 22{
22 u8 v8; 23 u8 v8;
23 24
@@ -28,7 +29,8 @@ static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightnes
28 outb(v8 | PKDR_LED_GREEN, PKDR); 29 outb(v8 | PKDR_LED_GREEN, PKDR);
29} 30}
30 31
31static void hp6xxled_red_set(struct led_classdev *led_cdev, enum led_brightness value) 32static void hp6xxled_red_set(struct led_classdev *led_cdev,
33 enum led_brightness value)
32{ 34{
33 u16 v16; 35 u16 v16;
34 36
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 0d10e119d8f5..d4f5021dccbf 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -51,7 +51,7 @@ static void s3c24xx_led_set(struct led_classdev *led_cdev,
51 51
52 if (pd->flags & S3C24XX_LEDF_TRISTATE) 52 if (pd->flags & S3C24XX_LEDF_TRISTATE)
53 s3c2410_gpio_cfgpin(pd->gpio, 53 s3c2410_gpio_cfgpin(pd->gpio,
54 value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT); 54 value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
55 55
56} 56}
57 57
@@ -151,7 +151,7 @@ static int __init s3c24xx_led_init(void)
151 151
152static void __exit s3c24xx_led_exit(void) 152static void __exit s3c24xx_led_exit(void)
153{ 153{
154 platform_driver_unregister(&s3c24xx_led_driver); 154 platform_driver_unregister(&s3c24xx_led_driver);
155} 155}
156 156
157module_init(s3c24xx_led_init); 157module_init(s3c24xx_led_init);
diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
index 87007cc362c1..e75e8543bc5a 100644
--- a/drivers/leds/leds-spitz.c
+++ b/drivers/leds/leds-spitz.c
@@ -21,7 +21,8 @@
21#include <asm/arch/pxa-regs.h> 21#include <asm/arch/pxa-regs.h>
22#include <asm/arch/spitz.h> 22#include <asm/arch/spitz.h>
23 23
24static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) 24static void spitzled_amber_set(struct led_classdev *led_cdev,
25 enum led_brightness value)
25{ 26{
26 if (value) 27 if (value)
27 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); 28 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
@@ -29,7 +30,8 @@ static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightnes
29 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); 30 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
30} 31}
31 32
32static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value) 33static void spitzled_green_set(struct led_classdev *led_cdev,
34 enum led_brightness value)
33{ 35{
34 if (value) 36 if (value)
35 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); 37 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
@@ -53,7 +55,8 @@ static struct led_classdev spitz_green_led = {
53static int spitzled_suspend(struct platform_device *dev, pm_message_t state) 55static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
54{ 56{
55#ifdef CONFIG_LEDS_TRIGGERS 57#ifdef CONFIG_LEDS_TRIGGERS
56 if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge")) 58 if (spitz_amber_led.trigger &&
59 strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
57#endif 60#endif
58 led_classdev_suspend(&spitz_amber_led); 61 led_classdev_suspend(&spitz_amber_led);
59 led_classdev_suspend(&spitz_green_led); 62 led_classdev_suspend(&spitz_green_led);
@@ -116,7 +119,7 @@ static int __init spitzled_init(void)
116 119
117static void __exit spitzled_exit(void) 120static void __exit spitzled_exit(void)
118{ 121{
119 platform_driver_unregister(&spitzled_driver); 122 platform_driver_unregister(&spitzled_driver);
120} 123}
121 124
122module_init(spitzled_init); 125module_init(spitzled_init);
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 12b6fe93b135..5edbf52c4fa7 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-default-on.c b/drivers/leds/ledtrig-default-on.c
new file mode 100644
index 000000000000..92995e40cfa4
--- /dev/null
+++ b/drivers/leds/ledtrig-default-on.c
@@ -0,0 +1,45 @@
1/*
2 * LED Kernel Default ON Trigger
3 *
4 * Copyright 2008 Nick Forbes <nick.forbes@incepta.com>
5 *
6 * Based on Richard Purdie's ledtrig-timer.c.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/leds.h>
18#include "leds.h"
19
20static void defon_trig_activate(struct led_classdev *led_cdev)
21{
22 led_set_brightness(led_cdev, LED_FULL);
23}
24
25static struct led_trigger defon_led_trigger = {
26 .name = "default-on",
27 .activate = defon_trig_activate,
28};
29
30static int __init defon_trig_init(void)
31{
32 return led_trigger_register(&defon_led_trigger);
33}
34
35static void __exit defon_trig_exit(void)
36{
37 led_trigger_unregister(&defon_led_trigger);
38}
39
40module_init(defon_trig_init);
41module_exit(defon_trig_exit);
42
43MODULE_AUTHOR("Nick Forbes <nick.forbes@incepta.com>");
44MODULE_DESCRIPTION("Default-ON LED trigger");
45MODULE_LICENSE("GPL");
diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c
index 54b155c7026f..883a577b1b97 100644
--- a/drivers/leds/ledtrig-ide-disk.c
+++ b/drivers/leds/ledtrig-ide-disk.c
@@ -38,7 +38,7 @@ static void ledtrig_ide_timerfunc(unsigned long data)
38 if (ide_lastactivity != ide_activity) { 38 if (ide_lastactivity != ide_activity) {
39 ide_lastactivity = ide_activity; 39 ide_lastactivity = ide_activity;
40 led_trigger_event(ledtrig_ide, LED_FULL); 40 led_trigger_event(ledtrig_ide, LED_FULL);
41 mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); 41 mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
42 } else { 42 } else {
43 led_trigger_event(ledtrig_ide, LED_OFF); 43 led_trigger_event(ledtrig_ide, LED_OFF);
44 } 44 }
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index 82c55d6e4902..5c99f4f0c692 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);
@@ -52,7 +64,7 @@ static void led_timer_function(unsigned long data)
52 mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); 64 mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
53} 65}
54 66
55static ssize_t led_delay_on_show(struct device *dev, 67static ssize_t led_delay_on_show(struct device *dev,
56 struct device_attribute *attr, char *buf) 68 struct device_attribute *attr, char *buf)
57{ 69{
58 struct led_classdev *led_cdev = dev_get_drvdata(dev); 70 struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -63,7 +75,7 @@ static ssize_t led_delay_on_show(struct device *dev,
63 return strlen(buf) + 1; 75 return strlen(buf) + 1;
64} 76}
65 77
66static ssize_t led_delay_on_store(struct device *dev, 78static ssize_t led_delay_on_store(struct device *dev,
67 struct device_attribute *attr, const char *buf, size_t size) 79 struct device_attribute *attr, const char *buf, size_t size)
68{ 80{
69 struct led_classdev *led_cdev = dev_get_drvdata(dev); 81 struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -87,7 +99,7 @@ static ssize_t led_delay_on_store(struct device *dev,
87 /* try to activate hardware acceleration, if any */ 99 /* try to activate hardware acceleration, if any */
88 if (!led_cdev->blink_set || 100 if (!led_cdev->blink_set ||
89 led_cdev->blink_set(led_cdev, 101 led_cdev->blink_set(led_cdev,
90 &timer_data->delay_on, &timer_data->delay_off)) { 102 &timer_data->delay_on, &timer_data->delay_off)) {
91 /* no hardware acceleration, blink via timer */ 103 /* no hardware acceleration, blink via timer */
92 mod_timer(&timer_data->timer, jiffies + 1); 104 mod_timer(&timer_data->timer, jiffies + 1);
93 } 105 }
@@ -98,7 +110,7 @@ static ssize_t led_delay_on_store(struct device *dev,
98 return ret; 110 return ret;
99} 111}
100 112
101static ssize_t led_delay_off_show(struct device *dev, 113static ssize_t led_delay_off_show(struct device *dev,
102 struct device_attribute *attr, char *buf) 114 struct device_attribute *attr, char *buf)
103{ 115{
104 struct led_classdev *led_cdev = dev_get_drvdata(dev); 116 struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -109,7 +121,7 @@ static ssize_t led_delay_off_show(struct device *dev,
109 return strlen(buf) + 1; 121 return strlen(buf) + 1;
110} 122}
111 123
112static ssize_t led_delay_off_store(struct device *dev, 124static ssize_t led_delay_off_store(struct device *dev,
113 struct device_attribute *attr, const char *buf, size_t size) 125 struct device_attribute *attr, const char *buf, size_t size)
114{ 126{
115 struct led_classdev *led_cdev = dev_get_drvdata(dev); 127 struct led_classdev *led_cdev = dev_get_drvdata(dev);
@@ -133,7 +145,7 @@ static ssize_t led_delay_off_store(struct device *dev,
133 /* try to activate hardware acceleration, if any */ 145 /* try to activate hardware acceleration, if any */
134 if (!led_cdev->blink_set || 146 if (!led_cdev->blink_set ||
135 led_cdev->blink_set(led_cdev, 147 led_cdev->blink_set(led_cdev,
136 &timer_data->delay_on, &timer_data->delay_off)) { 148 &timer_data->delay_on, &timer_data->delay_off)) {
137 /* no hardware acceleration, blink via timer */ 149 /* no hardware acceleration, blink via timer */
138 mod_timer(&timer_data->timer, jiffies + 1); 150 mod_timer(&timer_data->timer, jiffies + 1);
139 } 151 }
@@ -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);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index b07e3d400bd6..519df72e939d 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -35,8 +35,11 @@ struct led_classdev {
35#define LED_SUSPENDED (1 << 0) 35#define LED_SUSPENDED (1 << 0)
36 36
37 /* Set LED brightness level */ 37 /* Set LED brightness level */
38 /* Must not sleep, use a workqueue if needed */
38 void (*brightness_set)(struct led_classdev *led_cdev, 39 void (*brightness_set)(struct led_classdev *led_cdev,
39 enum led_brightness brightness); 40 enum led_brightness brightness);
41 /* Get LED brightness level */
42 enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
40 43
41 /* Activate hardware accelerated blink */ 44 /* Activate hardware accelerated blink */
42 int (*blink_set)(struct led_classdev *led_cdev, 45 int (*blink_set)(struct led_classdev *led_cdev,
@@ -126,6 +129,9 @@ struct gpio_led {
126struct gpio_led_platform_data { 129struct gpio_led_platform_data {
127 int num_leds; 130 int num_leds;
128 struct gpio_led *leds; 131 struct gpio_led *leds;
132 int (*gpio_blink_set)(unsigned gpio,
133 unsigned long *delay_on,
134 unsigned long *delay_off);
129}; 135};
130 136
131 137