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

leds: simple driver for pwm driven LEDs

Add a simple driver for pwm driver LEDs. pwm_id and period can be defined
in board file. It is developed for pxa, however it is probably generic
enough to be used on other platforms with pwm.

Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>

authored by

Luotao Fu and committed by
Richard Purdie
41c42ff5 b2bdc3e7

+181
+6
drivers/leds/Kconfig
··· 197 197 This option enables support for DAC124S085 SPI DAC from NatSemi, 198 198 which can be used to control up to four LEDs. 199 199 200 + config LEDS_PWM 201 + tristate "PWM driven LED Support" 202 + depends on LEDS_CLASS && HAVE_PWM 203 + help 204 + This option enables support for pwm driven LEDs 205 + 200 206 comment "LED Triggers" 201 207 202 208 config LEDS_TRIGGERS
+1
drivers/leds/Makefile
··· 24 24 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o 25 25 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o 26 26 obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o 27 + obj-$(CONFIG_LEDS_PWM) += leds-pwm.o 27 28 28 29 # LED SPI Drivers 29 30 obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
+153
drivers/leds/leds-pwm.c
··· 1 + /* 2 + * linux/drivers/leds-pwm.c 3 + * 4 + * simple PWM based LED control 5 + * 6 + * Copyright 2009 Luotao Fu @ Pengutronix (l.fu@pengutronix.de) 7 + * 8 + * based on leds-gpio.c by Raphael Assenat <raph@8d.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/kernel.h> 17 + #include <linux/init.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/fb.h> 20 + #include <linux/leds.h> 21 + #include <linux/err.h> 22 + #include <linux/pwm.h> 23 + #include <linux/leds_pwm.h> 24 + 25 + struct led_pwm_data { 26 + struct led_classdev cdev; 27 + struct pwm_device *pwm; 28 + unsigned int active_low; 29 + unsigned int period; 30 + unsigned int max_brightness; 31 + }; 32 + 33 + static void led_pwm_set(struct led_classdev *led_cdev, 34 + enum led_brightness brightness) 35 + { 36 + struct led_pwm_data *led_dat = 37 + container_of(led_cdev, struct led_pwm_data, cdev); 38 + unsigned int max = led_dat->max_brightness; 39 + unsigned int period = led_dat->period; 40 + 41 + if (brightness == 0) { 42 + pwm_config(led_dat->pwm, 0, period); 43 + pwm_disable(led_dat->pwm); 44 + } else { 45 + pwm_config(led_dat->pwm, brightness * period / max, period); 46 + pwm_enable(led_dat->pwm); 47 + } 48 + } 49 + 50 + static int led_pwm_probe(struct platform_device *pdev) 51 + { 52 + struct led_pwm_platform_data *pdata = pdev->dev.platform_data; 53 + struct led_pwm *cur_led; 54 + struct led_pwm_data *leds_data, *led_dat; 55 + int i, ret = 0; 56 + 57 + if (!pdata) 58 + return -EBUSY; 59 + 60 + leds_data = kzalloc(sizeof(struct led_pwm_data) * pdata->num_leds, 61 + GFP_KERNEL); 62 + if (!leds_data) 63 + return -ENOMEM; 64 + 65 + for (i = 0; i < pdata->num_leds; i++) { 66 + cur_led = &pdata->leds[i]; 67 + led_dat = &leds_data[i]; 68 + 69 + led_dat->pwm = pwm_request(cur_led->pwm_id, 70 + cur_led->name); 71 + if (IS_ERR(led_dat->pwm)) { 72 + dev_err(&pdev->dev, "unable to request PWM %d\n", 73 + cur_led->pwm_id); 74 + goto err; 75 + } 76 + 77 + led_dat->cdev.name = cur_led->name; 78 + led_dat->cdev.default_trigger = cur_led->default_trigger; 79 + led_dat->active_low = cur_led->active_low; 80 + led_dat->max_brightness = cur_led->max_brightness; 81 + led_dat->period = cur_led->pwm_period_ns; 82 + led_dat->cdev.brightness_set = led_pwm_set; 83 + led_dat->cdev.brightness = LED_OFF; 84 + led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 85 + 86 + ret = led_classdev_register(&pdev->dev, &led_dat->cdev); 87 + if (ret < 0) { 88 + pwm_free(led_dat->pwm); 89 + goto err; 90 + } 91 + } 92 + 93 + platform_set_drvdata(pdev, leds_data); 94 + 95 + return 0; 96 + 97 + err: 98 + if (i > 0) { 99 + for (i = i - 1; i >= 0; i--) { 100 + led_classdev_unregister(&leds_data[i].cdev); 101 + pwm_free(leds_data[i].pwm); 102 + } 103 + } 104 + 105 + kfree(leds_data); 106 + 107 + return ret; 108 + } 109 + 110 + static int __devexit led_pwm_remove(struct platform_device *pdev) 111 + { 112 + int i; 113 + struct led_pwm_platform_data *pdata = pdev->dev.platform_data; 114 + struct led_pwm_data *leds_data; 115 + 116 + leds_data = platform_get_drvdata(pdev); 117 + 118 + for (i = 0; i < pdata->num_leds; i++) { 119 + led_classdev_unregister(&leds_data[i].cdev); 120 + pwm_free(leds_data[i].pwm); 121 + } 122 + 123 + kfree(leds_data); 124 + 125 + return 0; 126 + } 127 + 128 + static struct platform_driver led_pwm_driver = { 129 + .probe = led_pwm_probe, 130 + .remove = __devexit_p(led_pwm_remove), 131 + .driver = { 132 + .name = "leds_pwm", 133 + .owner = THIS_MODULE, 134 + }, 135 + }; 136 + 137 + static int __init led_pwm_init(void) 138 + { 139 + return platform_driver_register(&led_pwm_driver); 140 + } 141 + 142 + static void __exit led_pwm_exit(void) 143 + { 144 + platform_driver_unregister(&led_pwm_driver); 145 + } 146 + 147 + module_init(led_pwm_init); 148 + module_exit(led_pwm_exit); 149 + 150 + MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); 151 + MODULE_DESCRIPTION("PWM LED driver for PXA"); 152 + MODULE_LICENSE("GPL"); 153 + MODULE_ALIAS("platform:leds-pwm");
+21
include/linux/leds_pwm.h
··· 1 + /* 2 + * PWM LED driver data - see drivers/leds/leds-pwm.c 3 + */ 4 + #ifndef __LINUX_LEDS_PWM_H 5 + #define __LINUX_LEDS_PWM_H 6 + 7 + struct led_pwm { 8 + const char *name; 9 + const char *default_trigger; 10 + unsigned pwm_id; 11 + u8 active_low; 12 + unsigned max_brightness; 13 + unsigned pwm_period_ns; 14 + }; 15 + 16 + struct led_pwm_platform_data { 17 + int num_leds; 18 + struct led_pwm *leds; 19 + }; 20 + 21 + #endif