diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 20:26:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 20:26:27 -0700 |
commit | aa0b3b2bee1d3ca8355de76caebf65b836c9bb6e (patch) | |
tree | e1ba9eb2e96b55af1008162ec662b03ea24f9989 /drivers | |
parent | 6ee127b7dd63afe4d6d0a58293786bf4bf336850 (diff) | |
parent | d45bb11616c94c76c6e40960a120c0687b708a2e (diff) |
Merge branch 'for-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED subsystem update from Bryan Wu.
* 'for-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds: (50 commits)
leds-lp8788: forgotten unlock at lp8788_led_work
LEDS: propagate error codes in blinkm_detect()
LEDS: memory leak in blinkm_led_common_set()
leds: add new lp8788 led driver
LEDS: add BlinkM RGB LED driver, documentation and update MAINTAINERS
leds: max8997: Simplify max8997_led_set_mode implementation
leds/leds-s3c24xx: use devm_gpio_request
leds: convert Network Space v2 LED driver to devm_kzalloc() and cleanup error exit path
leds: convert DAC124S085 LED driver to devm_kzalloc()
leds: convert LM3530 LED driver to devm_kzalloc() and cleanup error exit path
leds: convert TCA6507 LED driver to devm_kzalloc()
leds: convert Freescale MC13783 LED driver to devm_kzalloc() and cleanup error exit path
leds: convert ADP5520 LED driver to devm_kzalloc() and cleanup error exit path
leds: convert PCA955x LED driver to devm_kzalloc() and cleanup error exit path
leds: convert Sun Fire LED driver to devm_kzalloc() and cleanup error exit path
leds: convert PCA9532 LED driver to devm_kzalloc()
leds: convert LT3593 LED driver to devm_kzalloc()
leds: convert Renesas TPU LED driver to devm_kzalloc() and cleanup error exit path
leds: convert LP5523 LED driver to devm_kzalloc() and cleanup error exit path
leds: convert PCA9633 LED driver to devm_kzalloc()
...
Diffstat (limited to 'drivers')
43 files changed, 2067 insertions, 410 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 12b2b55c519..c96bbaadeeb 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -200,6 +200,13 @@ config LEDS_LP5523 Driver provides direct control via LED class and interface for programming the engines. +config LEDS_LP8788 + tristate "LED support for the TI LP8788 PMIC" + depends on LEDS_CLASS + depends on MFD_LP8788 + help + This option enables support for the Keyboard LEDs on the LP8788 PMIC. + config LEDS_CLEVO_MAIL tristate "Mail LED on Clevo notebook" depends on LEDS_CLASS @@ -415,6 +422,14 @@ config LEDS_MAX8997 This option enables support for on-chip LED drivers on MAXIM MAX8997 PMIC. +config LEDS_LM3556 + tristate "LED support for LM3556 Chip" + depends on LEDS_CLASS && I2C + select REGMAP_I2C + help + This option enables support for LEDs connected to LM3556. + LM3556 includes Torch, Flash and Indicator functions. + config LEDS_OT200 tristate "LED support for the Bachmann OT200" depends on LEDS_CLASS && HAS_IOMEM @@ -422,6 +437,14 @@ config LEDS_OT200 This option enables support for the LEDs on the Bachmann OT200. Say Y to enable LEDs on the Bachmann OT200. +config LEDS_BLINKM + tristate "LED support for the BlinkM I2C RGB LED" + depends on LEDS_CLASS + depends on I2C + help + This option enables support for the BlinkM RGB LED connected + through I2C. Say Y to enable support for the BlinkM LED. + config LEDS_TRIGGERS bool "LED Trigger support" depends on LEDS_CLASS @@ -443,6 +466,20 @@ config LEDS_TRIGGER_TIMER If unsure, say Y. +config LEDS_TRIGGER_ONESHOT + tristate "LED One-shot Trigger" + depends on LEDS_TRIGGERS + help + This allows LEDs to blink in one-shot pulses with parameters + controlled via sysfs. It's useful to notify the user on + sporadic events, when there are no clear begin and end trap points, + or on dense events, where this blinks the LED at constant rate if + rearmed continuously. + + It also shows how to use the led_blink_set_oneshot() function. + + If unsure, say Y. + config LEDS_TRIGGER_IDE_DISK bool "LED IDE Disk Trigger" depends on IDE_GD_ATA @@ -497,7 +534,7 @@ config LEDS_TRIGGER_TRANSIENT depends on LEDS_TRIGGERS help This allows one time activation of a transient state on - GPIO/PWM based hadrware. + GPIO/PWM based hardware. If unsure, say Y. endif # NEW_LEDS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index f8958cd6cf6..a4429a9217b 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o +obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o @@ -47,12 +48,15 @@ obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o +obj-$(CONFIG_LEDS_LM3556) += leds-lm3556.o +obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o +obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index e663e6f413e..c599095bc00 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -53,7 +53,7 @@ static ssize_t led_brightness_store(struct device *dev, if (state == LED_OFF) led_trigger_remove(led_cdev); - led_set_brightness(led_cdev, state); + __led_set_brightness(led_cdev, state); return size; } @@ -82,7 +82,12 @@ static void led_timer_function(unsigned long data) unsigned long delay; if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { - led_set_brightness(led_cdev, LED_OFF); + __led_set_brightness(led_cdev, LED_OFF); + return; + } + + if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) { + led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; return; } @@ -100,7 +105,21 @@ static void led_timer_function(unsigned long data) delay = led_cdev->blink_delay_off; } - led_set_brightness(led_cdev, brightness); + __led_set_brightness(led_cdev, brightness); + + /* Return in next iteration if led is in one-shot mode and we are in + * the final blink state so that the led is toggled each delay_on + + * delay_off milliseconds in worst case. + */ + if (led_cdev->flags & LED_BLINK_ONESHOT) { + if (led_cdev->flags & LED_BLINK_INVERT) { + if (brightness) + led_cdev->flags |= LED_BLINK_ONESHOT_STOP; + } else { + if (!brightness) + led_cdev->flags |= LED_BLINK_ONESHOT_STOP; + } + } mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); } @@ -203,7 +222,7 @@ void led_classdev_unregister(struct led_classdev *led_cdev) #endif /* Stop blinking */ - led_brightness_set(led_cdev, LED_OFF); + led_set_brightness(led_cdev, LED_OFF); device_unregister(led_cdev->dev); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c index d65353d8d3f..2ab05af3de3 100644 --- a/drivers/leds/led-core.c +++ b/drivers/leds/led-core.c @@ -24,14 +24,6 @@ EXPORT_SYMBOL_GPL(leds_list_lock); LIST_HEAD(leds_list); EXPORT_SYMBOL_GPL(leds_list); -static void led_stop_software_blink(struct led_classdev *led_cdev) -{ - /* deactivate previous settings */ - del_timer_sync(&led_cdev->blink_timer); - led_cdev->blink_delay_on = 0; - led_cdev->blink_delay_off = 0; -} - static void led_set_software_blink(struct led_classdev *led_cdev, unsigned long delay_on, unsigned long delay_off) @@ -53,7 +45,7 @@ static void led_set_software_blink(struct led_classdev *led_cdev, /* never off - just set to brightness */ if (!delay_off) { - led_set_brightness(led_cdev, led_cdev->blink_brightness); + __led_set_brightness(led_cdev, led_cdev->blink_brightness); return; } @@ -61,13 +53,12 @@ static void led_set_software_blink(struct led_classdev *led_cdev, } -void led_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) +static void led_blink_setup(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) { - del_timer_sync(&led_cdev->blink_timer); - - if (led_cdev->blink_set && + if (!(led_cdev->flags & LED_BLINK_ONESHOT) && + led_cdev->blink_set && !led_cdev->blink_set(led_cdev, delay_on, delay_off)) return; @@ -77,12 +68,49 @@ void led_blink_set(struct led_classdev *led_cdev, led_set_software_blink(led_cdev, *delay_on, *delay_off); } + +void led_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + del_timer_sync(&led_cdev->blink_timer); + + led_cdev->flags &= ~LED_BLINK_ONESHOT; + led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; + + led_blink_setup(led_cdev, delay_on, delay_off); +} EXPORT_SYMBOL(led_blink_set); -void led_brightness_set(struct led_classdev *led_cdev, +void led_blink_set_oneshot(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off, + int invert) +{ + if ((led_cdev->flags & LED_BLINK_ONESHOT) && + timer_pending(&led_cdev->blink_timer)) + return; + + led_cdev->flags |= LED_BLINK_ONESHOT; + led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; + + if (invert) + led_cdev->flags |= LED_BLINK_INVERT; + else + led_cdev->flags &= ~LED_BLINK_INVERT; + + led_blink_setup(led_cdev, delay_on, delay_off); +} +EXPORT_SYMBOL(led_blink_set_oneshot); + +void led_set_brightness(struct led_classdev *led_cdev, enum led_brightness brightness) { - led_stop_software_blink(led_cdev); - led_cdev->brightness_set(led_cdev, brightness); + /* stop and clear soft-blink timer */ + del_timer_sync(&led_cdev->blink_timer); + led_cdev->blink_delay_on = 0; + led_cdev->blink_delay_off = 0; + + __led_set_brightness(led_cdev, brightness); } -EXPORT_SYMBOL(led_brightness_set); +EXPORT_SYMBOL(led_set_brightness); diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 46b4c766335..6157cbbf411 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -99,7 +99,7 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, EXPORT_SYMBOL_GPL(led_trigger_show); /* Caller must ensure led_cdev->trigger_lock held */ -void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) +void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) { unsigned long flags; @@ -112,15 +112,15 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) if (led_cdev->trigger->deactivate) led_cdev->trigger->deactivate(led_cdev); led_cdev->trigger = NULL; - led_brightness_set(led_cdev, LED_OFF); + led_set_brightness(led_cdev, LED_OFF); } - if (trigger) { - write_lock_irqsave(&trigger->leddev_list_lock, flags); - list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs); - write_unlock_irqrestore(&trigger->leddev_list_lock, flags); - led_cdev->trigger = trigger; - if (trigger->activate) - trigger->activate(led_cdev); + if (trig) { + write_lock_irqsave(&trig->leddev_list_lock, flags); + list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); + write_unlock_irqrestore(&trig->leddev_list_lock, flags); + led_cdev->trigger = trig; + if (trig->activate) + trig->activate(led_cdev); } } EXPORT_SYMBOL_GPL(led_trigger_set); @@ -153,24 +153,24 @@ EXPORT_SYMBOL_GPL(led_trigger_set_default); /* LED Trigger Interface */ -int led_trigger_register(struct led_trigger *trigger) +int led_trigger_register(struct led_trigger *trig) { struct led_classdev *led_cdev; - struct led_trigger *trig; + struct led_trigger *_trig; - rwlock_init(&trigger->leddev_list_lock); - INIT_LIST_HEAD(&trigger->led_cdevs); + rwlock_init(&trig->leddev_list_lock); + INIT_LIST_HEAD(&trig->led_cdevs); down_write(&triggers_list_lock); /* Make sure the trigger's name isn't already in use */ - list_for_each_entry(trig, &trigger_list, next_trig) { - if (!strcmp(trig->name, trigger->name)) { + list_for_each_entry(_trig, &trigger_list, next_trig) { + if (!strcmp(_trig->name, trig->name)) { up_write(&triggers_list_lock); return -EEXIST; } } /* Add to the list of led triggers */ - list_add_tail(&trigger->next_trig, &trigger_list); + list_add_tail(&trig->next_trig, &trigger_list); up_write(&triggers_list_lock); /* Register with any LEDs that have this as a default trigger */ @@ -178,8 +178,8 @@ int led_trigger_register(struct led_trigger *trigger) list_for_each_entry(led_cdev, &leds_list, node) { down_write(&led_cdev->trigger_lock); if (!led_cdev->trigger && led_cdev->default_trigger && - !strcmp(led_cdev->default_trigger, trigger->name)) - led_trigger_set(led_cdev, trigger); + !strcmp(led_cdev->default_trigger, trig->name)) + led_trigger_set(led_cdev, trig); up_write(&led_cdev->trigger_lock); } up_read(&leds_list_lock); @@ -188,20 +188,20 @@ int led_trigger_register(struct led_trigger *trigger) } EXPORT_SYMBOL_GPL(led_trigger_register); -void led_trigger_unregister(struct led_trigger *trigger) +void led_trigger_unregister(struct led_trigger *trig) { struct led_classdev *led_cdev; /* Remove from the list of led triggers */ down_write(&triggers_list_lock); - list_del(&trigger->next_trig); + list_del(&trig->next_trig); up_write(&triggers_list_lock); /* Remove anyone actively using this trigger */ down_read(&leds_list_lock); list_for_each_entry(led_cdev, &leds_list, node) { down_write(&led_cdev->trigger_lock); - if (led_cdev->trigger == trigger) + if (led_cdev->trigger == trig) led_trigger_set(led_cdev, NULL); up_write(&led_cdev->trigger_lock); } @@ -211,58 +211,80 @@ EXPORT_SYMBOL_GPL(led_trigger_unregister); /* Simple LED Tigger Interface */ -void led_trigger_event(struct led_trigger *trigger, +void led_trigger_event(struct led_trigger *trig, enum led_brightness brightness) { struct list_head *entry; - if (!trigger) + if (!trig) return; - read_lock(&trigger->leddev_list_lock); - list_for_each(entry, &trigger->led_cdevs) { + read_lock(&trig->leddev_list_lock); + list_for_each(entry, &trig->led_cdevs) { struct led_classdev *led_cdev; led_cdev = list_entry(entry, struct led_classdev, trig_list); led_set_brightness(led_cdev, brightness); } - read_unlock(&trigger->leddev_list_lock); + read_unlock(&trig->leddev_list_lock); } EXPORT_SYMBOL_GPL(led_trigger_event); -void led_trigger_blink(struct led_trigger *trigger, - unsigned long *delay_on, - unsigned long *delay_off) +static void led_trigger_blink_setup(struct led_trigger *trig, + unsigned long *delay_on, + unsigned long *delay_off, + int oneshot, + int invert) { struct list_head *entry; - if (!trigger) + if (!trig) return; - read_lock(&trigger->leddev_list_lock); - list_for_each(entry, &trigger->led_cdevs) { + read_lock(&trig->leddev_list_lock); + list_for_each(entry, &trig->led_cdevs) { struct led_classdev *led_cdev; led_cdev = list_entry(entry, struct led_classdev, trig_list); - led_blink_set(led_cdev, delay_on, delay_off); + if (oneshot) + led_blink_set_oneshot(led_cdev, delay_on, delay_off, + invert); + else + led_blink_set(led_cdev, delay_on, delay_off); } - read_unlock(&trigger->leddev_list_lock); + read_unlock(&trig->leddev_list_lock); +} + +void led_trigger_blink(struct led_trigger *trig, + unsigned long *delay_on, + unsigned long *delay_off) +{ + led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0); } EXPORT_SYMBOL_GPL(led_trigger_blink); +void led_trigger_blink_oneshot(struct led_trigger *trig, + unsigned long *delay_on, + unsigned long *delay_off, + int invert) +{ + led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert); +} +EXPORT_SYMBOL_GPL(led_trigger_blink_oneshot); + void led_trigger_register_simple(const char *name, struct led_trigger **tp) { - struct led_trigger *trigger; + struct led_trigger *trig; int err; - trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + trig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); - if (trigger) { - trigger->name = name; - err = led_trigger_register(trigger); + if (trig) { + trig->name = name; + err = led_trigger_register(trig); if (err < 0) { - kfree(trigger); - trigger = NULL; + kfree(trig); + trig = NULL; printk(KERN_WARNING "LED trigger %s failed to register" " (%d)\n", name, err); } @@ -270,15 +292,15 @@ void led_trigger_register_simple(const char *name, struct led_trigger **tp) printk(KERN_WARNING "LED trigger %s failed to register" " (no memory)\n", name); - *tp = trigger; + *tp = trig; } EXPORT_SYMBOL_GPL(led_trigger_register_simple); -void led_trigger_unregister_simple(struct led_trigger *trigger) +void led_trigger_unregister_simple(struct led_trigger *trig) { - if (trigger) - led_trigger_unregister(trigger); - kfree(trigger); + if (trig) + led_trigger_unregister(trig); + kfree(trig); } EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 5b61aaf7ac0..61897cfeeda 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -209,7 +209,7 @@ static int pm860x_led_probe(struct platform_device *pdev) return -EINVAL; } - data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL); if (data == NULL) return -ENOMEM; strncpy(data->name, res->name, MFD_NAME_SIZE - 1); @@ -220,7 +220,6 @@ static int pm860x_led_probe(struct platform_device *pdev) data->port = pdata->flags; if (data->port < 0) { dev_err(&pdev->dev, "check device failed\n"); - kfree(data); return -EINVAL; } @@ -233,13 +232,10 @@ static int pm860x_led_probe(struct platform_device *pdev) ret = led_classdev_register(chip->dev, &data->cdev); if (ret < 0) { dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); - goto out; + return ret; } pm860x_led_set(&data->cdev, 0); return 0; -out: - kfree(data); - return ret; } static int pm860x_led_remove(struct platform_device *pdev) @@ -247,7 +243,6 @@ static int pm860x_led_remove(struct platform_device *pdev) struct pm860x_led *data = platform_get_drvdata(pdev); led_classdev_unregister(&data->cdev); - kfree(data); return 0; } diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index b1400db3f83..aa56a867693 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c @@ -119,7 +119,8 @@ static int __devinit adp5520_led_probe(struct platform_device *pdev) return -EFAULT; } - led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL); + led = devm_kzalloc(&pdev->dev, sizeof(*led) * pdata->num_leds, + GFP_KERNEL); if (led == NULL) { dev_err(&pdev->dev, "failed to alloc memory\n"); return -ENOMEM; @@ -129,7 +130,7 @@ static int __devinit adp5520_led_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to write\n"); - goto err_free; + return ret; } for (i = 0; i < pdata->num_leds; ++i) { @@ -179,8 +180,6 @@ err: } } -err_free: - kfree(led); return ret; } @@ -200,7 +199,6 @@ static int __devexit adp5520_led_remove(struct platform_device *pdev) cancel_work_sync(&led[i].work); } - kfree(led); return 0; } diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c index 525a9249283..5de74ff90dc 100644 --- a/drivers/leds/leds-asic3.c +++ b/drivers/leds/leds-asic3.c @@ -99,12 +99,13 @@ static int __devinit asic3_led_probe(struct platform_device *pdev) ret = mfd_cell_enable(pdev); if (ret < 0) - goto ret0; + return ret; - led->cdev = kzalloc(sizeof(struct led_classdev), GFP_KERNEL); + led->cdev = devm_kzalloc(&pdev->dev, sizeof(struct led_classdev), + GFP_KERNEL); if (!led->cdev) { ret = -ENOMEM; - goto ret1; + goto out; } led->cdev->name = led->name; @@ -115,15 +116,12 @@ static int __devinit asic3_led_probe(struct platform_device *pdev) ret = led_classdev_register(&pdev->dev, led->cdev); if (ret < 0) - goto ret2; + goto out; return 0; -ret2: - kfree(led->cdev); -ret1: +out: (void) mfd_cell_disable(pdev); -ret0: return ret; } @@ -133,8 +131,6 @@ static int __devexit asic3_led_remove(struct platform_device *pdev) led_classdev_unregister(led->cdev); - kfree(led->cdev); - return mfd_cell_disable(pdev); } diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c index 64ad702a2ec..45430632faa 100644 --- a/drivers/leds/leds-atmel-pwm.c +++ b/drivers/leds/leds-atmel-pwm.c @@ -46,7 +46,8 @@ static int __devinit pwmled_probe(struct platform_device *pdev) if (!pdata || pdata->num_leds < 1) return -ENODEV; - leds = kcalloc(pdata->num_leds, sizeof(*leds), GFP_KERNEL); + leds = devm_kzalloc(&pdev->dev, pdata->num_leds * sizeof(*leds), + GFP_KERNEL); if (!leds) return -ENOMEM; @@ -108,7 +109,6 @@ err: pwm_channel_free(&leds[i].pwmc); } } - kfree(leds); return status; } @@ -129,7 +129,6 @@ static int __exit pwmled_remove(struct platform_device *pdev) pwm_channel_free(&led->pwmc); } - kfree(leds); platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 591cbdf5a04..89ca6a2a19d 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -677,7 +677,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, struct bd2802_led_platform_data *pdata; int ret, i; - led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); + led = devm_kzalloc(&client->dev, sizeof(struct bd2802_led), GFP_KERNEL); if (!led) { dev_err(&client->dev, "failed to allocate driver data\n"); return -ENOMEM; @@ -697,7 +697,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, ret = bd2802_write_byte(client, BD2802_REG_CLKSETUP, 0x00); if (ret < 0) { dev_err(&client->dev, "failed to detect device\n"); - goto failed_free; + return ret; } else dev_info(&client->dev, "return 0x%02x\n", ret); @@ -729,9 +729,6 @@ static int __devinit bd2802_probe(struct i2c_client *client, failed_unregister_dev_file: for (i--; i >= 0; i--) device_remove_file(&led->client->dev, bd2802_attributes[i]); -failed_free: - kfree(led); - return ret; } @@ -746,7 +743,6 @@ static int __exit bd2802_remove(struct i2c_client *client) bd2802_disable_adv_conf(led); for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) device_remove_file(&led->client->dev, bd2802_attributes[i]); - kfree(led); return 0; } diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c new file mode 100644 index 00000000000..f7c3d7f1ec5 --- /dev/null +++ b/drivers/leds/leds-blinkm.c @@ -0,0 +1,815 @@ +/* + * leds-blinkm.c + * (c) Jan-Simon Möller (dl9pf@gmx.de) + * + * |