aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/Kconfig14
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-gt683r.c321
-rw-r--r--drivers/hid/hid-ids.h2
-rw-r--r--drivers/hid/usbhid/hid-quirks.c2
-rw-r--r--drivers/input/keyboard/lm8323.c22
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/led-class.c19
-rw-r--r--drivers/leds/led-core.c11
-rw-r--r--drivers/leds/leds-ipaq-micro.c141
-rw-r--r--drivers/leds/leds-lm3530.c20
-rw-r--r--drivers/leds/leds-lm3533.c20
-rw-r--r--drivers/leds/leds-lm355x.c21
-rw-r--r--drivers/leds/leds-lm3642.c30
-rw-r--r--drivers/leds/leds-lp55xx-common.c20
-rw-r--r--drivers/leds/leds-max8997.c16
-rw-r--r--drivers/leds/leds-netxbig.c31
-rw-r--r--drivers/leds/leds-ns2.c16
-rw-r--r--drivers/leds/leds-pca963x.c28
-rw-r--r--drivers/leds/leds-ss4200.c14
-rw-r--r--drivers/leds/leds-wm831x-status.c23
23 files changed, 619 insertions, 162 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index e02cf59b048d..ec48c823b157 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -261,6 +261,20 @@ config HOLTEK_FF
261 Say Y here if you have a Holtek On Line Grip based game controller 261 Say Y here if you have a Holtek On Line Grip based game controller
262 and want to have force feedback support for it. 262 and want to have force feedback support for it.
263 263
264config HID_GT683R
265 tristate "MSI GT68xR LED support"
266 depends on LEDS_CLASS && USB_HID
267 ---help---
268 Say Y here if you want to enable support for the three MSI GT68xR LEDs
269
270 This driver support following modes:
271 - Normal: LEDs are fully on when enabled
272 - Audio: LEDs brightness depends on sound level
273 - Breathing: LEDs brightness varies at human breathing rate
274
275 Currently the following devices are know to be supported:
276 - MSI GT683R
277
264config HID_HUION 278config HID_HUION
265 tristate "Huion tablets" 279 tristate "Huion tablets"
266 depends on USB_HID 280 depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 5e96be3ab280..a69f0adb5c76 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
48obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 48obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
49obj-$(CONFIG_HID_ELO) += hid-elo.o 49obj-$(CONFIG_HID_ELO) += hid-elo.o
50obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 50obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
51obj-$(CONFIG_HID_GT683R) += hid-gt683r.o
51obj-$(CONFIG_HID_GYRATION) += hid-gyration.o 52obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
52obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o 53obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
53obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o 54obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6c813c6092f8..b52baa120ffa 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1849,6 +1849,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1849 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, 1849 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
1850 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, 1850 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
1851 { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, 1851 { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
1852 { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
1852 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, 1853 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
1853 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, 1854 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
1854 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) }, 1855 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
diff --git a/drivers/hid/hid-gt683r.c b/drivers/hid/hid-gt683r.c
new file mode 100644
index 000000000000..0d6f135e266c
--- /dev/null
+++ b/drivers/hid/hid-gt683r.c
@@ -0,0 +1,321 @@
1/*
2 * MSI GT683R led driver
3 *
4 * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/device.h>
19#include <linux/hid.h>
20#include <linux/kernel.h>
21#include <linux/leds.h>
22#include <linux/module.h>
23
24#include "hid-ids.h"
25
26#define GT683R_BUFFER_SIZE 8
27
28/*
29 * GT683R_LED_OFF: all LEDs are off
30 * GT683R_LED_AUDIO: LEDs brightness depends on sound level
31 * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate
32 * GT683R_LED_NORMAL: LEDs are fully on when enabled
33 */
34enum gt683r_led_mode {
35 GT683R_LED_OFF = 0,
36 GT683R_LED_AUDIO = 2,
37 GT683R_LED_BREATHING = 3,
38 GT683R_LED_NORMAL = 5
39};
40
41enum gt683r_panels {
42 GT683R_LED_BACK = 0,
43 GT683R_LED_SIDE = 1,
44 GT683R_LED_FRONT = 2,
45 GT683R_LED_COUNT,
46};
47
48static const char * const gt683r_panel_names[] = {
49 "back",
50 "side",
51 "front",
52};
53
54struct gt683r_led {
55 struct hid_device *hdev;
56 struct led_classdev led_devs[GT683R_LED_COUNT];
57 struct mutex lock;
58 struct work_struct work;
59 enum led_brightness brightnesses[GT683R_LED_COUNT];
60 enum gt683r_led_mode mode;
61};
62
63static const struct hid_device_id gt683r_led_id[] = {
64 { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
65 { }
66};
67
68static void gt683r_brightness_set(struct led_classdev *led_cdev,
69 enum led_brightness brightness)
70{
71 int i;
72 struct device *dev = led_cdev->dev->parent;
73 struct hid_device *hdev = container_of(dev, struct hid_device, dev);
74 struct gt683r_led *led = hid_get_drvdata(hdev);
75
76 for (i = 0; i < GT683R_LED_COUNT; i++) {
77 if (led_cdev == &led->led_devs[i])
78 break;
79 }
80
81 if (i < GT683R_LED_COUNT) {
82 led->brightnesses[i] = brightness;
83 schedule_work(&led->work);
84 }
85}
86
87static ssize_t mode_show(struct device *dev,
88 struct device_attribute *attr,
89 char *buf)
90{
91 u8 sysfs_mode;
92 struct hid_device *hdev = container_of(dev->parent,
93 struct hid_device, dev);
94 struct gt683r_led *led = hid_get_drvdata(hdev);
95
96 if (led->mode == GT683R_LED_NORMAL)
97 sysfs_mode = 0;
98 else if (led->mode == GT683R_LED_AUDIO)
99 sysfs_mode = 1;
100 else
101 sysfs_mode = 2;
102
103 return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode);
104}
105
106static ssize_t mode_store(struct device *dev,
107 struct device_attribute *attr,
108 const char *buf, size_t count)
109{
110 u8 sysfs_mode;
111 struct hid_device *hdev = container_of(dev->parent,
112 struct hid_device, dev);
113 struct gt683r_led *led = hid_get_drvdata(hdev);
114
115
116 if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2)
117 return -EINVAL;
118
119 mutex_lock(&led->lock);
120
121 if (sysfs_mode == 0)
122 led->mode = GT683R_LED_NORMAL;
123 else if (sysfs_mode == 1)
124 led->mode = GT683R_LED_AUDIO;
125 else
126 led->mode = GT683R_LED_BREATHING;
127
128 mutex_unlock(&led->lock);
129 schedule_work(&led->work);
130
131 return count;
132}
133
134static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg)
135{
136 int ret;
137
138 ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE,
139 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
140 if (ret != GT683R_BUFFER_SIZE) {
141 hid_err(led->hdev,
142 "failed to send set report request: %i\n", ret);
143 if (ret < 0)
144 return ret;
145 return -EIO;
146 }
147
148 return 0;
149}
150
151static int gt683r_leds_set(struct gt683r_led *led, u8 leds)
152{
153 int ret;
154 u8 *buffer;
155
156 buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
157 if (!buffer)
158 return -ENOMEM;
159
160 buffer[0] = 0x01;
161 buffer[1] = 0x02;
162 buffer[2] = 0x30;
163 buffer[3] = leds;
164 ret = gt683r_led_snd_msg(led, buffer);
165
166 kfree(buffer);
167 return ret;
168}
169
170static int gt683r_mode_set(struct gt683r_led *led, u8 mode)
171{
172 int ret;
173 u8 *buffer;
174
175 buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
176 if (!buffer)
177 return -ENOMEM;
178
179 buffer[0] = 0x01;
180 buffer[1] = 0x02;
181 buffer[2] = 0x20;
182 buffer[3] = mode;
183 buffer[4] = 0x01;
184 ret = gt683r_led_snd_msg(led, buffer);
185
186 kfree(buffer);
187 return ret;
188}
189
190static void gt683r_led_work(struct work_struct *work)
191{
192 int i;
193 u8 leds = 0;
194 u8 mode;
195 struct gt683r_led *led = container_of(work, struct gt683r_led, work);
196
197 mutex_lock(&led->lock);
198
199 for (i = 0; i < GT683R_LED_COUNT; i++) {
200 if (led->brightnesses[i])
201 leds |= BIT(i);
202 }
203
204 if (gt683r_leds_set(led, leds))
205 goto fail;
206
207 if (leds)
208 mode = led->mode;
209 else
210 mode = GT683R_LED_OFF;
211
212 gt683r_mode_set(led, mode);
213fail:
214 mutex_unlock(&led->lock);
215}
216
217static DEVICE_ATTR_RW(mode);
218
219static struct attribute *gt683r_led_attrs[] = {
220 &dev_attr_mode.attr,
221 NULL
222};
223
224static const struct attribute_group gt683r_led_group = {
225 .name = "gt683r",
226 .attrs = gt683r_led_attrs,
227};
228
229static const struct attribute_group *gt683r_led_groups[] = {
230 &gt683r_led_group,
231 NULL
232};
233
234static int gt683r_led_probe(struct hid_device *hdev,
235 const struct hid_device_id *id)
236{
237 int i;
238 int ret;
239 int name_sz;
240 char *name;
241 struct gt683r_led *led;
242
243 led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL);
244 if (!led)
245 return -ENOMEM;
246
247 mutex_init(&led->lock);
248 INIT_WORK(&led->work, gt683r_led_work);
249
250 led->mode = GT683R_LED_NORMAL;
251 led->hdev = hdev;
252 hid_set_drvdata(hdev, led);
253
254 ret = hid_parse(hdev);
255 if (ret) {
256 hid_err(hdev, "hid parsing failed\n");
257 return ret;
258 }
259
260 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
261 if (ret) {
262 hid_err(hdev, "hw start failed\n");
263 return ret;
264 }
265
266 for (i = 0; i < GT683R_LED_COUNT; i++) {
267 name_sz = strlen(dev_name(&hdev->dev)) +
268 strlen(gt683r_panel_names[i]) + 3;
269
270 name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
271 if (!name) {
272 ret = -ENOMEM;
273 goto fail;
274 }
275
276 snprintf(name, name_sz, "%s::%s",
277 dev_name(&hdev->dev), gt683r_panel_names[i]);
278 led->led_devs[i].name = name;
279 led->led_devs[i].max_brightness = 1;
280 led->led_devs[i].brightness_set = gt683r_brightness_set;
281 led->led_devs[i].groups = gt683r_led_groups;
282
283 ret = led_classdev_register(&hdev->dev, &led->led_devs[i]);
284 if (ret) {
285 hid_err(hdev, "could not register led device\n");
286 goto fail;
287 }
288 }
289
290 return 0;
291
292fail:
293 for (i = i - 1; i >= 0; i--)
294 led_classdev_unregister(&led->led_devs[i]);
295 hid_hw_stop(hdev);
296 return ret;
297}
298
299static void gt683r_led_remove(struct hid_device *hdev)
300{
301 int i;
302 struct gt683r_led *led = hid_get_drvdata(hdev);
303
304 for (i = 0; i < GT683R_LED_COUNT; i++)
305 led_classdev_unregister(&led->led_devs[i]);
306 flush_work(&led->work);
307 hid_hw_stop(hdev);
308}
309
310static struct hid_driver gt683r_led_driver = {
311 .probe = gt683r_led_probe,
312 .remove = gt683r_led_remove,
313 .name = "gt683r_led",
314 .id_table = gt683r_led_id,
315};
316
317module_hid_driver(gt683r_led_driver);
318
319MODULE_AUTHOR("Janne Kanniainen");
320MODULE_DESCRIPTION("MSI GT683R led driver");
321MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index d53bdda26207..25cd674d6064 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -650,7 +650,7 @@
650#define USB_DEVICE_ID_GENIUS_KB29E 0x3004 650#define USB_DEVICE_ID_GENIUS_KB29E 0x3004
651 651
652#define USB_VENDOR_ID_MSI 0x1770 652#define USB_VENDOR_ID_MSI 0x1770
653#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL 0xff00 653#define USB_DEVICE_ID_MSI_GT683R_LED_PANEL 0xff00
654 654
655#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 655#define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
656#define USB_DEVICE_ID_N_S_HARMONY 0xc359 656#define USB_DEVICE_ID_N_S_HARMONY 0xc359
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 0dd568170d6e..15225f3eaed1 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -74,7 +74,7 @@ static const struct hid_blacklist {
74 { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, 74 { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
75 { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, 75 { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
76 { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, 76 { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
77 { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, 77 { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
78 { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, 78 { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
79 { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, 79 { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
80 { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET }, 80 { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET },
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 0b42118cbf8f..cb32e2b506b7 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -558,6 +558,12 @@ static ssize_t lm8323_pwm_store_time(struct device *dev,
558} 558}
559static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time); 559static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time);
560 560
561static struct attribute *lm8323_pwm_attrs[] = {
562 &dev_attr_time.attr,
563 NULL
564};
565ATTRIBUTE_GROUPS(lm8323_pwm);
566
561static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, 567static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev,
562 const char *name) 568 const char *name)
563{ 569{
@@ -580,16 +586,11 @@ static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev,
580 if (name) { 586 if (name) {
581 pwm->cdev.name = name; 587 pwm->cdev.name = name;
582 pwm->cdev.brightness_set = lm8323_pwm_set_brightness; 588 pwm->cdev.brightness_set = lm8323_pwm_set_brightness;
589 pwm->cdev.groups = lm8323_pwm_groups;
583 if (led_classdev_register(dev, &pwm->cdev) < 0) { 590 if (led_classdev_register(dev, &pwm->cdev) < 0) {
584 dev_err(dev, "couldn't register PWM %d\n", id); 591 dev_err(dev, "couldn't register PWM %d\n", id);
585 return -1; 592 return -1;
586 } 593 }
587 if (device_create_file(pwm->cdev.dev,
588 &dev_attr_time) < 0) {
589 dev_err(dev, "couldn't register time attribute\n");
590 led_classdev_unregister(&pwm->cdev);
591 return -1;
592 }
593 pwm->enabled = true; 594 pwm->enabled = true;
594 } 595 }
595 596
@@ -753,11 +754,8 @@ fail3:
753 device_remove_file(&client->dev, &dev_attr_disable_kp); 754 device_remove_file(&client->dev, &dev_attr_disable_kp);
754fail2: 755fail2:
755 while (--pwm >= 0) 756 while (--pwm >= 0)
756 if (lm->pwm[pwm].enabled) { 757 if (lm->pwm[pwm].enabled)
757 device_remove_file(lm->pwm[pwm].cdev.dev,
758 &dev_attr_time);
759 led_classdev_unregister(&lm->pwm[pwm].cdev); 758 led_classdev_unregister(&lm->pwm[pwm].cdev);
760 }
761fail1: 759fail1:
762 input_free_device(idev); 760 input_free_device(idev);
763 kfree(lm); 761 kfree(lm);
@@ -777,10 +775,8 @@ static int lm8323_remove(struct i2c_client *client)
777 device_remove_file(&lm->client->dev, &dev_attr_disable_kp); 775 device_remove_file(&lm->client->dev, &dev_attr_disable_kp);
778 776
779 for (i = 0; i < 3; i++) 777 for (i = 0; i < 3; i++)
780 if (lm->pwm[i].enabled) { 778 if (lm->pwm[i].enabled)
781 device_remove_file(lm->pwm[i].cdev.dev, &dev_attr_time);
782 led_classdev_unregister(&lm->pwm[i].cdev); 779 led_classdev_unregister(&lm->pwm[i].cdev);
783 }
784 780
785 kfree(lm); 781 kfree(lm);
786 782
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a1b044e7eaad..30e82860567a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -143,6 +143,13 @@ config LEDS_SUNFIRE
143 This option enables support for the Left, Middle, and Right 143 This option enables support for the Left, Middle, and Right
144 LEDs on the I/O and CPU boards of SunFire UltraSPARC servers. 144 LEDs on the I/O and CPU boards of SunFire UltraSPARC servers.
145 145
146config LEDS_IPAQ_MICRO
147 tristate "LED Support for the Compaq iPAQ h3xxx"
148 depends on MFD_IPAQ_MICRO
149 help
150 Choose this option if you want to use the notification LED on
151 Compaq/HP iPAQ h3100 and h3600.
152
146config LEDS_HP6XX 153config LEDS_HP6XX
147 tristate "LED Support for the HP Jornada 6xx" 154 tristate "LED Support for the HP Jornada 6xx"
148 depends on LEDS_CLASS 155 depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 79c5155199a7..b2a62959ff8f 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o
31obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o 31obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o
32obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o 32obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o
33obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 33obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
34obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o
34obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 35obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
35obj-$(CONFIG_LEDS_OT200) += leds-ot200.o 36obj-$(CONFIG_LEDS_OT200) += leds-ot200.o
36obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 37obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index f37d63cf726b..129729d35478 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -15,10 +15,10 @@
15#include <linux/list.h> 15#include <linux/list.h>
16#include <linux/spinlock.h> 16#include <linux/spinlock.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/timer.h>
19#include <linux/err.h> 18#include <linux/err.h>
20#include <linux/ctype.h> 19#include <linux/ctype.h>
21#include <linux/leds.h> 20#include <linux/leds.h>
21#include <linux/workqueue.h>
22#include "leds.h" 22#include "leds.h"
23 23
24static struct class *leds_class; 24static struct class *leds_class;
@@ -97,9 +97,10 @@ static const struct attribute_group *led_groups[] = {
97 NULL, 97 NULL,
98}; 98};
99 99
100static void led_timer_function(unsigned long data) 100static void led_work_function(struct work_struct *ws)
101{ 101{
102 struct led_classdev *led_cdev = (void *)data; 102 struct led_classdev *led_cdev =
103 container_of(ws, struct led_classdev, blink_work.work);
103 unsigned long brightness; 104 unsigned long brightness;
104 unsigned long delay; 105 unsigned long delay;
105 106
@@ -143,7 +144,8 @@ static void led_timer_function(unsigned long data)
143 } 144 }
144 } 145 }
145 146
146 mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); 147 queue_delayed_work(system_wq, &led_cdev->blink_work,
148 msecs_to_jiffies(delay));
147} 149}
148 150
149static void set_brightness_delayed(struct work_struct *ws) 151static void set_brightness_delayed(struct work_struct *ws)
@@ -210,8 +212,9 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
210 */ 212 */
211int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) 213int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
212{ 214{
213 led_cdev->dev = device_create(leds_class, parent, 0, led_cdev, 215 led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
214 "%s", led_cdev->name); 216 led_cdev, led_cdev->groups,
217 "%s", led_cdev->name);
215 if (IS_ERR(led_cdev->dev)) 218 if (IS_ERR(led_cdev->dev))
216 return PTR_ERR(led_cdev->dev); 219 return PTR_ERR(led_cdev->dev);
217 220
@@ -230,9 +233,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
230 233
231 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); 234 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
232 235
233 init_timer(&led_cdev->blink_timer); 236 INIT_DELAYED_WORK(&led_cdev->blink_work, led_work_function);
234 led_cdev->blink_timer.function = led_timer_function;
235 led_cdev->blink_timer.data = (unsigned long)led_cdev;
236 237
237#ifdef CONFIG_LEDS_TRIGGERS 238#ifdef CONFIG_LEDS_TRIGGERS
238 led_trigger_set_default(led_cdev); 239 led_trigger_set_default(led_cdev);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 71b40d3bf776..4bb116867b88 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -16,6 +16,7 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/rwsem.h> 17#include <linux/rwsem.h>
18#include <linux/leds.h> 18#include <linux/leds.h>
19#include <linux/workqueue.h>
19#include "leds.h" 20#include "leds.h"
20 21
21DECLARE_RWSEM(leds_list_lock); 22DECLARE_RWSEM(leds_list_lock);
@@ -51,7 +52,7 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
51 return; 52 return;
52 } 53 }
53 54
54 mod_timer(&led_cdev->blink_timer, jiffies + 1); 55 queue_delayed_work(system_wq, &led_cdev->blink_work, 1);
55} 56}
56 57
57 58
@@ -75,7 +76,7 @@ void led_blink_set(struct led_classdev *led_cdev,
75 unsigned long *delay_on, 76 unsigned long *delay_on,
76 unsigned long *delay_off) 77 unsigned long *delay_off)
77{ 78{
78 del_timer_sync(&led_cdev->blink_timer); 79 cancel_delayed_work_sync(&led_cdev->blink_work);
79 80
80 led_cdev->flags &= ~LED_BLINK_ONESHOT; 81 led_cdev->flags &= ~LED_BLINK_ONESHOT;
81 led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; 82 led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
@@ -90,7 +91,7 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
90 int invert) 91 int invert)
91{ 92{
92 if ((led_cdev->flags & LED_BLINK_ONESHOT) && 93 if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
93 timer_pending(&led_cdev->blink_timer)) 94 delayed_work_pending(&led_cdev->blink_work))
94 return; 95 return;
95 96
96 led_cdev->flags |= LED_BLINK_ONESHOT; 97 led_cdev->flags |= LED_BLINK_ONESHOT;
@@ -107,7 +108,7 @@ EXPORT_SYMBOL(led_blink_set_oneshot);
107 108
108void led_stop_software_blink(struct led_classdev *led_cdev) 109void led_stop_software_blink(struct led_classdev *led_cdev)
109{ 110{
110 del_timer_sync(&led_cdev->blink_timer); 111 cancel_delayed_work_sync(&led_cdev->blink_work);
111 led_cdev->blink_delay_on = 0; 112 led_cdev->blink_delay_on = 0;
112 led_cdev->blink_delay_off = 0; 113 led_cdev->blink_delay_off = 0;
113} 114}
@@ -116,7 +117,7 @@ EXPORT_SYMBOL_GPL(led_stop_software_blink);
116void led_set_brightness(struct led_classdev *led_cdev, 117void led_set_brightness(struct led_classdev *led_cdev,
117 enum led_brightness brightness) 118 enum led_brightness brightness)
118{ 119{
119 /* delay brightness setting if need to stop soft-blink timer */ 120 /* delay brightness setting if need to stop soft-blink work */
120 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 121 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
121 led_cdev->delayed_set_value = brightness; 122 led_cdev->delayed_set_value = brightness;
122 schedule_work(&led_cdev->set_brightness_work); 123 schedule_work(&led_cdev->set_brightness_work);
diff --git a/drivers/leds/leds-ipaq-micro.c b/drivers/leds/leds-ipaq-micro.c
new file mode 100644
index 000000000000..3776f516cd88
--- /dev/null
+++ b/drivers/leds/leds-ipaq-micro.c
@@ -0,0 +1,141 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * h3xxx atmel micro companion support, notification LED subdevice
7 *
8 * Author : Linus Walleij <linus.walleij@linaro.org>
9 */
10
11#include <linux/module.h>
12#include <linux/platform_device.h>
13#include <linux/mfd/ipaq-micro.h>
14#include <linux/leds.h>
15
16#define LED_YELLOW 0x00
17#define LED_GREEN 0x01
18
19#define LED_EN (1 << 4) /* LED ON/OFF 0:off, 1:on */
20#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
21#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
22
23static void micro_leds_brightness_set(struct led_classdev *led_cdev,
24 enum led_brightness value)
25{
26 struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
27 /*
28 * In this message:
29 * Byte 0 = LED color: 0 = yellow, 1 = green
30 * yellow LED is always ~30 blinks per minute
31 * Byte 1 = duration (flags?) appears to be ignored
32 * Byte 2 = green ontime in 1/10 sec (deciseconds)
33 * 1 = 1/10 second
34 * 0 = 256/10 second
35 * Byte 3 = green offtime in 1/10 sec (deciseconds)
36 * 1 = 1/10 second
37 * 0 = 256/10 seconds
38 */
39 struct ipaq_micro_msg msg = {
40 .id = MSG_NOTIFY_LED,
41 .tx_len = 4,
42 };
43
44 msg.tx_data[0] = LED_GREEN;
45 msg.tx_data[1] = 0;
46 if (value) {
47 msg.tx_data[2] = 0; /* Duty cycle 256 */
48 msg.tx_data[3] = 1;
49 } else {
50 msg.tx_data[2] = 1;
51 msg.tx_data[3] = 0; /* Duty cycle 256 */
52 }
53 ipaq_micro_tx_msg_sync(micro, &msg);
54}
55
56/* Maximum duty cycle in ms 256/10 sec = 25600 ms */
57#define IPAQ_LED_MAX_DUTY 25600
58
59static int micro_leds_blink_set(struct led_classdev *led_cdev,
60 unsigned long *delay_on,
61 unsigned long *delay_off)
62{
63 struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
64 /*
65 * In this message:
66 * Byte 0 = LED color: 0 = yellow, 1 = green
67 * yellow LED is always ~30 blinks per minute
68 * Byte 1 = duration (flags?) appears to be ignored
69 * Byte 2 = green ontime in 1/10 sec (deciseconds)
70 * 1 = 1/10 second
71 * 0 = 256/10 second
72 * Byte 3 = green offtime in 1/10 sec (deciseconds)
73 * 1 = 1/10 second
74 * 0 = 256/10 seconds
75 */
76 struct ipaq_micro_msg msg = {
77 .id = MSG_NOTIFY_LED,
78 .tx_len = 4,
79 };
80
81 msg.tx_data[0] = LED_GREEN;
82 if (*delay_on > IPAQ_LED_MAX_DUTY ||
83 *delay_off > IPAQ_LED_MAX_DUTY)
84 return -EINVAL;
85
86 if (*delay_on == 0 && *delay_off == 0) {
87 *delay_on = 100;
88 *delay_off = 100;
89 }
90
91 msg.tx_data[1] = 0;
92 if (*delay_on >= IPAQ_LED_MAX_DUTY)
93 msg.tx_data[2] = 0;
94 else
95 msg.tx_data[2] = (u8) DIV_ROUND_CLOSEST(*delay_on, 100);
96 if (*delay_off >= IPAQ_LED_MAX_DUTY)
97 msg.tx_data[3] = 0;
98 else
99 msg.tx_data[3] = (u8) DIV_ROUND_CLOSEST(*delay_off, 100);
100 return ipaq_micro_tx_msg_sync(micro, &msg);
101}
102
103static struct led_classdev micro_led = {
104 .name = "led-ipaq-micro",
105 .brightness_set = micro_leds_brightness_set,
106 .blink_set = micro_leds_blink_set,
107 .flags = LED_CORE_SUSPENDRESUME,
108};
109
110static int micro_leds_probe(struct platform_device *pdev)
111{
112 int ret;
113
114 ret = led_classdev_register(&pdev->dev, &micro_led);
115 if (ret) {
116 dev_err(&pdev->dev, "registering led failed: %d\n", ret);
117 return ret;
118 }
119 dev_info(&pdev->dev, "iPAQ micro notification LED driver\n");
120
121 return 0;
122}
123
124static int micro_leds_remove(struct platform_device *pdev)
125{
126 led_classdev_unregister(&micro_led);
127 return 0;
128}
129
130static struct platform_driver micro_leds_device_driver = {
131 .driver = {
132 .name = "ipaq-micro-leds",
133 },
134 .probe = micro_leds_probe,
135 .remove = micro_leds_remove,
136};
137module_platform_driver(micro_leds_device_driver);
138
139MODULE_LICENSE("GPL");
140MODULE_DESCRIPTION("driver for iPAQ Atmel micro leds");
141MODULE_ALIAS("platform:ipaq-micro-leds");
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 652368c2ea9a..91325de3cd33 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -400,6 +400,12 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
400} 400}
401static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set); 401static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set);
402 402
403static struct attribute *lm3530_attrs[] = {
404 &dev_attr_mode.attr,
405 NULL
406};
407ATTRIBUTE_GROUPS(lm3530);
408
403static int lm3530_probe(struct i2c_client *client, 409static int lm3530_probe(struct i2c_client *client,
404 const struct i2c_device_id *id) 410 const struct i2c_device_id *id)
405{ 411{
@@ -436,6 +442,7 @@ static int lm3530_probe(struct i2c_client *client,
436 drvdata->led_dev.name = LM3530_LED_DEV; 442 drvdata->led_dev.name = LM3530_LED_DEV;
437 drvdata->led_dev.brightness_set = lm3530_brightness_set; 443 drvdata->led_dev.brightness_set = lm3530_brightness_set;
438 drvdata->led_dev.max_brightness = MAX_BRIGHTNESS; 444 drvdata->led_dev.max_brightness = MAX_BRIGHTNESS;
445 drvdata->led_dev.groups = lm3530_groups;
439 446
440 i2c_set_clientdata(client, drvdata); 447 i2c_set_clientdata(client, drvdata);
441 448
@@ -461,26 +468,13 @@ static int lm3530_probe(struct i2c_client *client,
461 return err; 468 return err;
462 } 469 }
463 470
464 err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
465 if (err < 0) {
466 dev_err(&client->dev, "File device creation failed: %d\n", err);
467 err = -ENODEV;
468 goto err_create_file;
469 }
470
471 return 0; 471 return 0;
472
473err_create_file:
474 led_classdev_unregister(&drvdata->led_dev);
475 return err;
476} 472}
477 473
478static int lm3530_remove(struct i2c_client *client) 474static int lm3530_remove(struct i2c_client *client)
479{ 475{
480 struct lm3530_data *drvdata = i2c_get_clientdata(client); 476 struct lm3530_data *drvdata = i2c_get_clientdata(client);
481 477
482 device_remove_file(drvdata->led_dev.dev, &dev_attr_mode);
483
484 lm3530_led_disable(drvdata); 478 lm3530_led_disable(drvdata);
485 led_classdev_unregister(&drvdata->led_dev); 479 led_classdev_unregister(&drvdata->led_dev);
486 return 0; 480 return 0;
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index e2c642c1169b..cbf61a40137d 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -645,6 +645,11 @@ static struct attribute_group lm3533_led_attribute_group = {
645 .attrs = lm3533_led_attributes 645 .attrs = lm3533_led_attributes
646}; 646};
647 647
648static const struct attribute_group *lm3533_led_attribute_groups[] = {
649 &lm3533_led_attribute_group,
650 NULL
651};
652
648static int lm3533_led_setup(struct lm3533_led *led, 653static int lm3533_led_setup(struct lm3533_led *led,
649 struct lm3533_led_platform_data *pdata) 654 struct lm3533_led_platform_data *pdata)
650{ 655{
@@ -692,6 +697,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
692 led->cdev.brightness_get = lm3533_led_get; 697 led->cdev.brightness_get = lm3533_led_get;
693 led->cdev.blink_set = lm3533_led_blink_set; 698 led->cdev.blink_set = lm3533_led_blink_set;
694 led->cdev.brightness = LED_OFF; 699 led->cdev.brightness = LED_OFF;
700 led->cdev.groups = lm3533_led_attribute_groups,
695 led->id = pdev->id; 701 led->id = pdev->id;
696 702
697 mutex_init(&led->mutex); 703 mutex_init(&led->mutex);
@@ -715,25 +721,16 @@ static int lm3533_led_probe(struct platform_device *pdev)
715 721
716 led->cb.dev = led->cdev.dev; 722 led->cb.dev = led->cdev.dev;
717 723
718 ret = sysfs_create_group(&led->cdev.dev->kobj,
719 &lm3533_led_attribute_group);
720 if (ret < 0) {
721 dev_err(&pdev->dev, "failed to create sysfs attributes\n");
722 goto err_unregister;
723 }
724
725 ret = lm3533_led_setup(led, pdata); 724 ret = lm3533_led_setup(led, pdata);
726 if (ret) 725 if (ret)
727 goto err_sysfs_remove; 726 goto err_unregister;
728 727
729 ret = lm3533_ctrlbank_enable(&led->cb); 728 ret = lm3533_ctrlbank_enable(&led->cb);
730 if (ret) 729 if (ret)
731 goto err_sysfs_remove; 730 goto err_unregister;
732 731
733 return 0; 732 return 0;
734 733
735err_sysfs_remove:
736 sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
737err_unregister: 734err_unregister:
738 led_classdev_unregister(&led->cdev); 735 led_classdev_unregister(&led->cdev);
739 flush_work(&led->work); 736 flush_work(&led->work);
@@ -748,7 +745,6 @@ static int lm3533_led_remove(struct platform_device *pdev)
748 dev_dbg(&pdev->dev, "%s\n", __func__); 745 dev_dbg(&pdev->dev, "%s\n", __func__);
749 746
750 lm3533_ctrlbank_disable(&led->cb); 747 lm3533_ctrlbank_disable(&led->cb);
751 sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
752 led_classdev_unregister(&led->cdev); 748 led_classdev_unregister(&led->cdev);
753 flush_work(&led->work); 749 flush_work(&led->work);
754 750
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 591eb5e58ae3..f5112cb2d991 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -413,6 +413,12 @@ out:
413 413
414static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); 414static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
415 415
416static struct attribute *lm355x_indicator_attrs[] = {
417 &dev_attr_pattern.attr,
418 NULL
419};
420ATTRIBUTE_GROUPS(lm355x_indicator);
421
416static const struct regmap_config lm355x_regmap = { 422static const struct regmap_config lm355x_regmap = {
417 .reg_bits = 8, 423 .reg_bits = 8,
418 .val_bits = 8, 424 .val_bits = 8,
@@ -501,25 +507,18 @@ static int lm355x_probe(struct i2c_client *client,
501 else 507 else
502 chip->cdev_indicator.max_brightness = 8; 508 chip->cdev_indicator.max_brightness = 8;
503 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set; 509 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
510 /* indicator pattern control only for LM3556 */
511 if (id->driver_data == CHIP_LM3556)
512 chip->cdev_indicator.groups = lm355x_indicator_groups;
504 err = led_classdev_register((struct device *) 513 err = led_classdev_register((struct device *)
505 &client->dev, &chip->cdev_indicator); 514 &client->dev, &chip->cdev_indicator);
506 if (err < 0) 515 if (err < 0)
507 goto err_create_indicator_file; 516 goto err_create_indicator_file;
508 /* indicator pattern control only for LM3554 */
509 if (id->driver_data == CHIP_LM3556) {
510 err =
511 device_create_file(chip->cdev_indicator.dev,
512 &dev_attr_pattern);
513 if (err < 0)
514 goto err_create_pattern_file;
515 }
516 517
517 dev_info(&client->dev, "%s is initialized\n", 518 dev_info(&client->dev, "%s is initialized\n",
518 lm355x_name[id->driver_data]); 519 lm355x_name[id->driver_data]);
519 return 0; 520 return 0;
520 521
521err_create_pattern_file:
522 led_classdev_unregister(&chip->cdev_indicator);
523err_create_indicator_file: 522err_create_indicator_file:
524 led_classdev_unregister(&chip->cdev_torch); 523 led_classdev_unregister(&chip->cdev_torch);
525err_create_torch_file: 524err_create_torch_file:
@@ -534,8 +533,6 @@ static int lm355x_remove(struct i2c_client *client)
534 struct lm355x_reg_data *preg = chip->regs; 533 struct lm355x_reg_data *preg = chip->regs;
535 534
536 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0); 535 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
537 if (chip->type == CHIP_LM3556)
538 device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
539 led_classdev_unregister(&chip->cdev_indicator); 536 led_classdev_unregister(&chip->cdev_indicator);
540 flush_work(&chip->work_indicator); 537 flush_work(&chip->work_indicator);
541 led_classdev_unregister(&chip->cdev_torch); 538 led_classdev_unregister(&chip->cdev_torch);
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index ceb6b3cde6fe..d3dec0132769 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -313,6 +313,18 @@ static const struct regmap_config lm3642_regmap = {
313 .max_register = REG_MAX, 313 .max_register = REG_MAX,
314}; 314};
315 315
316static struct attribute *lm3642_flash_attrs[] = {
317 &dev_attr_strobe_pin.attr,
318 NULL
319};
320ATTRIBUTE_GROUPS(lm3642_flash);
321
322static struct attribute *lm3642_torch_attrs[] = {
323 &dev_attr_torch_pin.attr,
324 NULL
325};
326ATTRIBUTE_GROUPS(lm3642_torch);
327
316static int lm3642_probe(struct i2c_client *client, 328static int lm3642_probe(struct i2c_client *client,
317 const struct i2c_device_id *id) 329 const struct i2c_device_id *id)
318{ 330{
@@ -364,17 +376,13 @@ static int lm3642_probe(struct i2c_client *client,
364 chip->cdev_flash.max_brightness = 16; 376 chip->cdev_flash.max_brightness = 16;
365 chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set; 377 chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
366 chip->cdev_flash.default_trigger = "flash"; 378 chip->cdev_flash.default_trigger = "flash";
379 chip->cdev_flash.groups = lm3642_flash_groups,
367 err = led_classdev_register((struct device *) 380 err = led_classdev_register((struct device *)
368 &client->dev, &chip->cdev_flash); 381 &client->dev, &chip->cdev_flash);
369 if (err < 0) { 382 if (err < 0) {
370 dev_err(chip->dev, "failed to register flash\n"); 383 dev_err(chip->dev, "failed to register flash\n");
371 goto err_out; 384 goto err_out;
372 } 385 }
373 err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
374 if (err < 0) {
375 dev_err(chip->dev, "failed to create strobe-pin file\n");
376 goto err_create_flash_pin_file;
377 }
378 386
379 /* torch */ 387 /* torch */
380 INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set); 388 INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
@@ -382,17 +390,13 @@ static int lm3642_probe(struct i2c_client *client,
382 chip->cdev_torch.max_brightness = 8; 390 chip->cdev_torch.max_brightness = 8;
383 chip->cdev_torch.brightness_set = lm3642_torch_brightness_set; 391 chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
384 chip->cdev_torch.default_trigger = "torch"; 392 chip->cdev_torch.default_trigger = "torch";
393 chip->cdev_torch.groups = lm3642_torch_groups,
385 err = led_classdev_register((struct device *) 394 err = led_classdev_register((struct device *)
386 &client->dev, &chip->cdev_torch); 395 &client->dev, &chip->cdev_torch);
387 if (err < 0) { 396 if (err < 0) {
388 dev_err(chip->dev, "failed to register torch\n"); 397 dev_err(chip->dev, "failed to register torch\n");
389 goto err_create_torch_file; 398 goto err_create_torch_file;
390 } 399 }
391 err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
392 if (err < 0) {
393 dev_err(chip->dev, "failed to create torch-pin file\n");
394 goto err_create_torch_pin_file;
395 }
396 400
397 /* indicator */ 401 /* indicator */
398 INIT_WORK(&chip->work_indicator, 402 INIT_WORK(&chip->work_indicator,
@@ -411,12 +415,8 @@ static int lm3642_probe(struct i2c_client *client,
411 return 0; 415 return 0;
412 416
413err_create_indicator_file: 417err_create_indicator_file:
414 device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
415err_create_torch_pin_file:
416 led_classdev_unregister(&chip->cdev_torch); 418 led_classdev_unregister(&chip->cdev_torch);
417err_create_torch_file: 419err_create_torch_file:
418 device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
419err_create_flash_pin_file:
420 led_classdev_unregister(&chip->cdev_flash); 420 led_classdev_unregister(&chip->cdev_flash);
421err_out: 421err_out:
422 return err; 422 return err;
@@ -428,10 +428,8 @@ static int lm3642_remove(struct i2c_client *client)
428 428
429 led_classdev_unregister(&chip->cdev_indicator); 429 led_classdev_unregister(&chip->cdev_indicator);
430 flush_work(&chip->work_indicator); 430 flush_work(&chip->work_indicator);
431 device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
432 led_classdev_unregister(&chip->cdev_torch); 431 led_classdev_unregister(&chip->cdev_torch);
433 flush_work(&chip->work_torch); 432 flush_work(&chip->work_torch);
434 device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
435 led_classdev_unregister(&chip->cdev_flash); 433 led_classdev_unregister(&chip->cdev_flash);
436 flush_work(&chip->work_flash); 434 flush_work(&chip->work_flash);
437 regmap_write(chip->regmap, REG_ENABLE, 0); 435 regmap_write(chip->regmap, REG_ENABLE, 0);
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 88317b4f7bf3..77c26bc32eed 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -127,15 +127,12 @@ static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, lp55xx_show_current,
127 lp55xx_store_current); 127 lp55xx_store_current);
128static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL); 128static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL);
129 129
130static struct attribute *lp55xx_led_attributes[] = { 130static struct attribute *lp55xx_led_attrs[] = {
131 &dev_attr_led_current.attr, 131 &dev_attr_led_current.attr,
132 &dev_attr_max_current.attr, 132 &dev_attr_max_current.attr,
133 NULL, 133 NULL,
134}; 134};
135 135ATTRIBUTE_GROUPS(lp55xx_led);
136static struct attribute_group lp55xx_led_attr_group = {
137 .attrs = lp55xx_led_attributes
138};
139 136
140static void lp55xx_set_brightness(struct led_classdev *cdev, 137static void lp55xx_set_brightness(struct led_classdev *cdev,
141 enum led_brightness brightness) 138 enum led_brightness brightness)
@@ -176,6 +173,7 @@ static int lp55xx_init_led(struct lp55xx_led *led,
176 } 173 }
177 174
178 led->cdev.brightness_set = lp55xx_set_brightness; 175 led->cdev.brightness_set = lp55xx_set_brightness;
176 led->cdev.groups = lp55xx_led_groups;
179 177
180 if (pdata->led_config[chan].name) { 178 if (pdata->led_config[chan].name) {
181 led->cdev.name = pdata->led_config[chan].name; 179 led->cdev.name = pdata->led_config[chan].name;
@@ -185,24 +183,12 @@ static int lp55xx_init_led(struct lp55xx_led *led,
185 led->cdev.name = name; 183 led->cdev.name = name;
186 } 184 }
187 185
188 /*
189 * register led class device for each channel and
190 * add device attributes
191 */
192
193 ret = led_classdev_register(dev, &led->cdev); 186 ret = led_classdev_register(dev, &led->cdev);
194 if (ret) { 187 if (ret) {
195 dev_err(dev, "led register err: %d\n", ret); 188 dev_err(dev, "led register err: %d\n", ret);
196 return ret; 189 return ret;
197 } 190 }
198 191
199 ret = sysfs_create_group(&led->cdev.dev->kobj, &lp55xx_led_attr_group);
200 if (ret) {
201 dev_err(dev, "led sysfs err: %d\n", ret);
202 led_classdev_unregister(&led->cdev);
203 return ret;
204 }
205
206 return 0; 192 return 0;
207} 193}
208 194
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
index f449a8bdddc7..607bc2755aba 100644
--- a/drivers/leds/leds-max8997.c
+++ b/drivers/leds/leds-max8997.c
@@ -229,6 +229,12 @@ static ssize_t max8997_led_store_mode(struct device *dev,
229 229
230static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode); 230static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode);
231 231
232static struct attribute *max8997_attrs[] = {
233 &dev_attr_mode.attr,
234 NULL
235};
236ATTRIBUTE_GROUPS(max8997);
237
232static int max8997_led_probe(struct platform_device *pdev) 238static int max8997_led_probe(struct platform_device *pdev)
233{ 239{
234 struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); 240 struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
@@ -253,6 +259,7 @@ static int max8997_led_probe(struct platform_device *pdev)
253 led->cdev.brightness_set = max8997_led_brightness_set; 259 led->cdev.brightness_set = max8997_led_brightness_set;
254 led->cdev.flags |= LED_CORE_SUSPENDRESUME; 260 led->cdev.flags |= LED_CORE_SUSPENDRESUME;
255 led->cdev.brightness = 0; 261 led->cdev.brightness = 0;
262 led->cdev.groups = max8997_groups;
256 led->iodev = iodev; 263 led->iodev = iodev;
257 264
258 /* initialize mode and brightness according to platform_data */ 265 /* initialize mode and brightness according to platform_data */
@@ -281,14 +288,6 @@ static int max8997_led_probe(struct platform_device *pdev)
281 if (ret < 0) 288 if (ret < 0)
282 return ret; 289 return ret;
283 290
284 ret = device_create_file(led->cdev.dev, &dev_attr_mode);
285 if (ret != 0) {
286 dev_err(&pdev->dev,
287 "failed to create file: %d\n", ret);
288 led_classdev_unregister(&led->cdev);
289 return ret;
290 }
291
292 return 0; 291 return 0;
293} 292}
294 293
@@ -296,7 +295,6 @@ static int max8997_led_remove(struct platform_device *pdev)
296{ 295{
297 struct max8997_led *led = platform_get_drvdata(pdev); 296 struct max8997_led *led = platform_get_drvdata(pdev);
298 297
299 device_remove_file(led->cdev.dev, &dev_attr_mode);
300 led_classdev_unregister(&led->cdev); 298 led_classdev_unregister(&led->cdev);
301 299
302 return 0; 300 return 0;
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index e97f443a6e07..64fde485dcaa 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -293,10 +293,14 @@ static ssize_t netxbig_led_sata_show(struct device *dev,
293 293
294static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); 294static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store);
295 295
296static struct attribute *netxbig_led_attrs[] = {
297 &dev_attr_sata.attr,
298 NULL
299};
300ATTRIBUTE_GROUPS(netxbig_led);
301
296static void delete_netxbig_led(struct netxbig_led_data *led_dat) 302static void delete_netxbig_led(struct netxbig_led_data *led_dat)
297{ 303{
298 if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
299 device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
300 led_classdev_unregister(&led_dat->cdev); 304 led_classdev_unregister(&led_dat->cdev);
301} 305}
302 306
@@ -306,7 +310,6 @@ create_netxbig_led(struct platform_device *pdev,
306 const struct netxbig_led *template) 310 const struct netxbig_led *template)
307{ 311{
308 struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); 312 struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
309 int ret;
310 313
311 spin_lock_init(&led_dat->lock); 314 spin_lock_init(&led_dat->lock);
312 led_dat->gpio_ext = pdata->gpio_ext; 315 led_dat->gpio_ext = pdata->gpio_ext;
@@ -327,6 +330,12 @@ create_netxbig_led(struct platform_device *pdev,
327 led_dat->sata = 0; 330 led_dat->sata = 0;
328 led_dat->cdev.brightness = LED_OFF; 331 led_dat->cdev.brightness = LED_OFF;
329 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 332 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
333 /*
334 * If available, expose the SATA activity blink capability through
335 * a "sata" sysfs attribute.
336 */
337 if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE)
338 led_dat->cdev.groups = netxbig_led_groups;
330 led_dat->mode_addr = template->mode_addr; 339 led_dat->mode_addr = template->mode_addr;
331 led_dat->mode_val = template->mode_val; 340 led_dat->mode_val = template->mode_val;
332 led_dat->bright_addr = template->bright_addr; 341 led_dat->bright_addr = template->bright_addr;
@@ -334,21 +343,7 @@ create_netxbig_led(struct platform_device *pdev,
334 led_dat->timer = pdata->timer; 343 led_dat->timer = pdata->timer;
335 led_dat->num_timer = pdata->num_timer; 344 led_dat->num_timer = pdata->num_timer;
336 345
337 ret = led_classdev_register(&pdev->dev, &led_dat->cdev); 346 return led_classdev_register(&pdev->dev, &led_dat->cdev);
338 if (ret < 0)
339 return ret;
340
341 /*
342 * If available, expose the SATA activity blink capability through
343 * a "sata" sysfs attribute.
344 */
345 if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) {
346 ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
347 if (ret)
348 led_classdev_unregister(&led_dat->cdev);
349 }
350
351 return ret;
352} 347}
353 348
354static int netxbig_led_probe(struct platform_device *pdev) 349static int netxbig_led_probe(struct platform_device *pdev)
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index efa625883c83..231993d1fe21 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -185,6 +185,12 @@ static ssize_t ns2_led_sata_show(struct device *dev,
185 185
186static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store); 186static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store);
187 187
188static struct attribute *ns2_led_attrs[] = {
189 &dev_attr_sata.attr,
190 NULL
191};
192ATTRIBUTE_GROUPS(ns2_led);
193
188static int 194static int
189create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, 195create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
190 const struct ns2_led *template) 196 const struct ns2_led *template)
@@ -219,6 +225,7 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
219 led_dat->cdev.blink_set = NULL; 225 led_dat->cdev.blink_set = NULL;
220 led_dat->cdev.brightness_set = ns2_led_set; 226 led_dat->cdev.brightness_set = ns2_led_set;
221 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 227 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
228 led_dat->cdev.groups = ns2_led_groups;
222 led_dat->cmd = template->cmd; 229 led_dat->cmd = template->cmd;
223 led_dat->slow = template->slow; 230 led_dat->slow = template->slow;
224 231
@@ -235,20 +242,11 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
235 if (ret < 0) 242 if (ret < 0)
236 return ret; 243 return ret;
237 244
238 ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata);
239 if (ret < 0)
240 goto err_free_cdev;
241
242 return 0; 245 return 0;
243
244err_free_cdev:
245 led_classdev_unregister(&led_dat->cdev);
246 return ret;
247} 246}
248 247
249static void delete_ns2_led(struct ns2_led_data *led_dat) 248static void delete_ns2_led(struct ns2_led_data *led_dat)
250{ 249{
251 device_remove_file(led_dat->cdev.dev, &dev_attr_sata);
252 led_classdev_unregister(&led_dat->cdev); 250 led_classdev_unregister(&led_dat->cdev);
253} 251}
254 252
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index 82589c0a5689..f110b4c456ba 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -12,7 +12,7 @@
12 * directory of this archive for more details. 12 * directory of this archive for more details.
13 * 13 *
14 * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) 14 * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
15 * LED driver for the PCA9634 I2C LED driver (7-bit slave address set by hw.) 15 * LED driver for the PCA9634/5 I2C LED driver (7-bit slave address set by hw.)
16 * 16 *
17 * Note that hardware blinking violates the leds infrastructure driver 17 * Note that hardware blinking violates the leds infrastructure driver
18 * interface since the hardware only supports blinking all LEDs with the 18 * interface since the hardware only supports blinking all LEDs with the
@@ -52,6 +52,7 @@
52enum pca963x_type { 52enum pca963x_type {
53 pca9633, 53 pca9633,
54 pca9634, 54 pca9634,
55 pca9635,
55}; 56};
56 57
57struct pca963x_chipdef { 58struct pca963x_chipdef {
@@ -74,6 +75,12 @@ static struct pca963x_chipdef pca963x_chipdefs[] = {
74 .ledout_base = 0xc, 75 .ledout_base = 0xc,
75 .n_leds = 8, 76 .n_leds = 8,
76 }, 77 },
78 [pca9635] = {
79 .grppwm = 0x12,
80 .grpfreq = 0x13,
81 .ledout_base = 0x14,
82 .n_leds = 16,
83 },
77}; 84};
78 85
79/* Total blink period in milliseconds */ 86/* Total blink period in milliseconds */
@@ -84,6 +91,7 @@ static const struct i2c_device_id pca963x_id[] = {
84 { "pca9632", pca9633 }, 91 { "pca9632", pca9633 },
85 { "pca9633", pca9633 }, 92 { "pca9633", pca9633 },
86 { "pca9634", pca9634 }, 93 { "pca9634", pca9634 },
94 { "pca9635", pca9635 },
87 { } 95 { }
88}; 96};
89MODULE_DEVICE_TABLE(i2c, pca963x_id); 97MODULE_DEVICE_TABLE(i2c, pca963x_id);
@@ -107,7 +115,7 @@ struct pca963x_led {
107 struct work_struct work; 115 struct work_struct work;
108 enum led_brightness brightness; 116 enum led_brightness brightness;
109 struct led_classdev led_cdev; 117 struct led_classdev led_cdev;
110 int led_num; /* 0 .. 7 potentially */ 118 int led_num; /* 0 .. 15 potentially */
111 enum pca963x_cmd cmd; 119 enum pca963x_cmd cmd;
112 char name[32]; 120 char name[32];
113 u8 gdc; 121 u8 gdc;
@@ -321,6 +329,7 @@ static const struct of_device_id of_pca963x_match[] = {
321 { .compatible = "nxp,pca9632", }, 329 { .compatible = "nxp,pca9632", },
322 { .compatible = "nxp,pca9633", }, 330 { .compatible = "nxp,pca9633", },
323 { .compatible = "nxp,pca9634", }, 331 { .compatible = "nxp,pca9634", },
332 { .compatible = "nxp,pca9635", },
324 {}, 333 {},
325}; 334};
326#else 335#else
@@ -375,9 +384,8 @@ static int pca963x_probe(struct i2c_client *client,
375 pca963x_chip->leds = pca963x; 384 pca963x_chip->leds = pca963x;
376 385
377 /* Turn off LEDs by default*/ 386 /* Turn off LEDs by default*/
378 i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00); 387 for (i = 0; i < chip->n_leds / 4; i++)
379 if (chip->n_leds > 4) 388 i2c_smbus_write_byte_data(client, chip->ledout_base + i, 0x00);
380 i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00);
381 389
382 for (i = 0; i < chip->n_leds; i++) { 390 for (i = 0; i < chip->n_leds; i++) {
383 pca963x[i].led_num = i; 391 pca963x[i].led_num = i;
@@ -415,9 +423,13 @@ static int pca963x_probe(struct i2c_client *client,
415 /* Disable LED all-call address and set normal mode */ 423 /* Disable LED all-call address and set normal mode */
416 i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00); 424 i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00);
417 425
418 /* Configure output: open-drain or totem pole (push-pull) */ 426 if (pdata) {
419 if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN) 427 /* Configure output: open-drain or totem pole (push-pull) */
420 i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01); 428 if (pdata->outdrv == PCA963X_OPEN_DRAIN)
429 i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01);
430 else
431 i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x05);
432 }
421 433
422 return 0; 434 return 0;
423 435
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
index 2eb3ef62962b..046cb7008745 100644
--- a/drivers/leds/leds-ss4200.c
+++ b/drivers/leds/leds-ss4200.c
@@ -469,6 +469,12 @@ static ssize_t nas_led_blink_store(struct device *dev,
469 469
470static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store); 470static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store);
471 471
472static struct attribute *nasgpio_led_attrs[] = {
473 &dev_attr_blink.attr,
474 NULL
475};
476ATTRIBUTE_GROUPS(nasgpio_led);
477
472static int register_nasgpio_led(int led_nr) 478static int register_nasgpio_led(int led_nr)
473{ 479{
474 int ret; 480 int ret;
@@ -481,20 +487,18 @@ static int register_nasgpio_led(int led_nr)
481 led->brightness = LED_FULL; 487 led->brightness = LED_FULL;
482 led->brightness_set = nasgpio_led_set_brightness; 488 led->brightness_set = nasgpio_led_set_brightness;
483 led->blink_set = nasgpio_led_set_blink; 489 led->blink_set = nasgpio_led_set_blink;
490 led->groups = nasgpio_led_groups;
484 ret = led_classdev_register(&nas_gpio_pci_dev->dev, led); 491 ret = led_classdev_register(&nas_gpio_pci_dev->dev, led);
485 if (ret) 492 if (ret)
486 return ret; 493 return ret;
487 ret = device_create_file(led->dev, &dev_attr_blink); 494
488 if (ret) 495 return 0;
489 led_classdev_unregister(led);
490 return ret;
491} 496}
492 497
493static void unregister_nasgpio_led(int led_nr) 498static void unregister_nasgpio_led(int led_nr)
494{ 499{
495 struct led_classdev *led = get_classdev_for_led_nr(led_nr); 500 struct led_classdev *led = get_classdev_for_led_nr(led_nr);
496 led_classdev_unregister(led); 501 led_classdev_unregister(led);
497 device_remove_file(led->dev, &dev_attr_blink);
498} 502}
499/* 503/*
500 * module load/initialization 504 * module load/initialization
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index e72c974142d0..1b71e0701002 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -219,6 +219,12 @@ static ssize_t wm831x_status_src_store(struct device *dev,
219 219
220static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store); 220static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store);
221 221
222static struct attribute *wm831x_status_attrs[] = {
223 &dev_attr_src.attr,
224 NULL
225};
226ATTRIBUTE_GROUPS(wm831x_status);
227
222static int wm831x_status_probe(struct platform_device *pdev) 228static int wm831x_status_probe(struct platform_device *pdev)
223{ 229{
224 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 230 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -232,8 +238,7 @@ static int wm831x_status_probe(struct platform_device *pdev)
232 res = platform_get_resource(pdev, IORESOURCE_REG, 0); 238 res = platform_get_resource(pdev, IORESOURCE_REG, 0);
233 if (res == NULL) { 239 if (res == NULL) {
234 dev_err(&pdev->dev, "No register resource\n"); 240 dev_err(&pdev->dev, "No register resource\n");
235 ret = -EINVAL; 241 return -EINVAL;
236 goto err;
237 } 242 }
238 243
239 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status), 244 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status),
@@ -284,31 +289,21 @@ static int wm831x_status_probe(struct platform_device *pdev)
284 drvdata->cdev.default_trigger = pdata.default_trigger; 289 drvdata->cdev.default_trigger = pdata.default_trigger;
285 drvdata->cdev.brightness_set = wm831x_status_set; 290 drvdata->cdev.brightness_set = wm831x_status_set;
286 drvdata->cdev.blink_set = wm831x_status_blink_set; 291 drvdata->cdev.blink_set = wm831x_status_blink_set;
292 drvdata->cdev.groups = wm831x_status_groups;
287 293
288 ret = led_classdev_register(wm831x->dev, &drvdata->cdev); 294 ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
289 if (ret < 0) { 295 if (ret < 0) {
290 dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); 296 dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
291 goto err_led; 297 return ret;
292 } 298 }
293 299
294 ret = device_create_file(drvdata->cdev.dev, &dev_attr_src);
295 if (ret != 0)
296 dev_err(&pdev->dev,
297 "No source control for LED: %d\n", ret);
298
299 return 0; 300 return 0;
300
301err_led:
302 led_classdev_unregister(&drvdata->cdev);
303err:
304 return ret;
305} 301}
306 302
307static int wm831x_status_remove(struct platform_device *pdev) 303static int wm831x_status_remove(struct platform_device *pdev)
308{ 304{
309 struct wm831x_status *drvdata = platform_get_drvdata(pdev); 305 struct wm831x_status *drvdata = platform_get_drvdata(pdev);
310 306
311 device_remove_file(drvdata->cdev.dev, &dev_attr_src);
312 led_classdev_unregister(&drvdata->cdev); 307 led_classdev_unregister(&drvdata->cdev);
313 308
314 return 0; 309 return 0;