Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds

Pull LED updates from Bryan Wu:
"This cycle we got:
- a fix of attribute-creation race for the whole leds subsystem
- new drivers (HID:GT683R, leds-ipaq-micro)
- other fixing and clean up"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds: (23 commits)
leds: ipaq-micro: fix sparse non static symbol warning
leds: add driver for the iPAQ micro
Documentation: dts: tcs6507: Fix wrong statement about #gpio-cells
leds: convert blink timer to workqueue
leds:pca963x: Update for PCA9635 and correct statement about MODE2 OUTDRV default
leds:pca963x: Always initialize MODE2 register
leds:pca963x: Add support for PCA9635 LED driver chip
HID: gt683r: move mode attribute to led-class devices
HID: gt683r: fix race condition
HID: add support for MSI GT683R led panels
leds: lp55xx-common: fix attribute-creation race
leds: lp55xx-common: fix sysfs entry leak
input: lm8323: fix attribute-creation race
leds: wm831x-status: fix attribute-creation race
leds: ss4200: fix attribute-creation race
leds: ns2: fix attribute-creation race
leds: netxbig: fix attribute-creation race
leds: max8997: fix attribute-creation race
leds: lm3642: fix attribute-creation race
leds: lm355x: fix attribute-creation race
...

+644 -169
+16
Documentation/ABI/testing/sysfs-class-leds-gt683r
··· 1 + What: /sys/class/leds/<led>/gt683r/mode 2 + Date: Jun 2014 3 + KernelVersion: 3.17 4 + Contact: Janne Kanniainen <janne.kanniainen@gmail.com> 5 + Description: 6 + Set the mode of LEDs. You should notice that changing the mode 7 + of one LED will update the mode of its two sibling devices as 8 + well. 9 + 10 + 0 - normal 11 + 1 - audio 12 + 2 - breathing 13 + 14 + Normal: LEDs are fully on when enabled 15 + Audio: LEDs brightness depends on sound level 16 + Breathing: LEDs brightness varies at human breathing rate
+5 -4
Documentation/devicetree/bindings/leds/pca963x.txt
··· 1 1 LEDs connected to pca9632, pca9633 or pca9634 2 2 3 3 Required properties: 4 - - compatible : should be : "nxp,pca9632", "nxp,pca9633" or "nxp,pca9634" 4 + - compatible : should be : "nxp,pca9632", "nxp,pca9633", "nxp,pca9634" or "nxp,pca9635" 5 5 6 6 Optional properties: 7 - - nxp,totem-pole : use totem pole (push-pull) instead of default open-drain 7 + - nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults 8 + to open-drain, newer chips to totem pole) 8 9 - nxp,hw-blink : use hardware blinking instead of software blinking 9 10 10 11 Each led is represented as a sub-node of the nxp,pca963x device. 11 12 12 13 LED sub-node properties: 13 14 - label : (optional) see Documentation/devicetree/bindings/leds/common.txt 14 - - reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633 15 - or 0 to 7 in pca9634) 15 + - reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633, 16 + 0 to 7 in pca9634, or 0 to 15 in pca9635) 16 17 - linux,default-trigger : (optional) 17 18 see Documentation/devicetree/bindings/leds/common.txt 18 19
+1 -1
Documentation/devicetree/bindings/leds/tca6507.txt
··· 8 8 9 9 Optional properties: 10 10 - gpio-controller: allows lines to be used as output-only GPIOs. 11 - - #gpio-cells: if present, must be 0. 11 + - #gpio-cells: if present, must not be 0. 12 12 13 13 Each led is represented as a sub-node of the ti,tca6507 device. 14 14
+14
drivers/hid/Kconfig
··· 261 261 Say Y here if you have a Holtek On Line Grip based game controller 262 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 278 config HID_HUION 265 279 tristate "Huion tablets" 266 280 depends on USB_HID
+1
drivers/hid/Makefile
··· 48 48 obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 49 49 obj-$(CONFIG_HID_ELO) += hid-elo.o 50 50 obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 51 + obj-$(CONFIG_HID_GT683R) += hid-gt683r.o 51 52 obj-$(CONFIG_HID_GYRATION) += hid-gyration.o 52 53 obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o 53 54 obj-$(CONFIG_HID_HOLTEK) += hid-holtek-mouse.o
+1
drivers/hid/hid-core.c
··· 1849 1849 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, 1850 1850 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, 1851 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 1853 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, 1853 1854 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) }, 1854 1855 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
+321
drivers/hid/hid-gt683r.c
··· 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 + &gt683r_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");
+1 -1
drivers/hid/hid-ids.h
··· 650 650 #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 651 651 652 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 655 #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 656 656 #define USB_DEVICE_ID_N_S_HARMONY 0xc359
+1 -1
drivers/hid/usbhid/hid-quirks.c
··· 74 74 { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, 75 75 { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, 76 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 78 { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, 79 79 { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, 80 80 { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET },
+9 -13
drivers/input/keyboard/lm8323.c
··· 558 558 } 559 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 567 static int init_pwm(struct lm8323_chip *lm, int id, struct device *dev, 562 568 const char *name) 563 569 { ··· 586 580 if (name) { 587 581 pwm->cdev.name = name; 588 582 pwm->cdev.brightness_set = lm8323_pwm_set_brightness; 583 + pwm->cdev.groups = lm8323_pwm_groups; 589 584 if (led_classdev_register(dev, &pwm->cdev) < 0) { 590 585 dev_err(dev, "couldn't register PWM %d\n", id); 591 - return -1; 592 - } 593 - if (device_create_file(pwm->cdev.dev, 594 - &dev_attr_time) < 0) { 595 - dev_err(dev, "couldn't register time attribute\n"); 596 - led_classdev_unregister(&pwm->cdev); 597 586 return -1; 598 587 } 599 588 pwm->enabled = true; ··· 754 753 device_remove_file(&client->dev, &dev_attr_disable_kp); 755 754 fail2: 756 755 while (--pwm >= 0) 757 - if (lm->pwm[pwm].enabled) { 758 - device_remove_file(lm->pwm[pwm].cdev.dev, 759 - &dev_attr_time); 756 + if (lm->pwm[pwm].enabled) 760 757 led_classdev_unregister(&lm->pwm[pwm].cdev); 761 - } 762 758 fail1: 763 759 input_free_device(idev); 764 760 kfree(lm); ··· 775 777 device_remove_file(&lm->client->dev, &dev_attr_disable_kp); 776 778 777 779 for (i = 0; i < 3; i++) 778 - if (lm->pwm[i].enabled) { 779 - device_remove_file(lm->pwm[i].cdev.dev, &dev_attr_time); 780 + if (lm->pwm[i].enabled) 780 781 led_classdev_unregister(&lm->pwm[i].cdev); 781 - } 782 782 783 783 kfree(lm); 784 784
+7
drivers/leds/Kconfig
··· 143 143 This option enables support for the Left, Middle, and Right 144 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 153 config LEDS_HP6XX 147 154 tristate "LED Support for the HP Jornada 6xx" 148 155 depends on LEDS_CLASS
+1
drivers/leds/Makefile
··· 31 31 obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o 32 32 obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o 33 33 obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 34 + obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o 34 35 obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 35 36 obj-$(CONFIG_LEDS_OT200) += leds-ot200.o 36 37 obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
+10 -9
drivers/leds/led-class.c
··· 15 15 #include <linux/list.h> 16 16 #include <linux/spinlock.h> 17 17 #include <linux/device.h> 18 - #include <linux/timer.h> 19 18 #include <linux/err.h> 20 19 #include <linux/ctype.h> 21 20 #include <linux/leds.h> 21 + #include <linux/workqueue.h> 22 22 #include "leds.h" 23 23 24 24 static struct class *leds_class; ··· 97 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 104 unsigned long brightness; 104 105 unsigned long delay; 105 106 ··· 144 143 } 145 144 } 146 145 147 - mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); 146 + queue_delayed_work(system_wq, &led_cdev->blink_work, 147 + msecs_to_jiffies(delay)); 148 148 } 149 149 150 150 static void set_brightness_delayed(struct work_struct *ws) ··· 212 210 */ 213 211 int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) 214 212 { 215 - led_cdev->dev = device_create(leds_class, parent, 0, led_cdev, 216 - "%s", led_cdev->name); 213 + led_cdev->dev = device_create_with_groups(leds_class, parent, 0, 214 + led_cdev, led_cdev->groups, 215 + "%s", led_cdev->name); 217 216 if (IS_ERR(led_cdev->dev)) 218 217 return PTR_ERR(led_cdev->dev); 219 218 ··· 233 230 234 231 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); 235 232 236 - init_timer(&led_cdev->blink_timer); 237 - led_cdev->blink_timer.function = led_timer_function; 238 - led_cdev->blink_timer.data = (unsigned long)led_cdev; 233 + INIT_DELAYED_WORK(&led_cdev->blink_work, led_work_function); 239 234 240 235 #ifdef CONFIG_LEDS_TRIGGERS 241 236 led_trigger_set_default(led_cdev);
+6 -5
drivers/leds/led-core.c
··· 16 16 #include <linux/module.h> 17 17 #include <linux/rwsem.h> 18 18 #include <linux/leds.h> 19 + #include <linux/workqueue.h> 19 20 #include "leds.h" 20 21 21 22 DECLARE_RWSEM(leds_list_lock); ··· 52 51 return; 53 52 } 54 53 55 - mod_timer(&led_cdev->blink_timer, jiffies + 1); 54 + queue_delayed_work(system_wq, &led_cdev->blink_work, 1); 56 55 } 57 56 58 57 ··· 76 75 unsigned long *delay_on, 77 76 unsigned long *delay_off) 78 77 { 79 - del_timer_sync(&led_cdev->blink_timer); 78 + cancel_delayed_work_sync(&led_cdev->blink_work); 80 79 81 80 led_cdev->flags &= ~LED_BLINK_ONESHOT; 82 81 led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; ··· 91 90 int invert) 92 91 { 93 92 if ((led_cdev->flags & LED_BLINK_ONESHOT) && 94 - timer_pending(&led_cdev->blink_timer)) 93 + delayed_work_pending(&led_cdev->blink_work)) 95 94 return; 96 95 97 96 led_cdev->flags |= LED_BLINK_ONESHOT; ··· 108 107 109 108 void led_stop_software_blink(struct led_classdev *led_cdev) 110 109 { 111 - del_timer_sync(&led_cdev->blink_timer); 110 + cancel_delayed_work_sync(&led_cdev->blink_work); 112 111 led_cdev->blink_delay_on = 0; 113 112 led_cdev->blink_delay_off = 0; 114 113 } ··· 117 116 void led_set_brightness(struct led_classdev *led_cdev, 118 117 enum led_brightness brightness) 119 118 { 120 - /* delay brightness setting if need to stop soft-blink timer */ 119 + /* delay brightness setting if need to stop soft-blink work */ 121 120 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 122 121 led_cdev->delayed_set_value = brightness; 123 122 schedule_work(&led_cdev->set_brightness_work);
+141
drivers/leds/leds-ipaq-micro.c
··· 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, &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 + 124 + static int micro_leds_remove(struct platform_device *pdev) 125 + { 126 + led_classdev_unregister(&micro_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");
+7 -13
drivers/leds/leds-lm3530.c
··· 400 400 } 401 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 409 static int lm3530_probe(struct i2c_client *client, 404 410 const struct i2c_device_id *id) 405 411 { ··· 442 436 drvdata->led_dev.name = LM3530_LED_DEV; 443 437 drvdata->led_dev.brightness_set = lm3530_brightness_set; 444 438 drvdata->led_dev.max_brightness = MAX_BRIGHTNESS; 439 + drvdata->led_dev.groups = lm3530_groups; 445 440 446 441 i2c_set_clientdata(client, drvdata); 447 442 ··· 468 461 return err; 469 462 } 470 463 471 - err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode); 472 - if (err < 0) { 473 - dev_err(&client->dev, "File device creation failed: %d\n", err); 474 - err = -ENODEV; 475 - goto err_create_file; 476 - } 477 - 478 464 return 0; 479 - 480 - err_create_file: 481 - led_classdev_unregister(&drvdata->led_dev); 482 - return err; 483 465 } 484 466 485 467 static int lm3530_remove(struct i2c_client *client) 486 468 { 487 469 struct lm3530_data *drvdata = i2c_get_clientdata(client); 488 - 489 - device_remove_file(drvdata->led_dev.dev, &dev_attr_mode); 490 470 491 471 lm3530_led_disable(drvdata); 492 472 led_classdev_unregister(&drvdata->led_dev);
+8 -12
drivers/leds/leds-lm3533.c
··· 645 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 653 static int lm3533_led_setup(struct lm3533_led *led, 649 654 struct lm3533_led_platform_data *pdata) 650 655 { ··· 697 692 led->cdev.brightness_get = lm3533_led_get; 698 693 led->cdev.blink_set = lm3533_led_blink_set; 699 694 led->cdev.brightness = LED_OFF; 695 + led->cdev.groups = lm3533_led_attribute_groups, 700 696 led->id = pdev->id; 701 697 702 698 mutex_init(&led->mutex); ··· 721 715 722 716 led->cb.dev = led->cdev.dev; 723 717 724 - ret = sysfs_create_group(&led->cdev.dev->kobj, 725 - &lm3533_led_attribute_group); 726 - if (ret < 0) { 727 - dev_err(&pdev->dev, "failed to create sysfs attributes\n"); 728 - goto err_unregister; 729 - } 730 - 731 718 ret = lm3533_led_setup(led, pdata); 732 719 if (ret) 733 - goto err_sysfs_remove; 720 + goto err_unregister; 734 721 735 722 ret = lm3533_ctrlbank_enable(&led->cb); 736 723 if (ret) 737 - goto err_sysfs_remove; 724 + goto err_unregister; 738 725 739 726 return 0; 740 727 741 - err_sysfs_remove: 742 - sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); 743 728 err_unregister: 744 729 led_classdev_unregister(&led->cdev); 745 730 flush_work(&led->work); ··· 745 748 dev_dbg(&pdev->dev, "%s\n", __func__); 746 749 747 750 lm3533_ctrlbank_disable(&led->cb); 748 - sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group); 749 751 led_classdev_unregister(&led->cdev); 750 752 flush_work(&led->work); 751 753
+9 -12
drivers/leds/leds-lm355x.c
··· 413 413 414 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 422 static const struct regmap_config lm355x_regmap = { 417 423 .reg_bits = 8, 418 424 .val_bits = 8, ··· 507 501 else 508 502 chip->cdev_indicator.max_brightness = 8; 509 503 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set; 504 + /* indicator pattern control only for LM3556 */ 505 + if (id->driver_data == CHIP_LM3556) 506 + chip->cdev_indicator.groups = lm355x_indicator_groups; 510 507 err = led_classdev_register((struct device *) 511 508 &client->dev, &chip->cdev_indicator); 512 509 if (err < 0) 513 510 goto err_create_indicator_file; 514 - /* indicator pattern control only for LM3554 */ 515 - if (id->driver_data == CHIP_LM3556) { 516 - err = 517 - device_create_file(chip->cdev_indicator.dev, 518 - &dev_attr_pattern); 519 - if (err < 0) 520 - goto err_create_pattern_file; 521 - } 522 511 523 512 dev_info(&client->dev, "%s is initialized\n", 524 513 lm355x_name[id->driver_data]); 525 514 return 0; 526 515 527 - err_create_pattern_file: 528 - led_classdev_unregister(&chip->cdev_indicator); 529 516 err_create_indicator_file: 530 517 led_classdev_unregister(&chip->cdev_torch); 531 518 err_create_torch_file: ··· 533 534 struct lm355x_reg_data *preg = chip->regs; 534 535 535 536 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0); 536 - if (chip->type == CHIP_LM3556) 537 - device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern); 538 537 led_classdev_unregister(&chip->cdev_indicator); 539 538 flush_work(&chip->work_indicator); 540 539 led_classdev_unregister(&chip->cdev_torch);
+14 -16
drivers/leds/leds-lm3642.c
··· 313 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 328 static int lm3642_probe(struct i2c_client *client, 317 329 const struct i2c_device_id *id) 318 330 { ··· 376 364 chip->cdev_flash.max_brightness = 16; 377 365 chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set; 378 366 chip->cdev_flash.default_trigger = "flash"; 367 + chip->cdev_flash.groups = lm3642_flash_groups, 379 368 err = led_classdev_register((struct device *) 380 369 &client->dev, &chip->cdev_flash); 381 370 if (err < 0) { 382 371 dev_err(chip->dev, "failed to register flash\n"); 383 372 goto err_out; 384 - } 385 - err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); 386 - if (err < 0) { 387 - dev_err(chip->dev, "failed to create strobe-pin file\n"); 388 - goto err_create_flash_pin_file; 389 373 } 390 374 391 375 /* torch */ ··· 390 382 chip->cdev_torch.max_brightness = 8; 391 383 chip->cdev_torch.brightness_set = lm3642_torch_brightness_set; 392 384 chip->cdev_torch.default_trigger = "torch"; 385 + chip->cdev_torch.groups = lm3642_torch_groups, 393 386 err = led_classdev_register((struct device *) 394 387 &client->dev, &chip->cdev_torch); 395 388 if (err < 0) { 396 389 dev_err(chip->dev, "failed to register torch\n"); 397 390 goto err_create_torch_file; 398 - } 399 - err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin); 400 - if (err < 0) { 401 - dev_err(chip->dev, "failed to create torch-pin file\n"); 402 - goto err_create_torch_pin_file; 403 391 } 404 392 405 393 /* indicator */ ··· 415 411 return 0; 416 412 417 413 err_create_indicator_file: 418 - device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin); 419 - err_create_torch_pin_file: 420 414 led_classdev_unregister(&chip->cdev_torch); 421 415 err_create_torch_file: 422 - device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); 423 - err_create_flash_pin_file: 424 416 led_classdev_unregister(&chip->cdev_flash); 425 417 err_out: 426 418 return err; ··· 428 428 429 429 led_classdev_unregister(&chip->cdev_indicator); 430 430 flush_work(&chip->work_indicator); 431 - device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin); 432 431 led_classdev_unregister(&chip->cdev_torch); 433 432 flush_work(&chip->work_torch); 434 - device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); 435 433 led_classdev_unregister(&chip->cdev_flash); 436 434 flush_work(&chip->work_flash); 437 435 regmap_write(chip->regmap, REG_ENABLE, 0);
+3 -17
drivers/leds/leds-lp55xx-common.c
··· 127 127 lp55xx_store_current); 128 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 131 &dev_attr_led_current.attr, 132 132 &dev_attr_max_current.attr, 133 133 NULL, 134 134 }; 135 - 136 - static struct attribute_group lp55xx_led_attr_group = { 137 - .attrs = lp55xx_led_attributes 138 - }; 135 + ATTRIBUTE_GROUPS(lp55xx_led); 139 136 140 137 static void lp55xx_set_brightness(struct led_classdev *cdev, 141 138 enum led_brightness brightness) ··· 173 176 } 174 177 175 178 led->cdev.brightness_set = lp55xx_set_brightness; 179 + led->cdev.groups = lp55xx_led_groups; 176 180 177 181 if (pdata->led_config[chan].name) { 178 182 led->cdev.name = pdata->led_config[chan].name; ··· 183 185 led->cdev.name = name; 184 186 } 185 187 186 - /* 187 - * register led class device for each channel and 188 - * add device attributes 189 - */ 190 - 191 188 ret = led_classdev_register(dev, &led->cdev); 192 189 if (ret) { 193 190 dev_err(dev, "led register err: %d\n", ret); 194 - return ret; 195 - } 196 - 197 - ret = sysfs_create_group(&led->cdev.dev->kobj, &lp55xx_led_attr_group); 198 - if (ret) { 199 - dev_err(dev, "led sysfs err: %d\n", ret); 200 - led_classdev_unregister(&led->cdev); 201 191 return ret; 202 192 } 203 193
+7 -9
drivers/leds/leds-max8997.c
··· 229 229 230 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 238 static int max8997_led_probe(struct platform_device *pdev) 233 239 { 234 240 struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); ··· 259 253 led->cdev.brightness_set = max8997_led_brightness_set; 260 254 led->cdev.flags |= LED_CORE_SUSPENDRESUME; 261 255 led->cdev.brightness = 0; 256 + led->cdev.groups = max8997_groups; 262 257 led->iodev = iodev; 263 258 264 259 /* initialize mode and brightness according to platform_data */ ··· 288 281 if (ret < 0) 289 282 return ret; 290 283 291 - ret = device_create_file(led->cdev.dev, &dev_attr_mode); 292 - if (ret != 0) { 293 - dev_err(&pdev->dev, 294 - "failed to create file: %d\n", ret); 295 - led_classdev_unregister(&led->cdev); 296 - return ret; 297 - } 298 - 299 284 return 0; 300 285 } 301 286 ··· 295 296 { 296 297 struct max8997_led *led = platform_get_drvdata(pdev); 297 298 298 - device_remove_file(led->cdev.dev, &dev_attr_mode); 299 299 led_classdev_unregister(&led->cdev); 300 300 301 301 return 0;
+13 -18
drivers/leds/leds-netxbig.c
··· 293 293 294 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 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 304 led_classdev_unregister(&led_dat->cdev); 301 305 } 302 306 ··· 310 306 const struct netxbig_led *template) 311 307 { 312 308 struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); 313 - int ret; 314 309 315 310 spin_lock_init(&led_dat->lock); 316 311 led_dat->gpio_ext = pdata->gpio_ext; ··· 330 327 led_dat->sata = 0; 331 328 led_dat->cdev.brightness = LED_OFF; 332 329 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 330 + /* 331 + * If available, expose the SATA activity blink capability through 332 + * a "sata" sysfs attribute. 333 + */ 334 + if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) 335 + led_dat->cdev.groups = netxbig_led_groups; 333 336 led_dat->mode_addr = template->mode_addr; 334 337 led_dat->mode_val = template->mode_val; 335 338 led_dat->bright_addr = template->bright_addr; ··· 343 334 led_dat->timer = pdata->timer; 344 335 led_dat->num_timer = pdata->num_timer; 345 336 346 - ret = led_classdev_register(&pdev->dev, &led_dat->cdev); 347 - if (ret < 0) 348 - return ret; 349 - 350 - /* 351 - * If available, expose the SATA activity blink capability through 352 - * a "sata" sysfs attribute. 353 - */ 354 - if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) { 355 - ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); 356 - if (ret) 357 - led_classdev_unregister(&led_dat->cdev); 358 - } 359 - 360 - return ret; 337 + return led_classdev_register(&pdev->dev, &led_dat->cdev); 361 338 } 362 339 363 340 static int netxbig_led_probe(struct platform_device *pdev)
+7 -9
drivers/leds/leds-ns2.c
··· 185 185 186 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 194 static int 189 195 create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat, 190 196 const struct ns2_led *template) ··· 225 219 led_dat->cdev.blink_set = NULL; 226 220 led_dat->cdev.brightness_set = ns2_led_set; 227 221 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 222 + led_dat->cdev.groups = ns2_led_groups; 228 223 led_dat->cmd = template->cmd; 229 224 led_dat->slow = template->slow; 230 225 ··· 242 235 if (ret < 0) 243 236 return ret; 244 237 245 - ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); 246 - if (ret < 0) 247 - goto err_free_cdev; 248 - 249 238 return 0; 250 - 251 - err_free_cdev: 252 - led_classdev_unregister(&led_dat->cdev); 253 - return ret; 254 239 } 255 240 256 241 static void delete_ns2_led(struct ns2_led_data *led_dat) 257 242 { 258 - device_remove_file(led_dat->cdev.dev, &dev_attr_sata); 259 243 led_classdev_unregister(&led_dat->cdev); 260 244 } 261 245
+20 -8
drivers/leds/leds-pca963x.c
··· 12 12 * directory of this archive for more details. 13 13 * 14 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 17 * Note that hardware blinking violates the leds infrastructure driver 18 18 * interface since the hardware only supports blinking all LEDs with the ··· 52 52 enum pca963x_type { 53 53 pca9633, 54 54 pca9634, 55 + pca9635, 55 56 }; 56 57 57 58 struct pca963x_chipdef { ··· 75 74 .ledout_base = 0xc, 76 75 .n_leds = 8, 77 76 }, 77 + [pca9635] = { 78 + .grppwm = 0x12, 79 + .grpfreq = 0x13, 80 + .ledout_base = 0x14, 81 + .n_leds = 16, 82 + }, 78 83 }; 79 84 80 85 /* Total blink period in milliseconds */ ··· 91 84 { "pca9632", pca9633 }, 92 85 { "pca9633", pca9633 }, 93 86 { "pca9634", pca9634 }, 87 + { "pca9635", pca9635 }, 94 88 { } 95 89 }; 96 90 MODULE_DEVICE_TABLE(i2c, pca963x_id); ··· 115 107 struct work_struct work; 116 108 enum led_brightness brightness; 117 109 struct led_classdev led_cdev; 118 - int led_num; /* 0 .. 7 potentially */ 110 + int led_num; /* 0 .. 15 potentially */ 119 111 enum pca963x_cmd cmd; 120 112 char name[32]; 121 113 u8 gdc; ··· 329 321 { .compatible = "nxp,pca9632", }, 330 322 { .compatible = "nxp,pca9633", }, 331 323 { .compatible = "nxp,pca9634", }, 324 + { .compatible = "nxp,pca9635", }, 332 325 {}, 333 326 }; 334 327 #else ··· 384 375 pca963x_chip->leds = pca963x; 385 376 386 377 /* Turn off LEDs by default*/ 387 - i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00); 388 - if (chip->n_leds > 4) 389 - i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00); 378 + for (i = 0; i < chip->n_leds / 4; i++) 379 + i2c_smbus_write_byte_data(client, chip->ledout_base + i, 0x00); 390 380 391 381 for (i = 0; i < chip->n_leds; i++) { 392 382 pca963x[i].led_num = i; ··· 423 415 /* Disable LED all-call address and set normal mode */ 424 416 i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00); 425 417 426 - /* Configure output: open-drain or totem pole (push-pull) */ 427 - if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN) 428 - i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01); 418 + if (pdata) { 419 + /* Configure output: open-drain or totem pole (push-pull) */ 420 + if (pdata->outdrv == PCA963X_OPEN_DRAIN) 421 + i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01); 422 + else 423 + i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x05); 424 + } 429 425 430 426 return 0; 431 427
+9 -5
drivers/leds/leds-ss4200.c
··· 469 469 470 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 478 static int register_nasgpio_led(int led_nr) 473 479 { 474 480 int ret; ··· 487 481 led->brightness = LED_FULL; 488 482 led->brightness_set = nasgpio_led_set_brightness; 489 483 led->blink_set = nasgpio_led_set_blink; 484 + led->groups = nasgpio_led_groups; 490 485 ret = led_classdev_register(&nas_gpio_pci_dev->dev, led); 491 486 if (ret) 492 487 return ret; 493 - ret = device_create_file(led->dev, &dev_attr_blink); 494 - if (ret) 495 - led_classdev_unregister(led); 496 - return ret; 488 + 489 + return 0; 497 490 } 498 491 499 492 static void unregister_nasgpio_led(int led_nr) 500 493 { 501 494 struct led_classdev *led = get_classdev_for_led_nr(led_nr); 502 495 led_classdev_unregister(led); 503 - device_remove_file(led->dev, &dev_attr_blink); 504 496 } 505 497 /* 506 498 * module load/initialization
+9 -14
drivers/leds/leds-wm831x-status.c
··· 219 219 220 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 228 static int wm831x_status_probe(struct platform_device *pdev) 223 229 { 224 230 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); ··· 238 232 res = platform_get_resource(pdev, IORESOURCE_REG, 0); 239 233 if (res == NULL) { 240 234 dev_err(&pdev->dev, "No register resource\n"); 241 - ret = -EINVAL; 242 - goto err; 235 + return -EINVAL; 243 236 } 244 237 245 238 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status), ··· 289 284 drvdata->cdev.default_trigger = pdata.default_trigger; 290 285 drvdata->cdev.brightness_set = wm831x_status_set; 291 286 drvdata->cdev.blink_set = wm831x_status_blink_set; 287 + drvdata->cdev.groups = wm831x_status_groups; 292 288 293 289 ret = led_classdev_register(wm831x->dev, &drvdata->cdev); 294 290 if (ret < 0) { 295 291 dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); 296 - goto err_led; 292 + return ret; 297 293 } 298 294 299 - ret = device_create_file(drvdata->cdev.dev, &dev_attr_src); 300 - if (ret != 0) 301 - dev_err(&pdev->dev, 302 - "No source control for LED: %d\n", ret); 303 - 304 295 return 0; 305 - 306 - err_led: 307 - led_classdev_unregister(&drvdata->cdev); 308 - err: 309 - return ret; 310 296 } 311 297 312 298 static int wm831x_status_remove(struct platform_device *pdev) 313 299 { 314 300 struct wm831x_status *drvdata = platform_get_drvdata(pdev); 315 301 316 - device_remove_file(drvdata->cdev.dev, &dev_attr_src); 317 302 led_classdev_unregister(&drvdata->cdev); 318 303 319 304 return 0;
+3 -2
include/linux/leds.h
··· 15 15 #include <linux/list.h> 16 16 #include <linux/spinlock.h> 17 17 #include <linux/rwsem.h> 18 - #include <linux/timer.h> 19 18 #include <linux/workqueue.h> 20 19 21 20 struct device; ··· 62 63 unsigned long *delay_off); 63 64 64 65 struct device *dev; 66 + const struct attribute_group **groups; 67 + 65 68 struct list_head node; /* LED Device list */ 66 69 const char *default_trigger; /* Trigger to use */ 67 70 68 71 unsigned long blink_delay_on, blink_delay_off; 69 - struct timer_list blink_timer; 72 + struct delayed_work blink_work; 70 73 int blink_brightness; 71 74 72 75 struct work_struct set_brightness_work;