aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/leds-class.txt29
-rw-r--r--arch/arm/mach-ixp4xx/dsmg600-setup.c4
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c6
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c8
-rw-r--r--drivers/hwmon/applesmc.c2
-rw-r--r--drivers/input/misc/wistron_btns.c4
-rw-r--r--drivers/leds/Kconfig48
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/leds-ams-delta.c12
-rw-r--r--drivers/leds/leds-clevo-mail.c219
-rw-r--r--drivers/leds/leds-corgi.c4
-rw-r--r--drivers/leds/leds-gpio.c2
-rw-r--r--drivers/leds/leds-hp6xx.c120
-rw-r--r--drivers/leds/leds-ixp4xx-gpio.c214
-rw-r--r--drivers/leds/leds-locomo.c4
-rw-r--r--drivers/leds/leds-net48xx.c2
-rw-r--r--drivers/leds/leds-spitz.c8
-rw-r--r--drivers/leds/leds-tosa.c4
-rw-r--r--drivers/leds/leds-wrap.c47
-rw-r--r--drivers/leds/ledtrig-timer.c41
-rw-r--r--drivers/misc/asus-laptop.c2
-rw-r--r--drivers/net/wireless/b43/leds.c8
-rw-r--r--include/linux/leds.h5
23 files changed, 519 insertions, 277 deletions
diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt
index 8c35c0426110..56757c751d6f 100644
--- a/Documentation/leds-class.txt
+++ b/Documentation/leds-class.txt
@@ -39,12 +39,33 @@ LED Device Naming
39 39
40Is currently of the form: 40Is currently of the form:
41 41
42"devicename:colour" 42"devicename:colour:function"
43 43
44There have been calls for LED properties such as colour to be exported as 44There have been calls for LED properties such as colour to be exported as
45individual led class attributes. As a solution which doesn't incur as much 45individual led class attributes. As a solution which doesn't incur as much
46overhead, I suggest these become part of the device name. The naming scheme 46overhead, I suggest these become part of the device name. The naming scheme
47above leaves scope for further attributes should they be needed. 47above leaves scope for further attributes should they be needed. If sections
48of the name don't apply, just leave that section blank.
49
50
51Hardware accelerated blink of LEDs
52==================================
53
54Some LEDs can be programmed to blink without any CPU interaction. To
55support this feature, a LED driver can optionally implement the
56blink_set() function (see <linux/leds.h>). If implemeted, triggers can
57attempt to use it before falling back to software timers. The blink_set()
58function should return 0 if the blink setting is supported, or -EINVAL
59otherwise, which means that LED blinking will be handled by software.
60
61The blink_set() function should choose a user friendly blinking
62value 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
64and delay_off parameters to the leds subsystem.
65
66Any call to the brightness_set() callback function should cancel the
67previously programmed hardware blinking function so setting the brightness
68to 0 can also cancel the blinking of the LED.
48 69
49 70
50Known Issues 71Known Issues
@@ -55,10 +76,6 @@ would cause nightmare dependency issues. I see this as a minor issue
55compared to the benefits the simple trigger functionality brings. The 76compared to the benefits the simple trigger functionality brings. The
56rest of the LED subsystem can be modular. 77rest of the LED subsystem can be modular.
57 78
58Some leds can be programmed to flash in hardware. As this isn't a generic
59LED device property, this should be exported as a device specific sysfs
60attribute rather than part of the class if this functionality is required.
61
62 79
63Future Development 80Future Development
64================== 81==================
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 688659668bdf..8cb07437a807 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -71,11 +71,11 @@ static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
71 71
72static struct gpio_led dsmg600_led_pins[] = { 72static struct gpio_led dsmg600_led_pins[] = {
73 { 73 {
74 .name = "power", 74 .name = "dsmg600:green:power",
75 .gpio = DSMG600_LED_PWR_GPIO, 75 .gpio = DSMG600_LED_PWR_GPIO,
76 }, 76 },
77 { 77 {
78 .name = "wlan", 78 .name = "dsmg600:green:wlan",
79 .gpio = DSMG600_LED_WLAN_GPIO, 79 .gpio = DSMG600_LED_WLAN_GPIO,
80 .active_low = true, 80 .active_low = true,
81 }, 81 },
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 4cecae84837b..159e1c4f1eda 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -60,17 +60,17 @@ static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
60 60
61static struct gpio_led nas100d_led_pins[] = { 61static struct gpio_led nas100d_led_pins[] = {
62 { 62 {
63 .name = "wlan", /* green led */ 63 .name = "nas100d:green:wlan",
64 .gpio = NAS100D_LED_WLAN_GPIO, 64 .gpio = NAS100D_LED_WLAN_GPIO,
65 .active_low = true, 65 .active_low = true,
66 }, 66 },
67 { 67 {
68 .name = "power", /* blue power led (off=flashing) */ 68 .name = "nas100d:blue:power", /* (off=flashing) */
69 .gpio = NAS100D_LED_PWR_GPIO, 69 .gpio = NAS100D_LED_PWR_GPIO,
70 .active_low = true, 70 .active_low = true,
71 }, 71 },
72 { 72 {
73 .name = "disk", /* yellow led */ 73 .name = "nas100d:yellow:disk",
74 .gpio = NAS100D_LED_DISK_GPIO, 74 .gpio = NAS100D_LED_DISK_GPIO,
75 .active_low = true, 75 .active_low = true,
76 }, 76 },
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index acaebcbce53a..d9a182895a0f 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -63,20 +63,20 @@ static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
63 63
64static struct gpio_led nslu2_led_pins[] = { 64static struct gpio_led nslu2_led_pins[] = {
65 { 65 {
66 .name = "ready", /* green led */ 66 .name = "nslu2:green:ready",
67 .gpio = NSLU2_LED_GRN_GPIO, 67 .gpio = NSLU2_LED_GRN_GPIO,
68 }, 68 },
69 { 69 {
70 .name = "status", /* red led */ 70 .name = "nslu2:red:status",
71 .gpio = NSLU2_LED_RED_GPIO, 71 .gpio = NSLU2_LED_RED_GPIO,
72 }, 72 },
73 { 73 {
74 .name = "disk-1", 74 .name = "nslu2:green:disk-1",
75 .gpio = NSLU2_LED_DISK1_GPIO, 75 .gpio = NSLU2_LED_DISK1_GPIO,
76 .active_low = true, 76 .active_low = true,
77 }, 77 },
78 { 78 {
79 .name = "disk-2", 79 .name = "nslu2:green:disk-2",
80 .gpio = NSLU2_LED_DISK2_GPIO, 80 .gpio = NSLU2_LED_DISK2_GPIO,
81 .active_low = true, 81 .active_low = true,
82 }, 82 },
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 86c66c345f8b..0c94770b7f83 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -905,7 +905,7 @@ static ssize_t applesmc_key_at_index_store(struct device *dev,
905} 905}
906 906
907static struct led_classdev applesmc_backlight = { 907static struct led_classdev applesmc_backlight = {
908 .name = "smc:kbd_backlight", 908 .name = "smc::kbd_backlight",
909 .default_trigger = "nand-disk", 909 .default_trigger = "nand-disk",
910 .brightness_set = applesmc_brightness_set, 910 .brightness_set = applesmc_brightness_set,
911}; 911};
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index b438d998625c..72176f3d49cb 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -998,12 +998,12 @@ static void wistron_wifi_led_set(struct led_classdev *led_cdev,
998} 998}
999 999
1000static struct led_classdev wistron_mail_led = { 1000static struct led_classdev wistron_mail_led = {
1001 .name = "mail:green", 1001 .name = "wistron:green:mail",
1002 .brightness_set = wistron_mail_led_set, 1002 .brightness_set = wistron_mail_led_set,
1003}; 1003};
1004 1004
1005static struct led_classdev wistron_wifi_led = { 1005static struct led_classdev wistron_wifi_led = {
1006 .name = "wifi:red", 1006 .name = "wistron:red:wifi",
1007 .brightness_set = wistron_wifi_led_set, 1007 .brightness_set = wistron_wifi_led_set,
1008}; 1008};
1009 1009
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index ec568fa1c6cc..851a3b01781e 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -39,15 +39,6 @@ config LEDS_SPITZ
39 This option enables support for the LEDs on Sharp Zaurus 39 This option enables support for the LEDs on Sharp Zaurus
40 SL-Cxx00 series (C1000, C3000, C3100). 40 SL-Cxx00 series (C1000, C3000, C3100).
41 41
42config LEDS_IXP4XX
43 tristate "LED Support for GPIO connected LEDs on IXP4XX processors"
44 depends on LEDS_CLASS && ARCH_IXP4XX
45 help
46 This option enables support for the LEDs connected to GPIO
47 outputs of the Intel IXP4XX processors. To be useful the
48 particular board must have LEDs and they must be connected
49 to the GPIO lines. If unsure, say Y.
50
51config LEDS_TOSA 42config LEDS_TOSA
52 tristate "LED Support for the Sharp SL-6000 series" 43 tristate "LED Support for the Sharp SL-6000 series"
53 depends on LEDS_CLASS && PXA_SHARPSL 44 depends on LEDS_CLASS && PXA_SHARPSL
@@ -100,6 +91,13 @@ config LEDS_COBALT_RAQ
100 help 91 help
101 This option enables support for the Cobalt Raq series LEDs. 92 This option enables support for the Cobalt Raq series LEDs.
102 93
94config LEDS_HP6XX
95 tristate "LED Support for the HP Jornada 6xx"
96 depends on LEDS_CLASS && SH_HP6XX
97 help
98 This option enables led support for the handheld
99 HP Jornada 620/660/680/690.
100
103config LEDS_GPIO 101config LEDS_GPIO
104 tristate "LED Support for GPIO connected LEDs" 102 tristate "LED Support for GPIO connected LEDs"
105 depends on LEDS_CLASS && GENERIC_GPIO 103 depends on LEDS_CLASS && GENERIC_GPIO
@@ -114,6 +112,32 @@ config LEDS_CM_X270
114 help 112 help
115 This option enables support for the CM-X270 LEDs. 113 This option enables support for the CM-X270 LEDs.
116 114
115config LEDS_CLEVO_MAIL
116 tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
117 depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
118 help
119 This driver makes the mail LED accessible from userspace
120 programs through the leds subsystem. This LED have three
121 known mode: off, blink at 0.5Hz and blink at 1Hz.
122
123 The driver supports two kinds of interface: using ledtrig-timer
124 or through /sys/class/leds/clevo::mail/brightness. As this LED
125 cannot change it's brightness it blinks instead. The brightness
126 value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
127 blink at 1Hz.
128
129 This module can drive the mail LED for the following notebooks:
130
131 Clevo D410J
132 Clevo D410V
133 Clevo D400V/D470V (not tested, but might work)
134 Clevo M540N
135 Clevo M5x0N (not tested, but might work)
136 Positivo Mobile (Clevo M5x0V)
137
138 To compile this driver as a module, choose M here: the
139 module will be called leds-clevo-mail.
140
117comment "LED Triggers" 141comment "LED Triggers"
118 142
119config LEDS_TRIGGERS 143config LEDS_TRIGGERS
@@ -128,7 +152,11 @@ config LEDS_TRIGGER_TIMER
128 depends on LEDS_TRIGGERS 152 depends on LEDS_TRIGGERS
129 help 153 help
130 This allows LEDs to be controlled by a programmable timer 154 This allows LEDs to be controlled by a programmable timer
131 via sysfs. If unsure, say Y. 155 via sysfs. Some LED hardware can be programmed to start
156 blinking the LED without any further software interaction.
157 For more details read Documentation/leds-class.txt.
158
159 If unsure, say Y.
132 160
133config LEDS_TRIGGER_IDE_DISK 161config LEDS_TRIGGER_IDE_DISK
134 bool "LED IDE Disk Trigger" 162 bool "LED IDE Disk Trigger"
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a60de1b46c2c..bc6afc8dcb27 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
8obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o 8obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
9obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 9obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
10obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o 10obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
11obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o
12obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o 11obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
13obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o 12obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
14obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o 13obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
@@ -19,6 +18,8 @@ obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
19obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o 18obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
20obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 19obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
21obj-$(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
22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
22 23
23# LED Triggers 24# LED Triggers
24obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 25obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
index 599878c8e714..9e3077463d84 100644
--- a/drivers/leds/leds-ams-delta.c
+++ b/drivers/leds/leds-ams-delta.c
@@ -37,42 +37,42 @@ static void ams_delta_led_set(struct led_classdev *led_cdev,
37static struct ams_delta_led ams_delta_leds[] = { 37static struct ams_delta_led ams_delta_leds[] = {
38 { 38 {
39 .cdev = { 39 .cdev = {
40 .name = "ams-delta:camera", 40 .name = "ams-delta::camera",
41 .brightness_set = ams_delta_led_set, 41 .brightness_set = ams_delta_led_set,
42 }, 42 },
43 .bitmask = AMS_DELTA_LATCH1_LED_CAMERA, 43 .bitmask = AMS_DELTA_LATCH1_LED_CAMERA,
44 }, 44 },
45 { 45 {
46 .cdev = { 46 .cdev = {
47 .name = "ams-delta:advert", 47 .name = "ams-delta::advert",
48 .brightness_set = ams_delta_led_set, 48 .brightness_set = ams_delta_led_set,
49 }, 49 },
50 .bitmask = AMS_DELTA_LATCH1_LED_ADVERT, 50 .bitmask = AMS_DELTA_LATCH1_LED_ADVERT,
51 }, 51 },
52 { 52 {
53 .cdev = { 53 .cdev = {
54 .name = "ams-delta:email", 54 .name = "ams-delta::email",
55 .brightness_set = ams_delta_led_set, 55 .brightness_set = ams_delta_led_set,
56 }, 56 },
57 .bitmask = AMS_DELTA_LATCH1_LED_EMAIL, 57 .bitmask = AMS_DELTA_LATCH1_LED_EMAIL,
58 }, 58 },
59 { 59 {
60 .cdev = { 60 .cdev = {
61 .name = "ams-delta:handsfree", 61 .name = "ams-delta::handsfree",
62 .brightness_set = ams_delta_led_set, 62 .brightness_set = ams_delta_led_set,
63 }, 63 },
64 .bitmask = AMS_DELTA_LATCH1_LED_HANDSFREE, 64 .bitmask = AMS_DELTA_LATCH1_LED_HANDSFREE,
65 }, 65 },
66 { 66 {
67 .cdev = { 67 .cdev = {
68 .name = "ams-delta:voicemail", 68 .name = "ams-delta::voicemail",
69 .brightness_set = ams_delta_led_set, 69 .brightness_set = ams_delta_led_set,
70 }, 70 },
71 .bitmask = AMS_DELTA_LATCH1_LED_VOICEMAIL, 71 .bitmask = AMS_DELTA_LATCH1_LED_VOICEMAIL,
72 }, 72 },
73 { 73 {
74 .cdev = { 74 .cdev = {
75 .name = "ams-delta:voice", 75 .name = "ams-delta::voice",
76 .brightness_set = ams_delta_led_set, 76 .brightness_set = ams_delta_led_set,
77 }, 77 },
78 .bitmask = AMS_DELTA_LATCH1_LED_VOICE, 78 .bitmask = AMS_DELTA_LATCH1_LED_VOICE,
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
new file mode 100644
index 000000000000..6c3d33b8e383
--- /dev/null
+++ b/drivers/leds/leds-clevo-mail.c
@@ -0,0 +1,219 @@
1
2#include <linux/module.h>
3
4#include <linux/platform_device.h>
5#include <linux/err.h>
6#include <linux/leds.h>
7
8#include <linux/io.h>
9#include <linux/dmi.h>
10
11#include <linux/i8042.h>
12
13#define CLEVO_MAIL_LED_OFF 0x0084
14#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
15#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083
16
17MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
18MODULE_DESCRIPTION("Clevo mail LED driver");
19MODULE_LICENSE("GPL");
20
21static unsigned int __initdata nodetect;
22module_param_named(nodetect, nodetect, bool, 0);
23MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
24
25static struct platform_device *pdev;
26
27static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
28{
29 printk(KERN_INFO KBUILD_MODNAME ": '%s' found\n", id->ident);
30 return 1;
31}
32
33/*
34 * struct mail_led_whitelist - List of known good models
35 *
36 * Contains the known good models this driver is compatible with.
37 * When adding a new model try to be as strict as possible. This
38 * makes it possible to keep the false positives (the model is
39 * detected as working, but in reality it is not) as low as
40 * possible.
41 */
42static struct dmi_system_id __initdata mail_led_whitelist[] = {
43 {
44 .callback = clevo_mail_led_dmi_callback,
45 .ident = "Clevo D410J",
46 .matches = {
47 DMI_MATCH(DMI_SYS_VENDOR, "VIA"),
48 DMI_MATCH(DMI_PRODUCT_NAME, "K8N800"),
49 DMI_MATCH(DMI_PRODUCT_VERSION, "VT8204B")
50 }
51 },
52 {
53 .callback = clevo_mail_led_dmi_callback,
54 .ident = "Clevo M5x0N",
55 .matches = {
56 DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
57 DMI_MATCH(DMI_PRODUCT_NAME, "M5x0N")
58 }
59 },
60 {
61 .callback = clevo_mail_led_dmi_callback,
62 .ident = "Positivo Mobile",
63 .matches = {
64 DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
65 DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
66 DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
67 DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
68 }
69 },
70 {
71 .callback = clevo_mail_led_dmi_callback,
72 .ident = "Clevo D410V",
73 .matches = {
74 DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
75 DMI_MATCH(DMI_BOARD_NAME, "D400V/D470V"),
76 DMI_MATCH(DMI_BOARD_VERSION, "SS78B"),
77 DMI_MATCH(DMI_PRODUCT_VERSION, "Rev. A1")
78 }
79 },
80 { }
81};
82
83static void clevo_mail_led_set(struct led_classdev *led_cdev,
84 enum led_brightness value)
85{
86 if (value == LED_OFF)
87 i8042_command(NULL, CLEVO_MAIL_LED_OFF);
88 else if (value <= LED_HALF)
89 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
90 else
91 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
92
93}
94
95static int clevo_mail_led_blink(struct led_classdev *led_cdev,
96 unsigned long* delay_on,
97 unsigned long* delay_off)
98{
99 int status = -EINVAL;
100
101 if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) {
102 /* Special case: the leds subsystem requested us to
103 * chose one user friendly blinking of the LED, and
104 * start it. Let's blink the led slowly (0.5Hz).
105 */
106 *delay_on = 1000; /* ms */
107 *delay_off = 1000; /* ms */
108 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
109 status = 0;
110
111 } else if (*delay_on == 500 /* ms */ && *delay_off == 500 /* ms */) {
112 /* blink the led with 1Hz */
113 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
114 status = 0;
115
116 } else if (*delay_on == 1000 /* ms */ && *delay_off == 1000 /* ms */) {
117 /* blink the led with 0.5Hz */
118 i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
119 status = 0;
120
121 } else {
122 printk(KERN_DEBUG KBUILD_MODNAME
123 ": clevo_mail_led_blink(..., %lu, %lu),"
124 " returning -EINVAL (unsupported)\n",
125 *delay_on, *delay_off);
126 }
127
128 return status;
129}
130
131static struct led_classdev clevo_mail_led = {
132 .name = "clevo::mail",
133 .brightness_set = clevo_mail_led_set,
134 .blink_set = clevo_mail_led_blink,
135};
136
137static int __init clevo_mail_led_probe(struct platform_device *pdev)
138{
139 return led_classdev_register(&pdev->dev, &clevo_mail_led);
140}
141
142static int clevo_mail_led_remove(struct platform_device *pdev)
143{
144 led_classdev_unregister(&clevo_mail_led);
145 return 0;
146}
147
148#ifdef CONFIG_PM
149static int clevo_mail_led_suspend(struct platform_device *dev,
150 pm_message_t state)
151{
152 led_classdev_suspend(&clevo_mail_led);
153 return 0;
154}
155
156static int clevo_mail_led_resume(struct platform_device *dev)
157{
158 led_classdev_resume(&clevo_mail_led);
159 return 0;
160}
161#else
162#define clevo_mail_led_suspend NULL
163#define clevo_mail_led_resume NULL
164#endif
165
166static struct platform_driver clevo_mail_led_driver = {
167 .probe = clevo_mail_led_probe,
168 .remove = clevo_mail_led_remove,
169 .suspend = clevo_mail_led_suspend,
170 .resume = clevo_mail_led_resume,
171 .driver = {
172 .name = KBUILD_MODNAME,
173 },
174};
175
176static int __init clevo_mail_led_init(void)
177{
178 int error = 0;
179 int count = 0;
180
181 /* Check with the help of DMI if we are running on supported hardware */
182 if (!nodetect) {
183 count = dmi_check_system(mail_led_whitelist);
184 } else {
185 count = 1;
186 printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
187 "If the driver works on your hardware please "
188 "report model and the output of dmidecode in tracker "
189 "at http://sourceforge.net/projects/clevo-mailled/\n");
190 }
191
192 if (!count)
193 return -ENODEV;
194
195 pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
196 if (!IS_ERR(pdev)) {
197 error = platform_driver_probe(&clevo_mail_led_driver,
198 clevo_mail_led_probe);
199 if (error) {
200 printk(KERN_ERR KBUILD_MODNAME
201 ": Can't probe platform driver\n");
202 platform_device_unregister(pdev);
203 }
204 } else
205 error = PTR_ERR(pdev);
206
207 return error;
208}
209
210static void __exit clevo_mail_led_exit(void)
211{
212 platform_device_unregister(pdev);
213 platform_driver_unregister(&clevo_mail_led_driver);
214
215 clevo_mail_led_set(NULL, LED_OFF);
216}
217
218module_init(clevo_mail_led_init);
219module_exit(clevo_mail_led_exit);
diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c
index cf1dcd719a28..e45f6c4b59ba 100644
--- a/drivers/leds/leds-corgi.c
+++ b/drivers/leds/leds-corgi.c
@@ -38,13 +38,13 @@ static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightnes
38} 38}
39 39
40static struct led_classdev corgi_amber_led = { 40static struct led_classdev corgi_amber_led = {
41 .name = "corgi:amber", 41 .name = "corgi:amber:charge",
42 .default_trigger = "sharpsl-charge", 42 .default_trigger = "sharpsl-charge",
43 .brightness_set = corgiled_amber_set, 43 .brightness_set = corgiled_amber_set,
44}; 44};
45 45
46static struct led_classdev corgi_green_led = { 46static struct led_classdev corgi_green_led = {
47 .name = "corgi:green", 47 .name = "corgi:green:mail",
48 .default_trigger = "nand-disk", 48 .default_trigger = "nand-disk",
49 .brightness_set = corgiled_green_set, 49 .brightness_set = corgiled_green_set,
50}; 50};
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 99bc50059d35..6c0a9c4761ee 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -85,7 +85,7 @@ static int gpio_led_probe(struct platform_device *pdev)
85 led_dat->can_sleep = gpio_cansleep(cur_led->gpio); 85 led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
86 led_dat->active_low = cur_led->active_low; 86 led_dat->active_low = cur_led->active_low;
87 led_dat->cdev.brightness_set = gpio_led_set; 87 led_dat->cdev.brightness_set = gpio_led_set;
88 led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF; 88 led_dat->cdev.brightness = LED_OFF;
89 89
90 ret = gpio_request(led_dat->gpio, led_dat->cdev.name); 90 ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
91 if (ret < 0) 91 if (ret < 0)
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
new file mode 100644
index 000000000000..82d4ec384797
--- /dev/null
+++ b/drivers/leds/leds-hp6xx.c
@@ -0,0 +1,120 @@
1/*
2 * LED Triggers Core
3 * For the HP Jornada 620/660/680/690 handhelds
4 *
5 * Copyright 2008 Kristoffer Ericson <kristoffer.ericson@gmail.com>
6 * this driver is based on leds-spitz.c by Richard Purdie.
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#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/leds.h>
17#include <asm/hd64461.h>
18#include <asm/hp6xx.h>
19
20static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
21{
22 u8 v8;
23
24 v8 = inb(PKDR);
25 if (value)
26 outb(v8 & (~PKDR_LED_GREEN), PKDR);
27 else
28 outb(v8 | PKDR_LED_GREEN, PKDR);
29}
30
31static void hp6xxled_red_set(struct led_classdev *led_cdev, enum led_brightness value)
32{
33 u16 v16;
34
35 v16 = inw(HD64461_GPBDR);
36 if (value)
37 outw(v16 & (~HD64461_GPBDR_LED_RED), HD64461_GPBDR);
38 else
39 outw(v16 | HD64461_GPBDR_LED_RED, HD64461_GPBDR);
40}
41
42static struct led_classdev hp6xx_red_led = {
43 .name = "hp6xx:red",
44 .default_trigger = "hp6xx-charge",
45 .brightness_set = hp6xxled_red_set,
46};
47
48static struct led_classdev hp6xx_green_led = {
49 .name = "hp6xx:green",
50 .default_trigger = "ide-disk",
51 .brightness_set = hp6xxled_green_set,
52};
53
54#ifdef CONFIG_PM
55static int hp6xxled_suspend(struct platform_device *dev, pm_message_t state)
56{
57 led_classdev_suspend(&hp6xx_red_led);
58 led_classdev_suspend(&hp6xx_green_led);
59 return 0;
60}
61
62static int hp6xxled_resume(struct platform_device *dev)
63{
64 led_classdev_resume(&hp6xx_red_led);
65 led_classdev_resume(&hp6xx_green_led);
66 return 0;
67}
68#endif
69
70static int hp6xxled_probe(struct platform_device *pdev)
71{
72 int ret;
73
74 ret = led_classdev_register(&pdev->dev, &hp6xx_red_led);
75 if (ret < 0)
76 return ret;
77
78 ret = led_classdev_register(&pdev->dev, &hp6xx_green_led);
79 if (ret < 0)
80 led_classdev_unregister(&hp6xx_red_led);
81
82 return ret;
83}
84
85static int hp6xxled_remove(struct platform_device *pdev)
86{
87 led_classdev_unregister(&hp6xx_red_led);
88 led_classdev_unregister(&hp6xx_green_led);
89
90 return 0;
91}
92
93static struct platform_driver hp6xxled_driver = {
94 .probe = hp6xxled_probe,
95 .remove = hp6xxled_remove,
96#ifdef CONFIG_PM
97 .suspend = hp6xxled_suspend,
98 .resume = hp6xxled_resume,
99#endif
100 .driver = {
101 .name = "hp6xx-led",
102 },
103};
104
105static int __init hp6xxled_init(void)
106{
107 return platform_driver_register(&hp6xxled_driver);
108}
109
110static void __exit hp6xxled_exit(void)
111{
112 platform_driver_unregister(&hp6xxled_driver);
113}
114
115module_init(hp6xxled_init);
116module_exit(hp6xxled_exit);
117
118MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
119MODULE_DESCRIPTION("HP Jornada 6xx LED driver");
120MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ixp4xx-gpio.c b/drivers/leds/leds-ixp4xx-gpio.c
deleted file mode 100644
index 7dcf0b92c460..000000000000
--- a/drivers/leds/leds-ixp4xx-gpio.c
+++ /dev/null
@@ -1,214 +0,0 @@
1/*
2 * IXP4XX GPIO driver LED driver
3 *
4 * Author: John Bowler <jbowler@acm.org>
5 *
6 * Copyright (c) 2006 John Bowler
7 *
8 * Permission is hereby granted, free of charge, to any
9 * person obtaining a copy of this software and associated
10 * documentation files (the "Software"), to deal in the
11 * Software without restriction, including without
12 * limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of
14 * the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the
16 * following conditions:
17 *
18 * The above copyright notice and this permission notice
19 * shall be included in all copies or substantial portions
20 * of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
23 * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
24 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
26 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
27 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 * OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <linux/kernel.h>
35#include <linux/init.h>
36#include <linux/platform_device.h>
37#include <linux/spinlock.h>
38#include <linux/leds.h>
39#include <asm/arch/hardware.h>
40
41extern spinlock_t gpio_lock;
42
43/* Up to 16 gpio lines are possible. */
44#define GPIO_MAX 16
45static struct ixp4xxgpioled_device {
46 struct led_classdev ancestor;
47 int flags;
48} ixp4xxgpioled_devices[GPIO_MAX];
49
50void ixp4xxgpioled_brightness_set(struct led_classdev *pled,
51 enum led_brightness value)
52{
53 const struct ixp4xxgpioled_device *const ixp4xx_dev =
54 container_of(pled, struct ixp4xxgpioled_device, ancestor);
55 const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices;
56
57 if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) {
58 /* Set or clear the 'gpio_pin' bit according to the style
59 * and the required setting (value > 0 == on)
60 */
61 const int gpio_value =
62 (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ?
63 IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW;
64
65 {
66 unsigned long flags;
67 spin_lock_irqsave(&gpio_lock, flags);
68 gpio_line_set(gpio_pin, gpio_value);
69 spin_unlock_irqrestore(&gpio_lock, flags);
70 }
71 }
72}
73
74/* LEDs are described in resources, the following iterates over the valid
75 * LED resources.
76 */
77#define for_all_leds(i, pdev) \
78 for (i=0; i<pdev->num_resources; ++i) \
79 if (pdev->resource[i].start < GPIO_MAX && \
80 pdev->resource[i].name != 0)
81
82/* The following applies 'operation' to each LED from the given platform,
83 * the function always returns 0 to allow tail call elimination.
84 */
85static int apply_to_all_leds(struct platform_device *pdev,
86 void (*operation)(struct led_classdev *pled))
87{
88 int i;
89
90 for_all_leds(i, pdev)
91 operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor);
92 return 0;
93}
94
95#ifdef CONFIG_PM
96static int ixp4xxgpioled_suspend(struct platform_device *pdev,
97 pm_message_t state)
98{
99 return apply_to_all_leds(pdev, led_classdev_suspend);
100}
101
102static int ixp4xxgpioled_resume(struct platform_device *pdev)
103{
104 return apply_to_all_leds(pdev, led_classdev_resume);
105}
106#endif
107
108static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled)
109{
110 led_classdev_unregister(pled);
111 pled->name = 0;
112}
113
114static int ixp4xxgpioled_remove(struct platform_device *pdev)
115{
116 return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led);
117}
118
119static int ixp4xxgpioled_probe(struct platform_device *pdev)
120{
121 /* The board level has to tell the driver where the
122 * LEDs are connected - there is no way to find out
123 * electrically. It must also say whether the GPIO
124 * lines are active high or active low.
125 *
126 * To do this read the num_resources (the number of
127 * LEDs) and the struct resource (the data for each
128 * LED). The name comes from the resource, and it
129 * isn't copied.
130 */
131 int i;
132
133 for_all_leds(i, pdev) {
134 const u8 gpio_pin = pdev->resource[i].start;
135 int rc;
136
137 if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) {
138 unsigned long flags;
139
140 spin_lock_irqsave(&gpio_lock, flags);
141 gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT);
142 /* The config can, apparently, reset the state,
143 * I suspect the gpio line may be an input and
144 * the config may cause the line to be latched,
145 * so the setting depends on how the LED is
146 * connected to the line (which affects how it
147 * floats if not driven).
148 */
149 gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH);
150 spin_unlock_irqrestore(&gpio_lock, flags);
151
152 ixp4xxgpioled_devices[gpio_pin].flags =
153 pdev->resource[i].flags & IORESOURCE_BITS;
154
155 ixp4xxgpioled_devices[gpio_pin].ancestor.name =
156 pdev->resource[i].name;
157
158 /* This is how a board manufacturer makes the LED
159 * come on on reset - the GPIO line will be high, so
160 * make the LED light when the line is low...
161 */
162 if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW)
163 ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100;
164 else
165 ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0;
166
167 ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0;
168
169 ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set =
170 ixp4xxgpioled_brightness_set;
171
172 ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0;
173 }
174
175 rc = led_classdev_register(&pdev->dev,
176 &ixp4xxgpioled_devices[gpio_pin].ancestor);
177 if (rc < 0) {
178 ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0;
179 ixp4xxgpioled_remove(pdev);
180 return rc;
181 }
182 }
183
184 return 0;
185}
186
187static struct platform_driver ixp4xxgpioled_driver = {
188 .probe = ixp4xxgpioled_probe,
189 .remove = ixp4xxgpioled_remove,
190#ifdef CONFIG_PM
191 .suspend = ixp4xxgpioled_suspend,
192 .resume = ixp4xxgpioled_resume,
193#endif
194 .driver = {
195 .name = "IXP4XX-GPIO-LED",
196 },
197};
198
199static int __init ixp4xxgpioled_init(void)
200{
201 return platform_driver_register(&ixp4xxgpioled_driver);
202}
203
204static void __exit ixp4xxgpioled_exit(void)
205{
206 platform_driver_unregister(&ixp4xxgpioled_driver);
207}
208
209module_init(ixp4xxgpioled_init);
210module_exit(ixp4xxgpioled_exit);
211
212MODULE_AUTHOR("John Bowler <jbowler@acm.org>");
213MODULE_DESCRIPTION("IXP4XX GPIO LED driver");
214MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
index 2207335e9212..7295f7f52185 100644
--- a/drivers/leds/leds-locomo.c
+++ b/drivers/leds/leds-locomo.c
@@ -43,13 +43,13 @@ static void locomoled_brightness_set1(struct led_classdev *led_cdev,
43} 43}
44 44
45static struct led_classdev locomo_led0 = { 45static struct led_classdev locomo_led0 = {
46 .name = "locomo:amber", 46 .name = "locomo:amber:charge",
47 .default_trigger = "sharpsl-charge", 47 .default_trigger = "sharpsl-charge",
48 .brightness_set = locomoled_brightness_set0, 48 .brightness_set = locomoled_brightness_set0,
49}; 49};
50 50
51static struct led_classdev locomo_led1 = { 51static struct led_classdev locomo_led1 = {
52 .name = "locomo:green", 52 .name = "locomo:green:mail",
53 .default_trigger = "nand-disk", 53 .default_trigger = "nand-disk",
54 .brightness_set = locomoled_brightness_set1, 54 .brightness_set = locomoled_brightness_set1,
55}; 55};
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
index 45ba3d45bcb8..054360473c94 100644
--- a/drivers/leds/leds-net48xx.c
+++ b/drivers/leds/leds-net48xx.c
@@ -31,7 +31,7 @@ static void net48xx_error_led_set(struct led_classdev *led_cdev,
31} 31}
32 32
33static struct led_classdev net48xx_error_led = { 33static struct led_classdev net48xx_error_led = {
34 .name = "net48xx:error", 34 .name = "net48xx::error",
35 .brightness_set = net48xx_error_led_set, 35 .brightness_set = net48xx_error_led_set,
36}; 36};
37 37
diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c
index 126d09cc96ec..93e1012b17e6 100644
--- a/drivers/leds/leds-spitz.c
+++ b/drivers/leds/leds-spitz.c
@@ -38,13 +38,13 @@ static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightnes
38} 38}
39 39
40static struct led_classdev spitz_amber_led = { 40static struct led_classdev spitz_amber_led = {
41 .name = "spitz:amber", 41 .name = "spitz:amber:charge",
42 .default_trigger = "sharpsl-charge", 42 .default_trigger = "sharpsl-charge",
43 .brightness_set = spitzled_amber_set, 43 .brightness_set = spitzled_amber_set,
44}; 44};
45 45
46static struct led_classdev spitz_green_led = { 46static struct led_classdev spitz_green_led = {
47 .name = "spitz:green", 47 .name = "spitz:green:hddactivity",
48 .default_trigger = "ide-disk", 48 .default_trigger = "ide-disk",
49 .brightness_set = spitzled_green_set, 49 .brightness_set = spitzled_green_set,
50}; 50};
@@ -72,8 +72,10 @@ static int spitzled_probe(struct platform_device *pdev)
72{ 72{
73 int ret; 73 int ret;
74 74
75 if (machine_is_akita()) 75 if (machine_is_akita()) {
76 spitz_green_led.name = "spitz:green:mail";
76 spitz_green_led.default_trigger = "nand-disk"; 77 spitz_green_led.default_trigger = "nand-disk";
78 }
77 79
78 ret = led_classdev_register(&pdev->dev, &spitz_amber_led); 80 ret = led_classdev_register(&pdev->dev, &spitz_amber_led);
79 if (ret < 0) 81 if (ret < 0)
diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c
index fb2416a38303..9e0a188fbb0a 100644
--- a/drivers/leds/leds-tosa.c
+++ b/drivers/leds/leds-tosa.c
@@ -45,13 +45,13 @@ static void tosaled_green_set(struct led_classdev *led_cdev,
45} 45}
46 46
47static struct led_classdev tosa_amber_led = { 47static struct led_classdev tosa_amber_led = {
48 .name = "tosa:amber", 48 .name = "tosa:amber:charge",
49 .default_trigger = "sharpsl-charge", 49 .default_trigger = "sharpsl-charge",
50 .brightness_set = tosaled_amber_set, 50 .brightness_set = tosaled_amber_set,
51}; 51};
52 52
53static struct led_classdev tosa_green_led = { 53static struct led_classdev tosa_green_led = {
54 .name = "tosa:green", 54 .name = "tosa:green:mail",
55 .default_trigger = "nand-disk", 55 .default_trigger = "nand-disk",
56 .brightness_set = tosaled_green_set, 56 .brightness_set = tosaled_green_set,
57}; 57};
diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c
index 27fb2d8e991f..7ac61a7b56ad 100644
--- a/drivers/leds/leds-wrap.c
+++ b/drivers/leds/leds-wrap.c
@@ -19,11 +19,21 @@
19#include <linux/scx200_gpio.h> 19#include <linux/scx200_gpio.h>
20 20
21#define DRVNAME "wrap-led" 21#define DRVNAME "wrap-led"
22#define WRAP_POWER_LED_GPIO 2
22#define WRAP_ERROR_LED_GPIO 3 23#define WRAP_ERROR_LED_GPIO 3
23#define WRAP_EXTRA_LED_GPIO 18 24#define WRAP_EXTRA_LED_GPIO 18
24 25
25static struct platform_device *pdev; 26static struct platform_device *pdev;
26 27
28static void wrap_power_led_set(struct led_classdev *led_cdev,
29 enum led_brightness value)
30{
31 if (value)
32 scx200_gpio_set_low(WRAP_POWER_LED_GPIO);
33 else
34 scx200_gpio_set_high(WRAP_POWER_LED_GPIO);
35}
36
27static void wrap_error_led_set(struct led_classdev *led_cdev, 37static void wrap_error_led_set(struct led_classdev *led_cdev,
28 enum led_brightness value) 38 enum led_brightness value)
29{ 39{
@@ -42,13 +52,18 @@ static void wrap_extra_led_set(struct led_classdev *led_cdev,
42 scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO); 52 scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO);
43} 53}
44 54
55static struct led_classdev wrap_power_led = {
56 .name = "wrap::power",
57 .brightness_set = wrap_power_led_set,
58};
59
45static struct led_classdev wrap_error_led = { 60static struct led_classdev wrap_error_led = {
46 .name = "wrap:error", 61 .name = "wrap::error",
47 .brightness_set = wrap_error_led_set, 62 .brightness_set = wrap_error_led_set,
48}; 63};
49 64
50static struct led_classdev wrap_extra_led = { 65static struct led_classdev wrap_extra_led = {
51 .name = "wrap:extra", 66 .name = "wrap::extra",
52 .brightness_set = wrap_extra_led_set, 67 .brightness_set = wrap_extra_led_set,
53}; 68};
54 69
@@ -56,6 +71,7 @@ static struct led_classdev wrap_extra_led = {
56static int wrap_led_suspend(struct platform_device *dev, 71static int wrap_led_suspend(struct platform_device *dev,
57 pm_message_t state) 72 pm_message_t state)
58{ 73{
74 led_classdev_suspend(&wrap_power_led);
59 led_classdev_suspend(&wrap_error_led); 75 led_classdev_suspend(&wrap_error_led);
60 led_classdev_suspend(&wrap_extra_led); 76 led_classdev_suspend(&wrap_extra_led);
61 return 0; 77 return 0;
@@ -63,6 +79,7 @@ static int wrap_led_suspend(struct platform_device *dev,
63 79
64static int wrap_led_resume(struct platform_device *dev) 80static int wrap_led_resume(struct platform_device *dev)
65{ 81{
82 led_classdev_resume(&wrap_power_led);
66 led_classdev_resume(&wrap_error_led); 83 led_classdev_resume(&wrap_error_led);
67 led_classdev_resume(&wrap_extra_led); 84 led_classdev_resume(&wrap_extra_led);
68 return 0; 85 return 0;
@@ -76,17 +93,31 @@ static int wrap_led_probe(struct platform_device *pdev)
76{ 93{
77 int ret; 94 int ret;
78 95
96 ret = led_classdev_register(&pdev->dev, &wrap_power_led);
97 if (ret < 0)
98 return ret;
99
79 ret = led_classdev_register(&pdev->dev, &wrap_error_led); 100 ret = led_classdev_register(&pdev->dev, &wrap_error_led);
80 if (ret == 0) { 101 if (ret < 0)
81 ret = led_classdev_register(&pdev->dev, &wrap_extra_led); 102 goto err1;
82 if (ret < 0) 103
83 led_classdev_unregister(&wrap_error_led); 104 ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
84 } 105 if (ret < 0)
106 goto err2;
107
108 return ret;
109
110err2:
111 led_classdev_unregister(&wrap_error_led);
112err1:
113 led_classdev_unregister(&wrap_power_led);
114
85 return ret; 115 return ret;
86} 116}
87 117
88static int wrap_led_remove(struct platform_device *pdev) 118static int wrap_led_remove(struct platform_device *pdev)
89{ 119{
120 led_classdev_unregister(&wrap_power_led);
90 led_classdev_unregister(&wrap_error_led); 121 led_classdev_unregister(&wrap_error_led);
91 led_classdev_unregister(&wrap_extra_led); 122 led_classdev_unregister(&wrap_extra_led);
92 return 0; 123 return 0;
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index ed9ff02c77ea..82c55d6e4902 100644
--- a/drivers/leds/ledtrig-timer.c
+++ b/drivers/leds/ledtrig-timer.c
@@ -77,8 +77,21 @@ static ssize_t led_delay_on_store(struct device *dev,
77 count++; 77 count++;
78 78
79 if (count == size) { 79 if (count == size) {
80 timer_data->delay_on = state; 80 if (timer_data->delay_on != state) {
81 mod_timer(&timer_data->timer, jiffies + 1); 81 /* the new value differs from the previous */
82 timer_data->delay_on = state;
83
84 /* deactivate previous settings */
85 del_timer_sync(&timer_data->timer);
86
87 /* try to activate hardware acceleration, if any */
88 if (!led_cdev->blink_set ||
89 led_cdev->blink_set(led_cdev,
90 &timer_data->delay_on, &timer_data->delay_off)) {
91 /* no hardware acceleration, blink via timer */
92 mod_timer(&timer_data->timer, jiffies + 1);
93 }
94 }
82 ret = count; 95 ret = count;
83 } 96 }
84 97
@@ -110,8 +123,21 @@ static ssize_t led_delay_off_store(struct device *dev,
110 count++; 123 count++;
111 124
112 if (count == size) { 125 if (count == size) {
113 timer_data->delay_off = state; 126 if (timer_data->delay_off != state) {
114 mod_timer(&timer_data->timer, jiffies + 1); 127 /* the new value differs from the previous */
128 timer_data->delay_off = state;
129
130 /* deactivate previous settings */
131 del_timer_sync(&timer_data->timer);
132
133 /* try to activate hardware acceleration, if any */
134 if (!led_cdev->blink_set ||
135 led_cdev->blink_set(led_cdev,
136 &timer_data->delay_on, &timer_data->delay_off)) {
137 /* no hardware acceleration, blink via timer */
138 mod_timer(&timer_data->timer, jiffies + 1);
139 }
140 }
115 ret = count; 141 ret = count;
116 } 142 }
117 143
@@ -143,6 +169,13 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
143 if (rc) 169 if (rc)
144 goto err_out_delayon; 170 goto err_out_delayon;
145 171
172 /* If there is hardware support for blinking, start one
173 * user friendly blink rate chosen by the driver.
174 */
175 if (led_cdev->blink_set)
176 led_cdev->blink_set(led_cdev,
177 &timer_data->delay_on, &timer_data->delay_off);
178
146 return; 179 return;
147 180
148err_out_delayon: 181err_out_delayon:
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 0846c33296bc..3a36a294e91b 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -239,7 +239,7 @@ static struct workqueue_struct *led_workqueue;
239 static int object##_led_wk; \ 239 static int object##_led_wk; \
240 static DECLARE_WORK(object##_led_work, object##_led_update); \ 240 static DECLARE_WORK(object##_led_work, object##_led_update); \
241 static struct led_classdev object##_led = { \ 241 static struct led_classdev object##_led = { \
242 .name = "asus:" ledname, \ 242 .name = "asus::" ledname, \
243 .brightness_set = object##_led_set, \ 243 .brightness_set = object##_led_set, \
244 } 244 }
245 245
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 0908335892db..0aac1ff511df 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -147,12 +147,12 @@ static void b43_map_led(struct b43_wldev *dev,
147 case B43_LED_TRANSFER: 147 case B43_LED_TRANSFER:
148 case B43_LED_APTRANSFER: 148 case B43_LED_APTRANSFER:
149 snprintf(name, sizeof(name), 149 snprintf(name, sizeof(name),
150 "b43-%s:tx", wiphy_name(hw->wiphy)); 150 "b43-%s::tx", wiphy_name(hw->wiphy));
151 b43_register_led(dev, &dev->led_tx, name, 151 b43_register_led(dev, &dev->led_tx, name,
152 ieee80211_get_tx_led_name(hw), 152 ieee80211_get_tx_led_name(hw),
153 led_index, activelow); 153 led_index, activelow);
154 snprintf(name, sizeof(name), 154 snprintf(name, sizeof(name),
155 "b43-%s:rx", wiphy_name(hw->wiphy)); 155 "b43-%s::rx", wiphy_name(hw->wiphy));
156 b43_register_led(dev, &dev->led_rx, name, 156 b43_register_led(dev, &dev->led_rx, name,
157 ieee80211_get_rx_led_name(hw), 157 ieee80211_get_rx_led_name(hw),
158 led_index, activelow); 158 led_index, activelow);
@@ -162,7 +162,7 @@ static void b43_map_led(struct b43_wldev *dev,
162 case B43_LED_RADIO_B: 162 case B43_LED_RADIO_B:
163 case B43_LED_MODE_BG: 163 case B43_LED_MODE_BG:
164 snprintf(name, sizeof(name), 164 snprintf(name, sizeof(name),
165 "b43-%s:radio", wiphy_name(hw->wiphy)); 165 "b43-%s::radio", wiphy_name(hw->wiphy));
166 b43_register_led(dev, &dev->led_radio, name, 166 b43_register_led(dev, &dev->led_radio, name,
167 b43_rfkill_led_name(dev), 167 b43_rfkill_led_name(dev),
168 led_index, activelow); 168 led_index, activelow);
@@ -173,7 +173,7 @@ static void b43_map_led(struct b43_wldev *dev,
173 case B43_LED_WEIRD: 173 case B43_LED_WEIRD:
174 case B43_LED_ASSOC: 174 case B43_LED_ASSOC:
175 snprintf(name, sizeof(name), 175 snprintf(name, sizeof(name),
176 "b43-%s:assoc", wiphy_name(hw->wiphy)); 176 "b43-%s::assoc", wiphy_name(hw->wiphy));
177 b43_register_led(dev, &dev->led_assoc, name, 177 b43_register_led(dev, &dev->led_assoc, name,
178 ieee80211_get_assoc_led_name(hw), 178 ieee80211_get_assoc_led_name(hw),
179 led_index, activelow); 179 led_index, activelow);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 00f89fd6c52a..0201f6f51cea 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -38,6 +38,11 @@ struct led_classdev {
38 void (*brightness_set)(struct led_classdev *led_cdev, 38 void (*brightness_set)(struct led_classdev *led_cdev,
39 enum led_brightness brightness); 39 enum led_brightness brightness);
40 40
41 /* Activate hardware accelerated blink */
42 int (*blink_set)(struct led_classdev *led_cdev,
43 unsigned long *delay_on,
44 unsigned long *delay_off);
45
41 struct device *dev; 46 struct device *dev;
42 struct list_head node; /* LED Device list */ 47 struct list_head node; /* LED Device list */
43 char *default_trigger; /* Trigger to use */ 48 char *default_trigger; /* Trigger to use */