diff options
-rw-r--r-- | Documentation/leds-class.txt | 29 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/dsmg600-setup.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/nas100d-setup.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/nslu2-setup.c | 8 | ||||
-rw-r--r-- | drivers/hwmon/applesmc.c | 2 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 4 | ||||
-rw-r--r-- | drivers/leds/Kconfig | 48 | ||||
-rw-r--r-- | drivers/leds/Makefile | 3 | ||||
-rw-r--r-- | drivers/leds/leds-ams-delta.c | 12 | ||||
-rw-r--r-- | drivers/leds/leds-clevo-mail.c | 219 | ||||
-rw-r--r-- | drivers/leds/leds-corgi.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-gpio.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-hp6xx.c | 120 | ||||
-rw-r--r-- | drivers/leds/leds-ixp4xx-gpio.c | 214 | ||||
-rw-r--r-- | drivers/leds/leds-locomo.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-net48xx.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-spitz.c | 8 | ||||
-rw-r--r-- | drivers/leds/leds-tosa.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-wrap.c | 47 | ||||
-rw-r--r-- | drivers/leds/ledtrig-timer.c | 41 | ||||
-rw-r--r-- | drivers/misc/asus-laptop.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43/leds.c | 8 | ||||
-rw-r--r-- | include/linux/leds.h | 5 |
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 | ||
40 | Is currently of the form: | 40 | Is currently of the form: |
41 | 41 | ||
42 | "devicename:colour" | 42 | "devicename:colour:function" |
43 | 43 | ||
44 | There have been calls for LED properties such as colour to be exported as | 44 | There have been calls for LED properties such as colour to be exported as |
45 | individual led class attributes. As a solution which doesn't incur as much | 45 | individual led class attributes. As a solution which doesn't incur as much |
46 | overhead, I suggest these become part of the device name. The naming scheme | 46 | overhead, I suggest these become part of the device name. The naming scheme |
47 | above leaves scope for further attributes should they be needed. | 47 | above leaves scope for further attributes should they be needed. If sections |
48 | of the name don't apply, just leave that section blank. | ||
49 | |||
50 | |||
51 | Hardware accelerated blink of LEDs | ||
52 | ================================== | ||
53 | |||
54 | Some LEDs can be programmed to blink without any CPU interaction. To | ||
55 | support this feature, a LED driver can optionally implement the | ||
56 | blink_set() function (see <linux/leds.h>). If implemeted, triggers can | ||
57 | attempt to use it before falling back to software timers. The blink_set() | ||
58 | function should return 0 if the blink setting is supported, or -EINVAL | ||
59 | otherwise, which means that LED blinking will be handled by software. | ||
60 | |||
61 | The blink_set() function should choose a user friendly blinking | ||
62 | value if it is called with *delay_on==0 && *delay_off==0 parameters. In | ||
63 | this case the driver should give back the chosen value through delay_on | ||
64 | and delay_off parameters to the leds subsystem. | ||
65 | |||
66 | Any call to the brightness_set() callback function should cancel the | ||
67 | previously programmed hardware blinking function so setting the brightness | ||
68 | to 0 can also cancel the blinking of the LED. | ||
48 | 69 | ||
49 | 70 | ||
50 | Known Issues | 71 | Known Issues |
@@ -55,10 +76,6 @@ would cause nightmare dependency issues. I see this as a minor issue | |||
55 | compared to the benefits the simple trigger functionality brings. The | 76 | compared to the benefits the simple trigger functionality brings. The |
56 | rest of the LED subsystem can be modular. | 77 | rest of the LED subsystem can be modular. |
57 | 78 | ||
58 | Some leds can be programmed to flash in hardware. As this isn't a generic | ||
59 | LED device property, this should be exported as a device specific sysfs | ||
60 | attribute rather than part of the class if this functionality is required. | ||
61 | |||
62 | 79 | ||
63 | Future Development | 80 | Future 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 | ||
72 | static struct gpio_led dsmg600_led_pins[] = { | 72 | static 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 | ||
61 | static struct gpio_led nas100d_led_pins[] = { | 61 | static 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 | ||
64 | static struct gpio_led nslu2_led_pins[] = { | 64 | static 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 | ||
907 | static struct led_classdev applesmc_backlight = { | 907 | static 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 | ||
1000 | static struct led_classdev wistron_mail_led = { | 1000 | static 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 | ||
1005 | static struct led_classdev wistron_wifi_led = { | 1005 | static 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 | ||
42 | config 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 | |||
51 | config LEDS_TOSA | 42 | config 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 | ||
94 | config 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 | |||
103 | config LEDS_GPIO | 101 | config 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 | ||
115 | config 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 | |||
117 | comment "LED Triggers" | 141 | comment "LED Triggers" |
118 | 142 | ||
119 | config LEDS_TRIGGERS | 143 | config 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 | ||
133 | config LEDS_TRIGGER_IDE_DISK | 161 | config 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 | |||
8 | obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o | 8 | obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o |
9 | obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o | 9 | obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o |
10 | obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o | 10 | obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o |
11 | obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o | ||
12 | obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o | 11 | obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o |
13 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o | 12 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o |
14 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o | 13 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o |
@@ -19,6 +18,8 @@ obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o | |||
19 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | 18 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o |
20 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | 19 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o |
21 | obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o | 20 | obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o |
21 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | ||
22 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | ||
22 | 23 | ||
23 | # LED Triggers | 24 | # LED Triggers |
24 | obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o | 25 | obj-$(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, | |||
37 | static struct ams_delta_led ams_delta_leds[] = { | 37 | static 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 | |||
17 | MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>"); | ||
18 | MODULE_DESCRIPTION("Clevo mail LED driver"); | ||
19 | MODULE_LICENSE("GPL"); | ||
20 | |||
21 | static unsigned int __initdata nodetect; | ||
22 | module_param_named(nodetect, nodetect, bool, 0); | ||
23 | MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection"); | ||
24 | |||
25 | static struct platform_device *pdev; | ||
26 | |||
27 | static 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 | */ | ||
42 | static 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 | |||
83 | static 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 | |||
95 | static 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 | |||
131 | static 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 | |||
137 | static int __init clevo_mail_led_probe(struct platform_device *pdev) | ||
138 | { | ||
139 | return led_classdev_register(&pdev->dev, &clevo_mail_led); | ||
140 | } | ||
141 | |||
142 | static 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 | ||
149 | static 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 | |||
156 | static 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 | |||
166 | static 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 | |||
176 | static 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 | |||
210 | static 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 | |||
218 | module_init(clevo_mail_led_init); | ||
219 | module_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 | ||
40 | static struct led_classdev corgi_amber_led = { | 40 | static 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 | ||
46 | static struct led_classdev corgi_green_led = { | 46 | static 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 | |||
20 | static 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 | |||
31 | static 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 | |||
42 | static struct led_classdev hp6xx_red_led = { | ||
43 | .name = "hp6xx:red", | ||
44 | .default_trigger = "hp6xx-charge", | ||
45 | .brightness_set = hp6xxled_red_set, | ||
46 | }; | ||
47 | |||
48 | static 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 | ||
55 | static 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 | |||
62 | static 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 | |||
70 | static 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 | |||
85 | static 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 | |||
93 | static 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 | |||
105 | static int __init hp6xxled_init(void) | ||
106 | { | ||
107 | return platform_driver_register(&hp6xxled_driver); | ||
108 | } | ||
109 | |||
110 | static void __exit hp6xxled_exit(void) | ||
111 | { | ||
112 | platform_driver_unregister(&hp6xxled_driver); | ||
113 | } | ||
114 | |||
115 | module_init(hp6xxled_init); | ||
116 | module_exit(hp6xxled_exit); | ||
117 | |||
118 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | ||
119 | MODULE_DESCRIPTION("HP Jornada 6xx LED driver"); | ||
120 | MODULE_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 | |||
41 | extern spinlock_t gpio_lock; | ||
42 | |||
43 | /* Up to 16 gpio lines are possible. */ | ||
44 | #define GPIO_MAX 16 | ||
45 | static struct ixp4xxgpioled_device { | ||
46 | struct led_classdev ancestor; | ||
47 | int flags; | ||
48 | } ixp4xxgpioled_devices[GPIO_MAX]; | ||
49 | |||
50 | void 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 | */ | ||
85 | static 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 | ||
96 | static 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 | |||
102 | static int ixp4xxgpioled_resume(struct platform_device *pdev) | ||
103 | { | ||
104 | return apply_to_all_leds(pdev, led_classdev_resume); | ||
105 | } | ||
106 | #endif | ||
107 | |||
108 | static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled) | ||
109 | { | ||
110 | led_classdev_unregister(pled); | ||
111 | pled->name = 0; | ||
112 | } | ||
113 | |||
114 | static int ixp4xxgpioled_remove(struct platform_device *pdev) | ||
115 | { | ||
116 | return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led); | ||
117 | } | ||
118 | |||
119 | static 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 | |||
187 | static 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 | |||
199 | static int __init ixp4xxgpioled_init(void) | ||
200 | { | ||
201 | return platform_driver_register(&ixp4xxgpioled_driver); | ||
202 | } | ||
203 | |||
204 | static void __exit ixp4xxgpioled_exit(void) | ||
205 | { | ||
206 | platform_driver_unregister(&ixp4xxgpioled_driver); | ||
207 | } | ||
208 | |||
209 | module_init(ixp4xxgpioled_init); | ||
210 | module_exit(ixp4xxgpioled_exit); | ||
211 | |||
212 | MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); | ||
213 | MODULE_DESCRIPTION("IXP4XX GPIO LED driver"); | ||
214 | MODULE_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 | ||
45 | static struct led_classdev locomo_led0 = { | 45 | static 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 | ||
51 | static struct led_classdev locomo_led1 = { | 51 | static 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 | ||
33 | static struct led_classdev net48xx_error_led = { | 33 | static 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 | ||
40 | static struct led_classdev spitz_amber_led = { | 40 | static 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 | ||
46 | static struct led_classdev spitz_green_led = { | 46 | static 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 | ||
47 | static struct led_classdev tosa_amber_led = { | 47 | static 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 | ||
53 | static struct led_classdev tosa_green_led = { | 53 | static 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 | ||
25 | static struct platform_device *pdev; | 26 | static struct platform_device *pdev; |
26 | 27 | ||
28 | static 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 | |||
27 | static void wrap_error_led_set(struct led_classdev *led_cdev, | 37 | static 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 | ||
55 | static struct led_classdev wrap_power_led = { | ||
56 | .name = "wrap::power", | ||
57 | .brightness_set = wrap_power_led_set, | ||
58 | }; | ||
59 | |||
45 | static struct led_classdev wrap_error_led = { | 60 | static 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 | ||
50 | static struct led_classdev wrap_extra_led = { | 65 | static 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 = { | |||
56 | static int wrap_led_suspend(struct platform_device *dev, | 71 | static 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 | ||
64 | static int wrap_led_resume(struct platform_device *dev) | 80 | static 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 | |||
110 | err2: | ||
111 | led_classdev_unregister(&wrap_error_led); | ||
112 | err1: | ||
113 | led_classdev_unregister(&wrap_power_led); | ||
114 | |||
85 | return ret; | 115 | return ret; |
86 | } | 116 | } |
87 | 117 | ||
88 | static int wrap_led_remove(struct platform_device *pdev) | 118 | static 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 | ||
148 | err_out_delayon: | 181 | err_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 */ |