aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-88pm860x.c12
-rw-r--r--drivers/leds/leds-adp5520.c12
-rw-r--r--drivers/leds/leds-ams-delta.c13
-rw-r--r--drivers/leds/leds-asic3.c16
-rw-r--r--drivers/leds/leds-atmel-pwm.c17
-rw-r--r--drivers/leds/leds-bd2802.c15
-rw-r--r--drivers/leds/leds-cobalt-qube.c17
-rw-r--r--drivers/leds/leds-da903x.c12
-rw-r--r--drivers/leds/leds-dac124s085.c13
-rw-r--r--drivers/leds/leds-fsg.c15
-rw-r--r--drivers/leds/leds-gpio.c16
-rw-r--r--drivers/leds/leds-hp6xx.c17
-rw-r--r--drivers/leds/leds-lm3530.c13
-rw-r--r--drivers/leds/leds-lp3944.c13
-rw-r--r--drivers/leds/leds-lp5521.c20
-rw-r--r--drivers/leds/leds-lp5523.c22
-rw-r--r--drivers/leds/leds-lt3593.c16
-rw-r--r--drivers/leds/leds-mc13783.c14
-rw-r--r--drivers/leds/leds-netxbig.c39
-rw-r--r--drivers/leds/leds-ns2.c15
-rw-r--r--drivers/leds/leds-pca9532.c14
-rw-r--r--drivers/leds/leds-pca955x.c13
-rw-r--r--drivers/leds/leds-pwm.c13
-rw-r--r--drivers/leds/leds-rb532.c16
-rw-r--r--drivers/leds/leds-regulator.c12
-rw-r--r--drivers/leds/leds-renesas-tpu.c13
-rw-r--r--drivers/leds/leds-s3c24xx.c13
-rw-r--r--drivers/leds/leds-tca6507.c779
-rw-r--r--drivers/leds/leds-wm831x-status.c17
-rw-r--r--drivers/leds/leds-wm8350.c19
32 files changed, 839 insertions, 406 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 1b75a56ebd08..897a77dfa9d7 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -388,6 +388,14 @@ config LEDS_RENESAS_TPU
388 pin function. The latter to support brightness control. 388 pin function. The latter to support brightness control.
389 Brightness control is supported but hardware blinking is not. 389 Brightness control is supported but hardware blinking is not.
390 390
391config LEDS_TCA6507
392 tristate "LED Support for TCA6507 I2C chip"
393 depends on LEDS_CLASS && I2C
394 help
395 This option enables support for LEDs connected to TC6507
396 LED driver chips accessed via the I2C bus.
397 Driver support brightness control and hardware-assisted blinking.
398
391config LEDS_TRIGGERS 399config LEDS_TRIGGERS
392 bool "LED Trigger support" 400 bool "LED Trigger support"
393 depends on LEDS_CLASS 401 depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e4f6bf568880..5c9dc4b000d5 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
25obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o 25obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
26obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o 26obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
27obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o 27obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o
28obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
28obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 29obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
29obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 30obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
30obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 31obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 0810604dc701..4ca00624bd18 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -238,17 +238,7 @@ static struct platform_driver pm860x_led_driver = {
238 .remove = pm860x_led_remove, 238 .remove = pm860x_led_remove,
239}; 239};
240 240
241static int __devinit pm860x_led_init(void) 241module_platform_driver(pm860x_led_driver);
242{
243 return platform_driver_register(&pm860x_led_driver);
244}
245module_init(pm860x_led_init);
246
247static void __devexit pm860x_led_exit(void)
248{
249 platform_driver_unregister(&pm860x_led_driver);
250}
251module_exit(pm860x_led_exit);
252 242
253MODULE_DESCRIPTION("LED driver for Marvell PM860x"); 243MODULE_DESCRIPTION("LED driver for Marvell PM860x");
254MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 244MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index 7ba4c7b5b97e..b1400db3f839 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -213,17 +213,7 @@ static struct platform_driver adp5520_led_driver = {
213 .remove = __devexit_p(adp5520_led_remove), 213 .remove = __devexit_p(adp5520_led_remove),
214}; 214};
215 215
216static int __init adp5520_led_init(void) 216module_platform_driver(adp5520_led_driver);
217{
218 return platform_driver_register(&adp5520_led_driver);
219}
220module_init(adp5520_led_init);
221
222static void __exit adp5520_led_exit(void)
223{
224 platform_driver_unregister(&adp5520_led_driver);
225}
226module_exit(adp5520_led_exit);
227 217
228MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 218MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
229MODULE_DESCRIPTION("LEDS ADP5520(01) Driver"); 219MODULE_DESCRIPTION("LEDS ADP5520(01) Driver");
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
index 8c00937bf7e7..07428357c83f 100644
--- a/drivers/leds/leds-ams-delta.c
+++ b/drivers/leds/leds-ams-delta.c
@@ -118,18 +118,7 @@ static struct platform_driver ams_delta_led_driver = {
118 }, 118 },
119}; 119};
120 120
121static int __init ams_delta_led_init(void) 121module_platform_driver(ams_delta_led_driver);
122{
123 return platform_driver_register(&ams_delta_led_driver);
124}
125
126static void __exit ams_delta_led_exit(void)
127{
128 platform_driver_unregister(&ams_delta_led_driver);
129}
130
131module_init(ams_delta_led_init);
132module_exit(ams_delta_led_exit);
133 122
134MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); 123MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
135MODULE_DESCRIPTION("Amstrad Delta LED driver"); 124MODULE_DESCRIPTION("Amstrad Delta LED driver");
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c
index 48d9fe61bdfc..525a92492837 100644
--- a/drivers/leds/leds-asic3.c
+++ b/drivers/leds/leds-asic3.c
@@ -179,21 +179,9 @@ static struct platform_driver asic3_led_driver = {
179 }, 179 },
180}; 180};
181 181
182MODULE_ALIAS("platform:leds-asic3"); 182module_platform_driver(asic3_led_driver);
183
184static int __init asic3_led_init(void)
185{
186 return platform_driver_register(&asic3_led_driver);
187}
188
189static void __exit asic3_led_exit(void)
190{
191 platform_driver_unregister(&asic3_led_driver);
192}
193
194module_init(asic3_led_init);
195module_exit(asic3_led_exit);
196 183
197MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>"); 184MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>");
198MODULE_DESCRIPTION("HTC ASIC3 LED driver"); 185MODULE_DESCRIPTION("HTC ASIC3 LED driver");
199MODULE_LICENSE("GPL"); 186MODULE_LICENSE("GPL");
187MODULE_ALIAS("platform:leds-asic3");
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 109c875ea233..800243b6037e 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -134,29 +134,18 @@ static int __exit pwmled_remove(struct platform_device *pdev)
134 return 0; 134 return 0;
135} 135}
136 136
137/* work with hotplug and coldplug */
138MODULE_ALIAS("platform:leds-atmel-pwm");
139
140static struct platform_driver pwmled_driver = { 137static struct platform_driver pwmled_driver = {
141 .driver = { 138 .driver = {
142 .name = "leds-atmel-pwm", 139 .name = "leds-atmel-pwm",
143 .owner = THIS_MODULE, 140 .owner = THIS_MODULE,
144 }, 141 },
145 /* REVISIT add suspend() and resume() methods */ 142 /* REVISIT add suspend() and resume() methods */
143 .probe = pwmled_probe,
146 .remove = __exit_p(pwmled_remove), 144 .remove = __exit_p(pwmled_remove),
147}; 145};
148 146
149static int __init modinit(void) 147module_platform_driver(pwmled_driver);
150{
151 return platform_driver_probe(&pwmled_driver, pwmled_probe);
152}
153module_init(modinit);
154
155static void __exit modexit(void)
156{
157 platform_driver_unregister(&pwmled_driver);
158}
159module_exit(modexit);
160 148
161MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness"); 149MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
162MODULE_LICENSE("GPL"); 150MODULE_LICENSE("GPL");
151MODULE_ALIAS("platform:leds-atmel-pwm");
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index ea2185531f82..591cbdf5a046 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -688,8 +688,7 @@ static int __devinit bd2802_probe(struct i2c_client *client,
688 i2c_set_clientdata(client, led); 688 i2c_set_clientdata(client, led);
689 689
690 /* Configure RESET GPIO (L: RESET, H: RESET cancel) */ 690 /* Configure RESET GPIO (L: RESET, H: RESET cancel) */
691 gpio_request(pdata->reset_gpio, "RGB_RESETB"); 691 gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, "RGB_RESETB");
692 gpio_direction_output(pdata->reset_gpio, 1);
693 692
694 /* Tacss = min 0.1ms */ 693 /* Tacss = min 0.1ms */
695 udelay(100); 694 udelay(100);
@@ -813,17 +812,7 @@ static struct i2c_driver bd2802_i2c_driver = {
813 .id_table = bd2802_id, 812 .id_table = bd2802_id,
814}; 813};
815 814
816static int __init bd2802_init(void) 815module_i2c_driver(bd2802_i2c_driver);
817{
818 return i2c_add_driver(&bd2802_i2c_driver);
819}
820module_init(bd2802_init);
821
822static void __exit bd2802_exit(void)
823{
824 i2c_del_driver(&bd2802_i2c_driver);
825}
826module_exit(bd2802_exit);
827 816
828MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); 817MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
829MODULE_DESCRIPTION("BD2802 LED driver"); 818MODULE_DESCRIPTION("BD2802 LED driver");
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index da5fb016b1a5..6a8725cc7b4d 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -75,9 +75,6 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev)
75 return 0; 75 return 0;
76} 76}
77 77
78/* work with hotplug and coldplug */
79MODULE_ALIAS("platform:cobalt-qube-leds");
80
81static struct platform_driver cobalt_qube_led_driver = { 78static struct platform_driver cobalt_qube_led_driver = {
82 .probe = cobalt_qube_led_probe, 79 .probe = cobalt_qube_led_probe,
83 .remove = __devexit_p(cobalt_qube_led_remove), 80 .remove = __devexit_p(cobalt_qube_led_remove),
@@ -87,19 +84,9 @@ static struct platform_driver cobalt_qube_led_driver = {
87 }, 84 },
88}; 85};
89 86
90static int __init cobalt_qube_led_init(void) 87module_platform_driver(cobalt_qube_led_driver);
91{
92 return platform_driver_register(&cobalt_qube_led_driver);
93}
94
95static void __exit cobalt_qube_led_exit(void)
96{
97 platform_driver_unregister(&cobalt_qube_led_driver);
98}
99
100module_init(cobalt_qube_led_init);
101module_exit(cobalt_qube_led_exit);
102 88
103MODULE_LICENSE("GPL"); 89MODULE_LICENSE("GPL");
104MODULE_DESCRIPTION("Front LED support for Cobalt Server"); 90MODULE_DESCRIPTION("Front LED support for Cobalt Server");
105MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 91MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
92MODULE_ALIAS("platform:cobalt-qube-leds");
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index f28931cf6781..d9cd73ebd6c4 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -158,17 +158,7 @@ static struct platform_driver da903x_led_driver = {
158 .remove = __devexit_p(da903x_led_remove), 158 .remove = __devexit_p(da903x_led_remove),
159}; 159};
160 160
161static int __init da903x_led_init(void) 161module_platform_driver(da903x_led_driver);
162{
163 return platform_driver_register(&da903x_led_driver);
164}
165module_init(da903x_led_init);
166
167static void __exit da903x_led_exit(void)
168{
169 platform_driver_unregister(&da903x_led_driver);
170}
171module_exit(da903x_led_exit);
172 162
173MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034"); 163MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
174MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" 164MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
index 31cf0d60a9a5..d56c14269ff0 100644
--- a/drivers/leds/leds-dac124s085.c
+++ b/drivers/leds/leds-dac124s085.c
@@ -131,18 +131,7 @@ static struct spi_driver dac124s085_driver = {
131 }, 131 },
132}; 132};
133 133
134static int __init dac124s085_leds_init(void) 134module_spi_driver(dac124s085_driver);
135{
136 return spi_register_driver(&dac124s085_driver);
137}
138
139static void __exit dac124s085_leds_exit(void)
140{
141 spi_unregister_driver(&dac124s085_driver);
142}
143
144module_init(dac124s085_leds_init);
145module_exit(dac124s085_leds_exit);
146 135
147MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); 136MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
148MODULE_DESCRIPTION("DAC124S085 LED driver"); 137MODULE_DESCRIPTION("DAC124S085 LED driver");
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index 49aceffaa5b6..b9053fa6e253 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -224,20 +224,7 @@ static struct platform_driver fsg_led_driver = {
224 }, 224 },
225}; 225};
226 226
227 227module_platform_driver(fsg_led_driver);
228static int __init fsg_led_init(void)
229{
230 return platform_driver_register(&fsg_led_driver);
231}
232
233static void __exit fsg_led_exit(void)
234{
235 platform_driver_unregister(&fsg_led_driver);
236}
237
238
239module_init(fsg_led_init);
240module_exit(fsg_led_exit);
241 228
242MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>"); 229MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
243MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); 230MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 399a86f2013a..7df74cb97e70 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -293,21 +293,9 @@ static struct platform_driver gpio_led_driver = {
293 }, 293 },
294}; 294};
295 295
296MODULE_ALIAS("platform:leds-gpio"); 296module_platform_driver(gpio_led_driver);
297
298static int __init gpio_led_init(void)
299{
300 return platform_driver_register(&gpio_led_driver);
301}
302
303static void __exit gpio_led_exit(void)
304{
305 platform_driver_unregister(&gpio_led_driver);
306}
307
308module_init(gpio_led_init);
309module_exit(gpio_led_exit);
310 297
311MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>"); 298MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>");
312MODULE_DESCRIPTION("GPIO LED driver"); 299MODULE_DESCRIPTION("GPIO LED driver");
313MODULE_LICENSE("GPL"); 300MODULE_LICENSE("GPL");
301MODULE_ALIAS("platform:leds-gpio");
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index bcfbd3a60eab..366b6055e330 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -79,9 +79,6 @@ static int hp6xxled_remove(struct platform_device *pdev)
79 return 0; 79 return 0;
80} 80}
81 81
82/* work with hotplug and coldplug */
83MODULE_ALIAS("platform:hp6xx-led");
84
85static struct platform_driver hp6xxled_driver = { 82static struct platform_driver hp6xxled_driver = {
86 .probe = hp6xxled_probe, 83 .probe = hp6xxled_probe,
87 .remove = hp6xxled_remove, 84 .remove = hp6xxled_remove,
@@ -91,19 +88,9 @@ static struct platform_driver hp6xxled_driver = {
91 }, 88 },
92}; 89};
93 90
94static int __init hp6xxled_init(void) 91module_platform_driver(hp6xxled_driver);
95{
96 return platform_driver_register(&hp6xxled_driver);
97}
98
99static void __exit hp6xxled_exit(void)
100{
101 platform_driver_unregister(&hp6xxled_driver);
102}
103
104module_init(hp6xxled_init);
105module_exit(hp6xxled_exit);
106 92
107MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); 93MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
108MODULE_DESCRIPTION("HP Jornada 6xx LED driver"); 94MODULE_DESCRIPTION("HP Jornada 6xx LED driver");
109MODULE_LICENSE("GPL"); 95MODULE_LICENSE("GPL");
96MODULE_ALIAS("platform:hp6xx-led");
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 0630e4f4b286..45e6878d7374 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -457,18 +457,7 @@ static struct i2c_driver lm3530_i2c_driver = {
457 }, 457 },
458}; 458};
459 459
460static int __init lm3530_init(void) 460module_i2c_driver(lm3530_i2c_driver);
461{
462 return i2c_add_driver(&lm3530_i2c_driver);
463}
464
465static void __exit lm3530_exit(void)
466{
467 i2c_del_driver(&lm3530_i2c_driver);
468}
469
470module_init(lm3530_init);
471module_exit(lm3530_exit);
472 461
473MODULE_DESCRIPTION("Back Light driver for LM3530"); 462MODULE_DESCRIPTION("Back Light driver for LM3530");
474MODULE_LICENSE("GPL v2"); 463MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 9010c054615e..b8f9f0a5d431 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -453,18 +453,7 @@ static struct i2c_driver lp3944_driver = {
453 .id_table = lp3944_id, 453 .id_table = lp3944_id,
454}; 454};
455 455
456static int __init lp3944_module_init(void) 456module_i2c_driver(lp3944_driver);
457{
458 return i2c_add_driver(&lp3944_driver);
459}
460
461static void __exit lp3944_module_exit(void)
462{
463 i2c_del_driver(&lp3944_driver);
464}
465
466module_init(lp3944_module_init);
467module_exit(lp3944_module_exit);
468 457
469MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); 458MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
470MODULE_DESCRIPTION("LP3944 Fun Light Chip"); 459MODULE_DESCRIPTION("LP3944 Fun Light Chip");
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index cb641f1b3342..d62a7982a5e6 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -797,25 +797,7 @@ static struct i2c_driver lp5521_driver = {
797 .id_table = lp5521_id, 797 .id_table = lp5521_id,
798}; 798};
799 799
800static int __init lp5521_init(void) 800module_i2c_driver(lp5521_driver);
801{
802 int ret;
803
804 ret = i2c_add_driver(&lp5521_driver);
805
806 if (ret < 0)
807 printk(KERN_ALERT "Adding lp5521 driver failed\n");
808
809 return ret;
810}
811
812static void __exit lp5521_exit(void)
813{
814 i2c_del_driver(&lp5521_driver);
815}
816
817module_init(lp5521_init);
818module_exit(lp5521_exit);
819 801
820MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo"); 802MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo");
821MODULE_DESCRIPTION("LP5521 LED engine"); 803MODULE_DESCRIPTION("LP5521 LED engine");
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 5971e309b234..73e791ae7259 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -870,8 +870,6 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
870 return 0; 870 return 0;
871} 871}
872 872
873static struct i2c_driver lp5523_driver;
874
875static int __devinit lp5523_probe(struct i2c_client *client, 873static int __devinit lp5523_probe(struct i2c_client *client,
876 const struct i2c_device_id *id) 874 const struct i2c_device_id *id)
877{ 875{
@@ -1021,25 +1019,7 @@ static struct i2c_driver lp5523_driver = {
1021 .id_table = lp5523_id, 1019 .id_table = lp5523_id,
1022}; 1020};
1023 1021
1024static int __init lp5523_init(void) 1022module_i2c_driver(lp5523_driver);
1025{
1026 int ret;
1027
1028 ret = i2c_add_driver(&lp5523_driver);
1029
1030 if (ret < 0)
1031 printk(KERN_ALERT "Adding lp5523 driver failed\n");
1032
1033 return ret;
1034}
1035
1036static void __exit lp5523_exit(void)
1037{
1038 i2c_del_driver(&lp5523_driver);
1039}
1040
1041module_init(lp5523_init);
1042module_exit(lp5523_exit);
1043 1023
1044MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>"); 1024MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>");
1045MODULE_DESCRIPTION("LP5523 LED engine"); 1025MODULE_DESCRIPTION("LP5523 LED engine");
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index 53f67b8ce55d..e311a96c4469 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -199,21 +199,9 @@ static struct platform_driver lt3593_led_driver = {
199 }, 199 },
200}; 200};
201 201
202MODULE_ALIAS("platform:leds-lt3593"); 202module_platform_driver(lt3593_led_driver);
203
204static int __init lt3593_led_init(void)
205{
206 return platform_driver_register(&lt3593_led_driver);
207}
208
209static void __exit lt3593_led_exit(void)
210{
211 platform_driver_unregister(&lt3593_led_driver);
212}
213
214module_init(lt3593_led_init);
215module_exit(lt3593_led_exit);
216 203
217MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); 204MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
218MODULE_DESCRIPTION("LED driver for LT3593 controllers"); 205MODULE_DESCRIPTION("LED driver for LT3593 controllers");
219MODULE_LICENSE("GPL"); 206MODULE_LICENSE("GPL");
207MODULE_ALIAS("platform:leds-lt3593");
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index b3393a9f2139..8bc491541550 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -275,7 +275,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev)
275 return -ENODEV; 275 return -ENODEV;
276 } 276 }
277 277
278 if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) { 278 if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) {
279 dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds); 279 dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds);
280 return -EINVAL; 280 return -EINVAL;
281 } 281 }
@@ -385,17 +385,7 @@ static struct platform_driver mc13783_led_driver = {
385 .remove = __devexit_p(mc13783_led_remove), 385 .remove = __devexit_p(mc13783_led_remove),
386}; 386};
387 387
388static int __init mc13783_led_init(void) 388module_platform_driver(mc13783_led_driver);
389{
390 return platform_driver_register(&mc13783_led_driver);
391}
392module_init(mc13783_led_init);
393
394static void __exit mc13783_led_exit(void)
395{
396 platform_driver_unregister(&mc13783_led_driver);
397}
398module_exit(mc13783_led_exit);
399 389
400MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC"); 390MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC");
401MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>"); 391MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>");
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index f2e51c134399..d8433f2d53bc 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -81,35 +81,23 @@ static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext)
81 81
82 /* Configure address GPIOs. */ 82 /* Configure address GPIOs. */
83 for (i = 0; i < gpio_ext->num_addr; i++) { 83 for (i = 0; i < gpio_ext->num_addr; i++) {
84 err = gpio_request(gpio_ext->addr[i], "GPIO extension addr"); 84 err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW,
85 "GPIO extension addr");
85 if (err) 86 if (err)
86 goto err_free_addr; 87 goto err_free_addr;
87 err = gpio_direction_output(gpio_ext->addr[i], 0);
88 if (err) {
89 gpio_free(gpio_ext->addr[i]);
90 goto err_free_addr;
91 }
92 } 88 }
93 /* Configure data GPIOs. */ 89 /* Configure data GPIOs. */
94 for (i = 0; i < gpio_ext->num_data; i++) { 90 for (i = 0; i < gpio_ext->num_data; i++) {
95 err = gpio_request(gpio_ext->data[i], "GPIO extension data"); 91 err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW,
92 "GPIO extension data");
96 if (err) 93 if (err)
97 goto err_free_data; 94 goto err_free_data;
98 err = gpio_direction_output(gpio_ext->data[i], 0);
99 if (err) {
100 gpio_free(gpio_ext->data[i]);
101 goto err_free_data;
102 }
103 } 95 }
104 /* Configure "enable select" GPIO. */ 96 /* Configure "enable select" GPIO. */
105 err = gpio_request(gpio_ext->enable, "GPIO extension enable"); 97 err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW,
98 "GPIO extension enable");
106 if (err) 99 if (err)
107 goto err_free_data; 100 goto err_free_data;
108 err = gpio_direction_output(gpio_ext->enable, 0);
109 if (err) {
110 gpio_free(gpio_ext->enable);
111 goto err_free_data;
112 }
113 101
114 return 0; 102 return 0;
115 103
@@ -429,21 +417,10 @@ static struct platform_driver netxbig_led_driver = {
429 .owner = THIS_MODULE, 417 .owner = THIS_MODULE,
430 }, 418 },
431}; 419};
432MODULE_ALIAS("platform:leds-netxbig");
433 420
434static int __init netxbig_led_init(void) 421module_platform_driver(netxbig_led_driver);
435{
436 return platform_driver_register(&netxbig_led_driver);
437}
438
439static void __exit netxbig_led_exit(void)
440{
441 platform_driver_unregister(&netxbig_led_driver);
442}
443
444module_init(netxbig_led_init);
445module_exit(netxbig_led_exit);
446 422
447MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); 423MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
448MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); 424MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards");
449MODULE_LICENSE("GPL"); 425MODULE_LICENSE("GPL");
426MODULE_ALIAS("platform:leds-netxbig");
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 37b7d0cfe586..2f0a14421a73 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -323,21 +323,10 @@ static struct platform_driver ns2_led_driver = {
323 .owner = THIS_MODULE, 323 .owner = THIS_MODULE,
324 }, 324 },
325}; 325};
326MODULE_ALIAS("platform:leds-ns2");
327
328static int __init ns2_led_init(void)
329{
330 return platform_driver_register(&ns2_led_driver);
331}
332 326
333static void __exit ns2_led_exit(void) 327module_platform_driver(ns2_led_driver);
334{
335 platform_driver_unregister(&ns2_led_driver);
336}
337
338module_init(ns2_led_init);
339module_exit(ns2_led_exit);
340 328
341MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); 329MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
342MODULE_DESCRIPTION("Network Space v2 LED driver"); 330MODULE_DESCRIPTION("Network Space v2 LED driver");
343MODULE_LICENSE("GPL"); 331MODULE_LICENSE("GPL");
332MODULE_ALIAS("platform:leds-ns2");
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index a2c874623e35..ceccab44b5b8 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -489,20 +489,8 @@ static int pca9532_remove(struct i2c_client *client)
489 return 0; 489 return 0;
490} 490}
491 491
492static int __init pca9532_init(void) 492module_i2c_driver(pca9532_driver);
493{
494 return i2c_add_driver(&pca9532_driver);
495}
496
497static void __exit pca9532_exit(void)
498{
499 i2c_del_driver(&pca9532_driver);
500}
501 493
502MODULE_AUTHOR("Riku Voipio"); 494MODULE_AUTHOR("Riku Voipio");
503MODULE_LICENSE("GPL"); 495MODULE_LICENSE("GPL");
504MODULE_DESCRIPTION("PCA 9532 LED dimmer"); 496MODULE_DESCRIPTION("PCA 9532 LED dimmer");
505
506module_init(pca9532_init);
507module_exit(pca9532_exit);
508
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 66aa3e8e786f..dcc3bc3d38db 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -371,18 +371,7 @@ static struct i2c_driver pca955x_driver = {
371 .id_table = pca955x_id, 371 .id_table = pca955x_id,
372}; 372};
373 373
374static int __init pca955x_leds_init(void) 374module_i2c_driver(pca955x_driver);
375{
376 return i2c_add_driver(&pca955x_driver);
377}
378
379static void __exit pca955x_leds_exit(void)
380{
381 i2c_del_driver(&pca955x_driver);
382}
383
384module_init(pca955x_leds_init);
385module_exit(pca955x_leds_exit);
386 375
387MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>"); 376MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>");
388MODULE_DESCRIPTION("PCA955x LED driver"); 377MODULE_DESCRIPTION("PCA955x LED driver");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 666daf77872e..3ed92f34bd44 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -135,18 +135,7 @@ static struct platform_driver led_pwm_driver = {
135 }, 135 },
136}; 136};
137 137
138static int __init led_pwm_init(void) 138module_platform_driver(led_pwm_driver);
139{
140 return platform_driver_register(&led_pwm_driver);
141}
142
143static void __exit led_pwm_exit(void)
144{
145 platform_driver_unregister(&led_pwm_driver);
146}
147
148module_init(led_pwm_init);
149module_exit(led_pwm_exit);
150 139
151MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); 140MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
152MODULE_DESCRIPTION("PWM LED driver for PXA"); 141MODULE_DESCRIPTION("PWM LED driver for PXA");
diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c
index c3525f37f73d..a7815b6cd856 100644
--- a/drivers/leds/leds-rb532.c
+++ b/drivers/leds/leds-rb532.c
@@ -57,21 +57,9 @@ static struct platform_driver rb532_led_driver = {
57 }, 57 },
58}; 58};
59 59
60static int __init rb532_led_init(void) 60module_platform_driver(rb532_led_driver);
61{
62 return platform_driver_register(&rb532_led_driver);
63}
64
65static void __exit rb532_led_exit(void)
66{
67 platform_driver_unregister(&rb532_led_driver);
68}
69
70module_init(rb532_led_init);
71module_exit(rb532_led_exit);
72
73MODULE_ALIAS("platform:rb532-led");
74 61
75MODULE_LICENSE("GPL"); 62MODULE_LICENSE("GPL");
76MODULE_DESCRIPTION("User LED support for Routerboard532"); 63MODULE_DESCRIPTION("User LED support for Routerboard532");
77MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); 64MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
65MODULE_ALIAS("platform:rb532-led");
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index 8497f56f8e46..df7e963bddd3 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -229,17 +229,7 @@ static struct platform_driver regulator_led_driver = {
229 .remove = __devexit_p(regulator_led_remove), 229 .remove = __devexit_p(regulator_led_remove),
230}; 230};
231 231
232static int __init regulator_led_init(void) 232module_platform_driver(regulator_led_driver);
233{
234 return platform_driver_register(&regulator_led_driver);
235}
236module_init(regulator_led_init);
237
238static void __exit regulator_led_exit(void)
239{
240 platform_driver_unregister(&regulator_led_driver);
241}
242module_exit(regulator_led_exit);
243 233
244MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); 234MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
245MODULE_DESCRIPTION("Regulator driven LED driver"); 235MODULE_DESCRIPTION("Regulator driven LED driver");
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c
index 3ee540eb127e..32fe337d5c68 100644
--- a/drivers/leds/leds-renesas-tpu.c
+++ b/drivers/leds/leds-renesas-tpu.c
@@ -339,18 +339,7 @@ static struct platform_driver r_tpu_device_driver = {
339 } 339 }
340}; 340};
341 341
342static int __init r_tpu_init(void) 342module_platform_driver(r_tpu_device_driver);
343{
344 return platform_driver_register(&r_tpu_device_driver);
345}
346
347static void __exit r_tpu_exit(void)
348{
349 platform_driver_unregister(&r_tpu_device_driver);
350}
351
352module_init(r_tpu_init);
353module_exit(r_tpu_exit);
354 343
355MODULE_AUTHOR("Magnus Damm"); 344MODULE_AUTHOR("Magnus Damm");
356MODULE_DESCRIPTION("Renesas TPU LED Driver"); 345MODULE_DESCRIPTION("Renesas TPU LED Driver");
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 29f8b0f0e2c6..bd0a5ed49c42 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -121,18 +121,7 @@ static struct platform_driver s3c24xx_led_driver = {
121 }, 121 },
122}; 122};
123 123
124static int __init s3c24xx_led_init(void) 124module_platform_driver(s3c24xx_led_driver);
125{
126 return platform_driver_register(&s3c24xx_led_driver);
127}
128
129static void __exit s3c24xx_led_exit(void)
130{
131 platform_driver_unregister(&s3c24xx_led_driver);
132}
133
134module_init(s3c24xx_led_init);
135module_exit(s3c24xx_led_exit);
136 125
137MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 126MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
138MODULE_DESCRIPTION("S3C24XX LED driver"); 127MODULE_DESCRIPTION("S3C24XX LED driver");
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
new file mode 100644
index 000000000000..133f89fb7071
--- /dev/null
+++ b/drivers/leds/leds-tca6507.c
@@ -0,0 +1,779 @@
1/*
2 * leds-tca6507
3 *
4 * The TCA6507 is a programmable LED controller that can drive 7
5 * separate lines either by holding them low, or by pulsing them
6 * with modulated width.
7 * The modulation can be varied in a simple pattern to produce a blink or
8 * double-blink.
9 *
10 * This driver can configure each line either as a 'GPIO' which is out-only
11 * (no pull-up) or as an LED with variable brightness and hardware-assisted
12 * blinking.
13 *
14 * Apart from OFF and ON there are three programmable brightness levels which
15 * can be programmed from 0 to 15 and indicate how many 500usec intervals in
16 * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and
17 * BANK1.
18 *
19 * There are two different blink rates that can be programmed, each with
20 * separate time for rise, on, fall, off and second-off. Thus if 3 or more
21 * different non-trivial rates are required, software must be used for the extra
22 * rates. The two different blink rates must align with the two levels BANK0 and
23 * BANK1.
24 * This driver does not support double-blink so 'second-off' always matches
25 * 'off'.
26 *
27 * Only 16 different times can be programmed in a roughly logarithmic scale from
28 * 64ms to 16320ms. To be precise the possible times are:
29 * 0, 64, 128, 192, 256, 384, 512, 768,
30 * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
31 *
32 * Times that cannot be closely matched with these must be
33 * handled in software. This driver allows 12.5% error in matching.
34 *
35 * This driver does not allow rise/fall rates to be set explicitly. When trying
36 * to match a given 'on' or 'off' period, an appropriate pair of 'change' and
37 * 'hold' times are chosen to get a close match. If the target delay is even,
38 * the 'change' number will be the smaller; if odd, the 'hold' number will be
39 * the smaller.
40
41 * Choosing pairs of delays with 12.5% errors allows us to match delays in the
42 * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720.
43 * 26% of the achievable sums can be matched by multiple pairings. For example
44 * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the
45 * pairing with the least maximum - 768+768 in this case. Other pairings are
46 * not available.
47 *
48 * Access to the 3 levels and 2 blinks are on a first-come, first-served basis.
49 * Access can be shared by multiple leds if they have the same level and
50 * either same blink rates, or some don't blink.
51 * When a led changes, it relinquishes access and tries again, so it might
52 * lose access to hardware blink.
53 * If a blink engine cannot be allocated, software blink is used.
54 * If the desired brightness cannot be allocated, the closest available non-zero
55 * brightness is used. As 'full' is always available, the worst case would be
56 * to have two different blink rates at '1', with Max at '2', then other leds
57 * will have to choose between '2' and '16'. Hopefully this is not likely.
58 *
59 * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness
60 * and LEDs using the blink. It can only be reprogrammed when the appropriate
61 * counter is zero. The MASTER level has a single usage count.
62 *
63 * Each Led has programmable 'on' and 'off' time as milliseconds. With each
64 * there is a flag saying if it was explicitly requested or defaulted.
65 * Similarly the banks know if each time was explicit or a default. Defaults
66 * are permitted to be changed freely - they are not recognised when matching.
67 *
68 *
69 * An led-tca6507 device must be provided with platform data. This data
70 * lists for each output: the name, default trigger, and whether the signal
71 * is being used as a GPiO rather than an led. 'struct led_plaform_data'
72 * is used for this. If 'name' is NULL, the output isn't used. If 'flags'
73 * is TCA6507_MAKE_CPIO, the output is a GPO.
74 * The "struct led_platform_data" can be embedded in a
75 * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs,
76 * and a 'setup' callback which is called once the GPiOs are available.
77 *
78 */
79
80#include <linux/module.h>
81#include <linux/slab.h>
82#include <linux/leds.h>
83#include <linux/err.h>
84#include <linux/i2c.h>
85#include <linux/gpio.h>
86#include <linux/workqueue.h>
87#include <linux/leds-tca6507.h>
88
89/* LED select registers determine the source that drives LED outputs */
90#define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */
91#define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */
92#define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */
93#define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */
94#define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */
95#define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */
96#define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */
97#define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */
98
99enum {
100 BANK0,
101 BANK1,
102 MASTER,
103};
104static int bank_source[3] = {
105 TCA6507_LS_LED_PWM0,
106 TCA6507_LS_LED_PWM1,
107 TCA6507_LS_LED_MIR,
108};
109static int blink_source[2] = {
110 TCA6507_LS_BLINK0,
111 TCA6507_LS_BLINK1,
112};
113
114/* PWM registers */
115#define TCA6507_REG_CNT 11
116
117/*
118 * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output
119 * owns one bit in each register
120 */
121#define TCA6507_FADE_ON 0x03
122#define TCA6507_FULL_ON 0x04
123#define TCA6507_FADE_OFF 0x05
124#define TCA6507_FIRST_OFF 0x06
125#define TCA6507_SECOND_OFF 0x07
126#define TCA6507_MAX_INTENSITY 0x08
127#define TCA6507_MASTER_INTENSITY 0x09
128#define TCA6507_INITIALIZE 0x0A
129
130#define INIT_CODE 0x8
131
132#define TIMECODES 16
133static int time_codes[TIMECODES] = {
134 0, 64, 128, 192, 256, 384, 512, 768,
135 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320
136};
137
138/* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */
139static inline int TO_LEVEL(int brightness)
140{
141 return brightness >> 4;
142}
143
144/* ...and convert back */
145static inline int TO_BRIGHT(int level)
146{
147 if (level)
148 return (level << 4) | 0xf;
149 return 0;
150}
151
152#define NUM_LEDS 7
153struct tca6507_chip {
154 int reg_set; /* One bit per register where
155 * a '1' means the register
156 * should be written */
157 u8 reg_file[TCA6507_REG_CNT];
158 /* Bank 2 is Master Intensity and doesn't use times */
159 struct bank {
160 int level;
161 int ontime, offtime;
162 int on_dflt, off_dflt;
163 int time_use, level_use;
164 } bank[3];
165 struct i2c_client *client;
166 struct work_struct work;
167 spinlock_t lock;
168
169 struct tca6507_led {
170 struct tca6507_chip *chip;
171 struct led_classdev led_cdev;
172 int num;
173 int ontime, offtime;
174 int on_dflt, off_dflt;
175 int bank; /* Bank used, or -1 */
176 int blink; /* Set if hardware-blinking */
177 } leds[NUM_LEDS];
178#ifdef CONFIG_GPIOLIB
179 struct gpio_chip gpio;
180 const char *gpio_name[NUM_LEDS];
181 int gpio_map[NUM_LEDS];
182#endif
183};
184
185static const struct i2c_device_id tca6507_id[] = {
186 { "tca6507" },
187 { }
188};
189MODULE_DEVICE_TABLE(i2c, tca6507_id);
190
191static int choose_times(int msec, int *c1p, int *c2p)
192{
193 /*
194 * Choose two timecodes which add to 'msec' as near as possible.
195 * The first returned is the 'on' or 'off' time. The second is to be
196 * used as a 'fade-on' or 'fade-off' time. If 'msec' is even,
197 * the first will not be smaller than the second. If 'msec' is odd,
198 * the first will not be larger than the second.
199 * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL,
200 * otherwise return the sum that was achieved, plus 1 if the first is
201 * smaller.
202 * If two possibilities are equally good (e.g. 512+0, 256+256), choose
203 * the first pair so there is more change-time visible (i.e. it is
204 * softer).
205 */
206 int c1, c2;
207 int tmax = msec * 9 / 8;
208 int tmin = msec * 7 / 8;
209 int diff = 65536;
210
211 /* We start at '1' to ensure we never even think of choosing a
212 * total time of '0'.
213 */
214 for (c1 = 1; c1 < TIMECODES; c1++) {
215 int t = time_codes[c1];
216 if (t*2 < tmin)
217 continue;
218 if (t > tmax)
219 break;
220 for (c2 = 0; c2 <= c1; c2++) {
221 int tt = t + time_codes[c2];
222 int d;
223 if (tt < tmin)
224 continue;
225 if (tt > tmax)
226 break;
227 /* This works! */
228 d = abs(msec - tt);
229 if (d >= diff)
230 continue;
231 /* Best yet */
232 *c1p = c1;
233 *c2p = c2;
234 diff = d;
235 if (d == 0)
236 return msec;
237 }
238 }
239 if (diff < 65536) {
240 int actual;
241 if (msec & 1) {
242 c1 = *c2p;
243 *c2p = *c1p;
244 *c1p = c1;
245 }
246 actual = time_codes[*c1p] + time_codes[*c2p];
247 if (*c1p < *c2p)
248 return actual + 1;
249 else
250 return actual;
251 }
252 /* No close match */
253 return -EINVAL;
254}
255
256/*
257 * Update the register file with the appropriate 3-bit state for
258 * the given led.
259 */
260static void set_select(struct tca6507_chip *tca, int led, int val)
261{
262 int mask = (1 << led);
263 int bit;
264
265 for (bit = 0; bit < 3; bit++) {
266 int n = tca->reg_file[bit] & ~mask;
267 if (val & (1 << bit))
268 n |= mask;
269 if (tca->reg_file[bit] != n) {
270 tca->reg_file[bit] = n;
271 tca->reg_set |= (1 << bit);
272 }
273 }
274}
275
276/* Update the register file with the appropriate 4-bit code for
277 * one bank or other. This can be used for timers, for levels, or
278 * for initialisation.
279 */
280static void set_code(struct tca6507_chip *tca, int reg, int bank, int new)
281{
282 int mask = 0xF;
283 int n;
284 if (bank) {
285 mask <<= 4;
286 new <<= 4;
287 }
288 n = tca->reg_file[reg] & ~mask;
289 n |= new;
290 if (tca->reg_file[reg] != n) {
291 tca->reg_file[reg] = n;
292 tca->reg_set |= 1 << reg;
293 }
294}
295
296/* Update brightness level. */
297static void set_level(struct tca6507_chip *tca, int bank, int level)
298{
299 switch (bank) {
300 case BANK0:
301 case BANK1:
302 set_code(tca, TCA6507_MAX_INTENSITY, bank, level);
303 break;
304 case MASTER:
305 set_code(tca, TCA6507_MASTER_INTENSITY, 0, level);
306 break;
307 }
308 tca->bank[bank].level = level;
309}
310
311/* Record all relevant time code for a given bank */
312static void set_times(struct tca6507_chip *tca, int bank)
313{
314 int c1, c2;
315 int result;
316
317 result = choose_times(tca->bank[bank].ontime, &c1, &c2);
318 dev_dbg(&tca->client->dev,
319 "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
320 c2, time_codes[c2], tca->bank[bank].ontime);
321 set_code(tca, TCA6507_FADE_ON, bank, c2);
322 set_code(tca, TCA6507_FULL_ON, bank, c1);
323 tca->bank[bank].ontime = result;
324
325 result = choose_times(tca->bank[bank].offtime, &c1, &c2);
326 dev_dbg(&tca->client->dev,
327 "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1],
328 c2, time_codes[c2], tca->bank[bank].offtime);
329 set_code(tca, TCA6507_FADE_OFF, bank, c2);
330 set_code(tca, TCA6507_FIRST_OFF, bank, c1);
331 set_code(tca, TCA6507_SECOND_OFF, bank, c1);
332 tca->bank[bank].offtime = result;
333
334 set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE);
335}
336
337/* Write all needed register of tca6507 */
338
339static void tca6507_work(struct work_struct *work)
340{
341 struct tca6507_chip *tca = container_of(work, struct tca6507_chip,
342 work);
343 struct i2c_client *cl = tca->client;
344 int set;
345 u8 file[TCA6507_REG_CNT];
346 int r;
347
348 spin_lock_irq(&tca->lock);
349 set = tca->reg_set;
350 memcpy(file, tca->reg_file, TCA6507_REG_CNT);
351 tca->reg_set = 0;
352 spin_unlock_irq(&tca->lock);
353
354 for (r = 0; r < TCA6507_REG_CNT; r++)
355 if (set & (1<<r))
356 i2c_smbus_write_byte_data(cl, r, file[r]);
357}
358
359static void led_release(struct tca6507_led *led)
360{
361 /* If led owns any resource, release it. */
362 struct tca6507_chip *tca = led->chip;
363 if (led->bank >= 0) {
364 struct bank *b = tca->bank + led->bank;
365 if (led->blink)
366 b->time_use--;
367 b->level_use--;
368 }
369 led->blink = 0;
370 led->bank = -1;
371}
372
373static int led_prepare(struct tca6507_led *led)
374{
375 /* Assign this led to a bank, configuring that bank if necessary. */
376 int level = TO_LEVEL(led->led_cdev.brightness);
377 struct tca6507_chip *tca = led->chip;
378 int c1, c2;
379 int i;
380 struct bank *b;
381 int need_init = 0;
382
383 led->led_cdev.brightness = TO_BRIGHT(level);
384 if (level == 0) {
385 set_select(tca, led->num, TCA6507_LS_LED_OFF);
386 return 0;
387 }
388
389 if (led->ontime == 0 || led->offtime == 0) {
390 /*
391 * Just set the brightness, choosing first usable bank.
392 * If none perfect, choose best.
393 * Count backwards so we check MASTER bank first
394 * to avoid wasting a timer.
395 */
396 int best = -1;/* full-on */
397 int diff = 15-level;
398
399 if (level == 15) {
400 set_select(tca, led->num, TCA6507_LS_LED_ON);
401 return 0;
402 }
403
404 for (i = MASTER; i >= BANK0; i--) {
405 int d;
406 if (tca->bank[i].level == level ||
407 tca->bank[i].level_use == 0) {
408 best = i;
409 break;
410 }
411 d = abs(level - tca->bank[i].level);
412 if (d < diff) {
413 diff = d;
414 best = i;
415 }
416 }
417 if (best == -1) {
418 /* Best brightness is full-on */
419 set_select(tca, led->num, TCA6507_LS_LED_ON);
420 led->led_cdev.brightness = LED_FULL;
421 return 0;
422 }
423
424 if (!tca->bank[best].level_use)
425 set_level(tca, best, level);
426
427 tca->bank[best].level_use++;
428 led->bank = best;
429 set_select(tca, led->num, bank_source[best]);
430 led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level);
431 return 0;
432 }
433
434 /*
435 * We have on/off time so we need to try to allocate a timing bank.
436 * First check if times are compatible with hardware and give up if
437 * not.
438 */
439 if (choose_times(led->ontime, &c1, &c2) < 0)
440 return -EINVAL;
441 if (choose_times(led->offtime, &c1, &c2) < 0)
442 return -EINVAL;
443
444 for (i = BANK0; i <= BANK1; i++) {
445 if (tca->bank[i].level_use == 0)
446 /* not in use - it is ours! */
447 break;
448 if (tca->bank[i].level != level)
449 /* Incompatible level - skip */
450 /* FIX: if timer matches we maybe should consider
451 * this anyway...
452 */
453 continue;
454
455 if (tca->bank[i].time_use == 0)
456 /* Timer not in use, and level matches - use it */
457 break;
458
459 if (!(tca->bank[i].on_dflt ||
460 led->on_dflt ||
461 tca->bank[i].ontime == led->ontime))
462 /* on time is incompatible */
463 continue;
464
465 if (!(tca->bank[i].off_dflt ||
466 led->off_dflt ||
467 tca->bank[i].offtime == led->offtime))
468 /* off time is incompatible */
469 continue;
470
471 /* looks like a suitable match */
472 break;
473 }
474
475 if (i > BANK1)
476 /* Nothing matches - how sad */
477 return -EINVAL;
478
479 b = &tca->bank[i];
480 if (b->level_use == 0)
481 set_level(tca, i, level);
482 b->level_use++;
483 led->bank = i;
484
485 if (b->on_dflt ||
486 !led->on_dflt ||
487 b->time_use == 0) {
488 b->ontime = led->ontime;
489 b->on_dflt = led->on_dflt;
490 need_init = 1;
491 }
492
493 if (b->off_dflt ||
494 !led->off_dflt ||
495 b->time_use == 0) {
496 b->offtime = led->offtime;
497 b->off_dflt = led->off_dflt;
498 need_init = 1;
499 }
500
501 if (need_init)
502 set_times(tca, i);
503
504 led->ontime = b->ontime;
505 led->offtime = b->offtime;
506
507 b->time_use++;
508 led->blink = 1;
509 led->led_cdev.brightness = TO_BRIGHT(b->level);
510 set_select(tca, led->num, blink_source[i]);
511 return 0;
512}
513
514static int led_assign(struct tca6507_led *led)
515{
516 struct tca6507_chip *tca = led->chip;
517 int err;
518 unsigned long flags;
519
520 spin_lock_irqsave(&tca->lock, flags);
521 led_release(led);
522 err = led_prepare(led);
523 if (err) {
524 /*
525 * Can only fail on timer setup. In that case we need to
526 * re-establish as steady level.
527 */
528 led->ontime = 0;
529 led->offtime = 0;
530 led_prepare(led);
531 }
532 spin_unlock_irqrestore(&tca->lock, flags);
533
534 if (tca->reg_set)
535 schedule_work(&tca->work);
536 return err;
537}
538
539static void tca6507_brightness_set(struct led_classdev *led_cdev,
540 enum led_brightness brightness)
541{
542 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
543 led_cdev);
544 led->led_cdev.brightness = brightness;
545 led->ontime = 0;
546 led->offtime = 0;
547 led_assign(led);
548}
549
550static int tca6507_blink_set(struct led_classdev *led_cdev,
551 unsigned long *delay_on,
552 unsigned long *delay_off)
553{
554 struct tca6507_led *led = container_of(led_cdev, struct tca6507_led,
555 led_cdev);
556
557 if (*delay_on == 0)
558 led->on_dflt = 1;
559 else if (delay_on != &led_cdev->blink_delay_on)
560 led->on_dflt = 0;
561 led->ontime = *delay_on;
562
563 if (*delay_off == 0)
564 led->off_dflt = 1;
565 else if (delay_off != &led_cdev->blink_delay_off)
566 led->off_dflt = 0;
567 led->offtime = *delay_off;
568
569 if (led->ontime == 0)
570 led->ontime = 512;
571 if (led->offtime == 0)
572 led->offtime = 512;
573
574 if (led->led_cdev.brightness == LED_OFF)
575 led->led_cdev.brightness = LED_FULL;
576 if (led_assign(led) < 0) {
577 led->ontime = 0;
578 led->offtime = 0;
579 led->led_cdev.brightness = LED_OFF;
580 return -EINVAL;
581 }
582 *delay_on = led->ontime;
583 *delay_off = led->offtime;
584 return 0;
585}
586
587#ifdef CONFIG_GPIOLIB
588static void tca6507_gpio_set_value(struct gpio_chip *gc,
589 unsigned offset, int val)
590{
591 struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio);
592 unsigned long flags;
593
594 spin_lock_irqsave(&tca->lock, flags);
595 /*
596 * 'OFF' is floating high, and 'ON' is pulled down, so it has the
597 * inverse sense of 'val'.
598 */
599 set_select(tca, tca->gpio_map[offset],
600 val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON);
601 spin_unlock_irqrestore(&tca->lock, flags);
602 if (tca->reg_set)
603 schedule_work(&tca->work);
604}
605
606static int tca6507_gpio_direction_output(struct gpio_chip *gc,
607 unsigned offset, int val)
608{
609 tca6507_gpio_set_value(gc, offset, val);
610 return 0;
611}
612
613static int tca6507_probe_gpios(struct i2c_client *client,
614 struct tca6507_chip *tca,
615 struct tca6507_platform_data *pdata)
616{
617 int err;
618 int i = 0;
619 int gpios = 0;
620
621 for (i = 0; i < NUM_LEDS; i++)
622 if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) {
623 /* Configure as a gpio */
624 tca->gpio_name[gpios] = pdata->leds.leds[i].name;
625 tca->gpio_map[gpios] = i;
626 gpios++;
627 }
628
629 if (!gpios)
630 return 0;
631
632 tca->gpio.label = "gpio-tca6507";
633 tca->gpio.names = tca->gpio_name;
634 tca->gpio.ngpio = gpios;
635 tca->gpio.base = pdata->gpio_base;
636 tca->gpio.owner = THIS_MODULE;
637 tca->gpio.direction_output = tca6507_gpio_direction_output;
638 tca->gpio.set = tca6507_gpio_set_value;
639 tca->gpio.dev = &client->dev;
640 err = gpiochip_add(&tca->gpio);
641 if (err) {
642 tca->gpio.ngpio = 0;
643 return err;
644 }
645 if (pdata->setup)
646 pdata->setup(tca->gpio.base, tca->gpio.ngpio);
647 return 0;
648}
649
650static void tca6507_remove_gpio(struct tca6507_chip *tca)
651{
652 if (tca->gpio.ngpio) {
653 int err = gpiochip_remove(&tca->gpio);
654 dev_err(&tca->client->dev, "%s failed, %d\n",
655 "gpiochip_remove()", err);
656 }
657}
658#else /* CONFIG_GPIOLIB */
659static int tca6507_probe_gpios(struct i2c_client *client,
660 struct tca6507_chip *tca,
661 struct tca6507_platform_data *pdata)
662{
663 return 0;
664}
665static void tca6507_remove_gpio(struct tca6507_chip *tca)
666{
667}
668#endif /* CONFIG_GPIOLIB */
669
670static int __devinit tca6507_probe(struct i2c_client *client,
671 const struct i2c_device_id *id)
672{
673 struct tca6507_chip *tca;
674 struct i2c_adapter *adapter;
675 struct tca6507_platform_data *pdata;
676 int err;
677 int i = 0;
678
679 adapter = to_i2c_adapter(client->dev.parent);
680 pdata = client->dev.platform_data;
681
682 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
683 return -EIO;
684
685 if (!pdata || pdata->leds.num_leds != NUM_LEDS) {
686 dev_err(&client->dev, "Need %d entries in platform-data list\n",
687 NUM_LEDS);
688 return -ENODEV;
689 }
690 err = -ENOMEM;
691 tca = kzalloc(sizeof(*tca), GFP_KERNEL);
692 if (!tca)
693 goto exit;
694
695 tca->client = client;
696 INIT_WORK(&tca->work, tca6507_work);
697 spin_lock_init(&tca->lock);
698 i2c_set_clientdata(client, tca);
699
700 for (i = 0; i < NUM_LEDS; i++) {
701 struct tca6507_led *l = tca->leds + i;
702
703 l->chip = tca;
704 l->num = i;
705 if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) {
706 l->led_cdev.name = pdata->leds.leds[i].name;
707 l->led_cdev.default_trigger
708 = pdata->leds.leds[i].default_trigger;
709 l->led_cdev.brightness_set = tca6507_brightness_set;
710 l->led_cdev.blink_set = tca6507_blink_set;
711 l->bank = -1;
712 err = led_classdev_register(&client->dev,
713 &l->led_cdev);
714 if (err < 0)
715 goto exit;
716 }
717 }
718 err = tca6507_probe_gpios(client, tca, pdata);
719 if (err)
720 goto exit;
721 /* set all registers to known state - zero */
722 tca->reg_set = 0x7f;
723 schedule_work(&tca->work);
724
725 return 0;
726exit:
727 while (i--)
728 if (tca->leds[i].led_cdev.name)
729 led_classdev_unregister(&tca->leds[i].led_cdev);
730 cancel_work_sync(&tca->work);
731 i2c_set_clientdata(client, NULL);
732 kfree(tca);
733 return err;
734}
735
736static int __devexit tca6507_remove(struct i2c_client *client)
737{
738 int i;
739 struct tca6507_chip *tca = i2c_get_clientdata(client);
740 struct tca6507_led *tca_leds = tca->leds;
741
742 for (i = 0; i < NUM_LEDS; i++) {
743 if (tca_leds[i].led_cdev.name)
744 led_classdev_unregister(&tca_leds[i].led_cdev);
745 }
746 tca6507_remove_gpio(tca);
747 cancel_work_sync(&tca->work);
748 i2c_set_clientdata(client, NULL);
749 kfree(tca);
750
751 return 0;
752}
753
754static struct i2c_driver tca6507_driver = {
755 .driver = {
756 .name = "leds-tca6507",
757 .owner = THIS_MODULE,
758 },
759 .probe = tca6507_probe,
760 .remove = __devexit_p(tca6507_remove),
761 .id_table = tca6507_id,
762};
763
764static int __init tca6507_leds_init(void)
765{
766 return i2c_add_driver(&tca6507_driver);
767}
768
769static void __exit tca6507_leds_exit(void)
770{
771 i2c_del_driver(&tca6507_driver);
772}
773
774module_init(tca6507_leds_init);
775module_exit(tca6507_leds_exit);
776
777MODULE_AUTHOR("NeilBrown <neilb@suse.de>");
778MODULE_DESCRIPTION("TCA6507 LED/GPO driver");
779MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index b1eb34c3e81f..74a24cf897c3 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -237,7 +237,8 @@ static int wm831x_status_probe(struct platform_device *pdev)
237 goto err; 237 goto err;
238 } 238 }
239 239
240 drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL); 240 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
241 GFP_KERNEL);
241 if (!drvdata) 242 if (!drvdata)
242 return -ENOMEM; 243 return -ENOMEM;
243 dev_set_drvdata(&pdev->dev, drvdata); 244 dev_set_drvdata(&pdev->dev, drvdata);
@@ -300,7 +301,6 @@ static int wm831x_status_probe(struct platform_device *pdev)
300 301
301err_led: 302err_led:
302 led_classdev_unregister(&drvdata->cdev); 303 led_classdev_unregister(&drvdata->cdev);
303 kfree(drvdata);
304err: 304err:
305 return ret; 305 return ret;
306} 306}
@@ -311,7 +311,6 @@ static int wm831x_status_remove(struct platform_device *pdev)
311 311
312 device_remove_file(drvdata->cdev.dev, &dev_attr_src); 312 device_remove_file(drvdata->cdev.dev, &dev_attr_src);
313 led_classdev_unregister(&drvdata->cdev); 313 led_classdev_unregister(&drvdata->cdev);
314 kfree(drvdata);
315 314
316 return 0; 315 return 0;
317} 316}
@@ -325,17 +324,7 @@ static struct platform_driver wm831x_status_driver = {
325 .remove = wm831x_status_remove, 324 .remove = wm831x_status_remove,
326}; 325};
327 326
328static int __devinit wm831x_status_init(void) 327module_platform_driver(wm831x_status_driver);
329{
330 return platform_driver_register(&wm831x_status_driver);
331}
332module_init(wm831x_status_init);
333
334static void wm831x_status_exit(void)
335{
336 platform_driver_unregister(&wm831x_status_driver);
337}
338module_exit(wm831x_status_exit);
339 328
340MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 329MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
341MODULE_DESCRIPTION("WM831x status LED driver"); 330MODULE_DESCRIPTION("WM831x status LED driver");
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 4a1276578352..918d4baff1c7 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -227,7 +227,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
227 goto err_isink; 227 goto err_isink;
228 } 228 }
229 229
230 led = kzalloc(sizeof(*led), GFP_KERNEL); 230 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
231 if (led == NULL) { 231 if (led == NULL) {
232 ret = -ENOMEM; 232 ret = -ENOMEM;
233 goto err_dcdc; 233 goto err_dcdc;
@@ -259,12 +259,10 @@ static int wm8350_led_probe(struct platform_device *pdev)
259 259
260 ret = led_classdev_register(&pdev->dev, &led->cdev); 260 ret = led_classdev_register(&pdev->dev, &led->cdev);
261 if (ret < 0) 261 if (ret < 0)
262 goto err_led; 262 goto err_dcdc;
263 263
264 return 0; 264 return 0;
265 265
266 err_led:
267 kfree(led);
268 err_dcdc: 266 err_dcdc:
269 regulator_put(dcdc); 267 regulator_put(dcdc);
270 err_isink: 268 err_isink:
@@ -281,7 +279,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
281 wm8350_led_disable(led); 279 wm8350_led_disable(led);
282 regulator_put(led->dcdc); 280 regulator_put(led->dcdc);
283 regulator_put(led->isink); 281 regulator_put(led->isink);
284 kfree(led);
285 return 0; 282 return 0;
286} 283}
287 284
@@ -295,17 +292,7 @@ static struct platform_driver wm8350_led_driver = {
295 .shutdown = wm8350_led_shutdown, 292 .shutdown = wm8350_led_shutdown,
296}; 293};
297 294
298static int __devinit wm8350_led_init(void) 295module_platform_driver(wm8350_led_driver);
299{
300 return platform_driver_register(&wm8350_led_driver);
301}
302module_init(wm8350_led_init);
303
304static void wm8350_led_exit(void)
305{
306 platform_driver_unregister(&wm8350_led_driver);
307}
308module_exit(wm8350_led_exit);
309 296
310MODULE_AUTHOR("Mark Brown"); 297MODULE_AUTHOR("Mark Brown");
311MODULE_DESCRIPTION("WM8350 LED driver"); 298MODULE_DESCRIPTION("WM8350 LED driver");