diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/Kconfig | 14 | ||||
-rw-r--r-- | drivers/hid/Makefile | 1 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-gt683r.c | 321 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 2 | ||||
-rw-r--r-- | drivers/input/keyboard/lm8323.c | 22 | ||||
-rw-r--r-- | drivers/leds/Kconfig | 7 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/led-class.c | 19 | ||||
-rw-r--r-- | drivers/leds/led-core.c | 11 | ||||
-rw-r--r-- | drivers/leds/leds-ipaq-micro.c | 141 | ||||
-rw-r--r-- | drivers/leds/leds-lm3530.c | 20 | ||||
-rw-r--r-- | drivers/leds/leds-lm3533.c | 20 | ||||
-rw-r--r-- | drivers/leds/leds-lm355x.c | 21 | ||||
-rw-r--r-- | drivers/leds/leds-lm3642.c | 30 | ||||
-rw-r--r-- | drivers/leds/leds-lp55xx-common.c | 20 | ||||
-rw-r--r-- | drivers/leds/leds-max8997.c | 16 | ||||
-rw-r--r-- | drivers/leds/leds-netxbig.c | 31 | ||||
-rw-r--r-- | drivers/leds/leds-ns2.c | 16 | ||||
-rw-r--r-- | drivers/leds/leds-pca963x.c | 28 | ||||
-rw-r--r-- | drivers/leds/leds-ss4200.c | 14 | ||||
-rw-r--r-- | drivers/leds/leds-wm831x-status.c | 23 |
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 | ||
264 | config 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 | |||
264 | config HID_HUION | 278 | config 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 | |||
48 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o | 48 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o |
49 | obj-$(CONFIG_HID_ELO) += hid-elo.o | 49 | obj-$(CONFIG_HID_ELO) += hid-elo.o |
50 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 50 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
51 | obj-$(CONFIG_HID_GT683R) += hid-gt683r.o | ||
51 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 52 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
52 | obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o | 53 | obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o |
53 | obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o | 54 | obj-$(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 | */ | ||
34 | enum 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 | |||
41 | enum gt683r_panels { | ||
42 | GT683R_LED_BACK = 0, | ||
43 | GT683R_LED_SIDE = 1, | ||
44 | GT683R_LED_FRONT = 2, | ||
45 | GT683R_LED_COUNT, | ||
46 | }; | ||
47 | |||
48 | static const char * const gt683r_panel_names[] = { | ||
49 | "back", | ||
50 | "side", | ||
51 | "front", | ||
52 | }; | ||
53 | |||
54 | struct 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 | |||
63 | static 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 | |||
68 | static 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 | |||
87 | static 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 | |||
106 | static 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 | |||
134 | static 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 | |||
151 | static 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 | |||
170 | static 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 | |||
190 | static 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); | ||
213 | fail: | ||
214 | mutex_unlock(&led->lock); | ||
215 | } | ||
216 | |||
217 | static DEVICE_ATTR_RW(mode); | ||
218 | |||
219 | static struct attribute *gt683r_led_attrs[] = { | ||
220 | &dev_attr_mode.attr, | ||
221 | NULL | ||
222 | }; | ||
223 | |||
224 | static const struct attribute_group gt683r_led_group = { | ||
225 | .name = "gt683r", | ||
226 | .attrs = gt683r_led_attrs, | ||
227 | }; | ||
228 | |||
229 | static const struct attribute_group *gt683r_led_groups[] = { | ||
230 | >683r_led_group, | ||
231 | NULL | ||
232 | }; | ||
233 | |||
234 | static 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 | |||
292 | fail: | ||
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 | |||
299 | static 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 | |||
310 | static 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 | |||
317 | module_hid_driver(gt683r_led_driver); | ||
318 | |||
319 | MODULE_AUTHOR("Janne Kanniainen"); | ||
320 | MODULE_DESCRIPTION("MSI GT683R led driver"); | ||
321 | MODULE_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 | } |
559 | static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time); | 559 | static DEVICE_ATTR(time, 0644, lm8323_pwm_show_time, lm8323_pwm_store_time); |
560 | 560 | ||
561 | static struct attribute *lm8323_pwm_attrs[] = { | ||
562 | &dev_attr_time.attr, | ||
563 | NULL | ||
564 | }; | ||
565 | ATTRIBUTE_GROUPS(lm8323_pwm); | ||
566 | |||
561 | static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, | 567 | static 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); |
754 | fail2: | 755 | fail2: |
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 | } | ||
761 | fail1: | 759 | fail1: |
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 | ||
146 | config 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 | |||
146 | config LEDS_HP6XX | 153 | config 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 | |||
31 | obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o | 31 | obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o |
32 | obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o | 32 | obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o |
33 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | 33 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o |
34 | obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o | ||
34 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | 35 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o |
35 | obj-$(CONFIG_LEDS_OT200) += leds-ot200.o | 36 | obj-$(CONFIG_LEDS_OT200) += leds-ot200.o |
36 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 37 | obj-$(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 | ||
24 | static struct class *leds_class; | 24 | static struct class *leds_class; |
@@ -97,9 +97,10 @@ static const struct attribute_group *led_groups[] = { | |||
97 | NULL, | 97 | NULL, |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static void led_timer_function(unsigned long data) | 100 | static 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 | ||
149 | static void set_brightness_delayed(struct work_struct *ws) | 151 | static 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 | */ |
211 | int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) | 213 | int 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 | ||
21 | DECLARE_RWSEM(leds_list_lock); | 22 | DECLARE_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 | ||
108 | void led_stop_software_blink(struct led_classdev *led_cdev) | 109 | void 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); | |||
116 | void led_set_brightness(struct led_classdev *led_cdev, | 117 | void 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 | |||
23 | static 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 | |||
59 | static 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 | |||
103 | static 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 | |||
110 | static int micro_leds_probe(struct platform_device *pdev) | ||
111 | { | ||
112 | int ret; | ||
113 | |||
114 | ret = led_classdev_register(&pdev->dev, µ_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 | |||
124 | static int micro_leds_remove(struct platform_device *pdev) | ||
125 | { | ||
126 | led_classdev_unregister(µ_led); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static 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 | }; | ||
137 | module_platform_driver(micro_leds_device_driver); | ||
138 | |||
139 | MODULE_LICENSE("GPL"); | ||
140 | MODULE_DESCRIPTION("driver for iPAQ Atmel micro leds"); | ||
141 | MODULE_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 | } |
401 | static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set); | 401 | static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set); |
402 | 402 | ||
403 | static struct attribute *lm3530_attrs[] = { | ||
404 | &dev_attr_mode.attr, | ||
405 | NULL | ||
406 | }; | ||
407 | ATTRIBUTE_GROUPS(lm3530); | ||
408 | |||
403 | static int lm3530_probe(struct i2c_client *client, | 409 | static 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 | |||
473 | err_create_file: | ||
474 | led_classdev_unregister(&drvdata->led_dev); | ||
475 | return err; | ||
476 | } | 472 | } |
477 | 473 | ||
478 | static int lm3530_remove(struct i2c_client *client) | 474 | static 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 | ||
648 | static const struct attribute_group *lm3533_led_attribute_groups[] = { | ||
649 | &lm3533_led_attribute_group, | ||
650 | NULL | ||
651 | }; | ||
652 | |||
648 | static int lm3533_led_setup(struct lm3533_led *led, | 653 | static 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 | ||
735 | err_sysfs_remove: | ||
736 | sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); | ||
737 | err_unregister: | 734 | err_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 | ||
414 | static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); | 414 | static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); |
415 | 415 | ||
416 | static struct attribute *lm355x_indicator_attrs[] = { | ||
417 | &dev_attr_pattern.attr, | ||
418 | NULL | ||
419 | }; | ||
420 | ATTRIBUTE_GROUPS(lm355x_indicator); | ||
421 | |||
416 | static const struct regmap_config lm355x_regmap = { | 422 | static 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 | ||
521 | err_create_pattern_file: | ||
522 | led_classdev_unregister(&chip->cdev_indicator); | ||
523 | err_create_indicator_file: | 522 | err_create_indicator_file: |
524 | led_classdev_unregister(&chip->cdev_torch); | 523 | led_classdev_unregister(&chip->cdev_torch); |
525 | err_create_torch_file: | 524 | err_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 | ||
316 | static struct attribute *lm3642_flash_attrs[] = { | ||
317 | &dev_attr_strobe_pin.attr, | ||
318 | NULL | ||
319 | }; | ||
320 | ATTRIBUTE_GROUPS(lm3642_flash); | ||
321 | |||
322 | static struct attribute *lm3642_torch_attrs[] = { | ||
323 | &dev_attr_torch_pin.attr, | ||
324 | NULL | ||
325 | }; | ||
326 | ATTRIBUTE_GROUPS(lm3642_torch); | ||
327 | |||
316 | static int lm3642_probe(struct i2c_client *client, | 328 | static 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 | ||
413 | err_create_indicator_file: | 417 | err_create_indicator_file: |
414 | device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin); | ||
415 | err_create_torch_pin_file: | ||
416 | led_classdev_unregister(&chip->cdev_torch); | 418 | led_classdev_unregister(&chip->cdev_torch); |
417 | err_create_torch_file: | 419 | err_create_torch_file: |
418 | device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); | ||
419 | err_create_flash_pin_file: | ||
420 | led_classdev_unregister(&chip->cdev_flash); | 420 | led_classdev_unregister(&chip->cdev_flash); |
421 | err_out: | 421 | err_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); |
128 | static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL); | 128 | static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL); |
129 | 129 | ||
130 | static struct attribute *lp55xx_led_attributes[] = { | 130 | static 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 | 135 | ATTRIBUTE_GROUPS(lp55xx_led); | |
136 | static struct attribute_group lp55xx_led_attr_group = { | ||
137 | .attrs = lp55xx_led_attributes | ||
138 | }; | ||
139 | 136 | ||
140 | static void lp55xx_set_brightness(struct led_classdev *cdev, | 137 | static 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 | ||
230 | static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode); | 230 | static DEVICE_ATTR(mode, 0644, max8997_led_show_mode, max8997_led_store_mode); |
231 | 231 | ||
232 | static struct attribute *max8997_attrs[] = { | ||
233 | &dev_attr_mode.attr, | ||
234 | NULL | ||
235 | }; | ||
236 | ATTRIBUTE_GROUPS(max8997); | ||
237 | |||
232 | static int max8997_led_probe(struct platform_device *pdev) | 238 | static 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 | ||
294 | static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); | 294 | static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); |
295 | 295 | ||
296 | static struct attribute *netxbig_led_attrs[] = { | ||
297 | &dev_attr_sata.attr, | ||
298 | NULL | ||
299 | }; | ||
300 | ATTRIBUTE_GROUPS(netxbig_led); | ||
301 | |||
296 | static void delete_netxbig_led(struct netxbig_led_data *led_dat) | 302 | static 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 | ||
354 | static int netxbig_led_probe(struct platform_device *pdev) | 349 | static 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 | ||
186 | static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store); | 186 | static DEVICE_ATTR(sata, 0644, ns2_led_sata_show, ns2_led_sata_store); |
187 | 187 | ||
188 | static struct attribute *ns2_led_attrs[] = { | ||
189 | &dev_attr_sata.attr, | ||
190 | NULL | ||
191 | }; | ||
192 | ATTRIBUTE_GROUPS(ns2_led); | ||
193 | |||
188 | static int | 194 | static int |
189 | create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, | 195 | create_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 | |||
244 | err_free_cdev: | ||
245 | led_classdev_unregister(&led_dat->cdev); | ||
246 | return ret; | ||
247 | } | 246 | } |
248 | 247 | ||
249 | static void delete_ns2_led(struct ns2_led_data *led_dat) | 248 | static 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 @@ | |||
52 | enum pca963x_type { | 52 | enum pca963x_type { |
53 | pca9633, | 53 | pca9633, |
54 | pca9634, | 54 | pca9634, |
55 | pca9635, | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | struct pca963x_chipdef { | 58 | struct 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 | }; |
89 | MODULE_DEVICE_TABLE(i2c, pca963x_id); | 97 | MODULE_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 | ||
470 | static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store); | 470 | static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store); |
471 | 471 | ||
472 | static struct attribute *nasgpio_led_attrs[] = { | ||
473 | &dev_attr_blink.attr, | ||
474 | NULL | ||
475 | }; | ||
476 | ATTRIBUTE_GROUPS(nasgpio_led); | ||
477 | |||
472 | static int register_nasgpio_led(int led_nr) | 478 | static 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 | ||
493 | static void unregister_nasgpio_led(int led_nr) | 498 | static 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 | ||
220 | static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store); | 220 | static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store); |
221 | 221 | ||
222 | static struct attribute *wm831x_status_attrs[] = { | ||
223 | &dev_attr_src.attr, | ||
224 | NULL | ||
225 | }; | ||
226 | ATTRIBUTE_GROUPS(wm831x_status); | ||
227 | |||
222 | static int wm831x_status_probe(struct platform_device *pdev) | 228 | static 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 | |||
301 | err_led: | ||
302 | led_classdev_unregister(&drvdata->cdev); | ||
303 | err: | ||
304 | return ret; | ||
305 | } | 301 | } |
306 | 302 | ||
307 | static int wm831x_status_remove(struct platform_device *pdev) | 303 | static 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; |