aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-26 13:50:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-26 13:50:47 -0400
commitcce1d9f23213f3a8a43b6038df84a665aa8d8612 (patch)
tree0ef75bc1641f7202763591a91fc6030898470f7b /drivers/leds
parentd910fc786014ac3fb72f837c329c112e0c7a9aea (diff)
parentf16a5dba01ed942f427f56b0d1128251721275a5 (diff)
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds: leds: move leds-clevo-mail's probe function to .devinit.text leds: Fix indentation in LEDS_LP3944 Kconfig entry leds: Fix LED names leds: Fix leds-pca9532 whitespace issues leds: fix coding style in worker thread code for ledtrig-gpio. leds: gpio-leds: fix typographics fault leds: Add WM831x status LED driver
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/Kconfig13
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-clevo-mail.c2
-rw-r--r--drivers/leds/leds-cobalt-qube.c2
-rw-r--r--drivers/leds/leds-cobalt-raq.c4
-rw-r--r--drivers/leds/leds-gpio.c2
-rw-r--r--drivers/leds/leds-pca9532.c12
-rw-r--r--drivers/leds/leds-wm831x-status.c341
-rw-r--r--drivers/leds/ledtrig-gpio.c32
9 files changed, 379 insertions, 30 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 7c8e7122aaa9..e4f599f20e38 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -150,9 +150,9 @@ config LEDS_LP3944
150 tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" 150 tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
151 depends on LEDS_CLASS && I2C 151 depends on LEDS_CLASS && I2C
152 help 152 help
153 This option enables support for LEDs connected to the National 153 This option enables support for LEDs connected to the National
154 Semiconductor LP3944 Lighting Management Unit (LMU) also known as 154 Semiconductor LP3944 Lighting Management Unit (LMU) also known as
155 Fun Light Chip. 155 Fun Light Chip.
156 156
157 To compile this driver as a module, choose M here: the 157 To compile this driver as a module, choose M here: the
158 module will be called leds-lp3944. 158 module will be called leds-lp3944.
@@ -195,6 +195,13 @@ config LEDS_PCA955X
195 LED driver chips accessed via the I2C bus. Supported 195 LED driver chips accessed via the I2C bus. Supported
196 devices include PCA9550, PCA9551, PCA9552, and PCA9553. 196 devices include PCA9550, PCA9551, PCA9552, and PCA9553.
197 197
198config LEDS_WM831X_STATUS
199 tristate "LED support for status LEDs on WM831x PMICs"
200 depends on LEDS_CLASS && MFD_WM831X
201 help
202 This option enables support for the status LEDs of the WM831x
203 series of PMICs.
204
198config LEDS_WM8350 205config LEDS_WM8350
199 tristate "LED Support for WM8350 AudioPlus PMIC" 206 tristate "LED Support for WM8350 AudioPlus PMIC"
200 depends on LEDS_CLASS && MFD_WM8350 207 depends on LEDS_CLASS && MFD_WM8350
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e8cdcf77a4c3..46d72704d606 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
26obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 26obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
27obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o 27obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
28obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o 28obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
29obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
29obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o 30obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
30obj-$(CONFIG_LEDS_PWM) += leds-pwm.o 31obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
31 32
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index f2242db54016..a498135a4e80 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -153,7 +153,7 @@ static struct led_classdev clevo_mail_led = {
153 .flags = LED_CORE_SUSPENDRESUME, 153 .flags = LED_CORE_SUSPENDRESUME,
154}; 154};
155 155
156static int __init clevo_mail_led_probe(struct platform_device *pdev) 156static int __devinit clevo_mail_led_probe(struct platform_device *pdev)
157{ 157{
158 return led_classdev_register(&pdev->dev, &clevo_mail_led); 158 return led_classdev_register(&pdev->dev, &clevo_mail_led);
159} 159}
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 059aa2924b1c..8816806accd2 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -28,7 +28,7 @@ static void qube_front_led_set(struct led_classdev *led_cdev,
28} 28}
29 29
30static struct led_classdev qube_front_led = { 30static struct led_classdev qube_front_led = {
31 .name = "qube-front", 31 .name = "qube::front",
32 .brightness = LED_FULL, 32 .brightness = LED_FULL,
33 .brightness_set = qube_front_led_set, 33 .brightness_set = qube_front_led_set,
34 .default_trigger = "ide-disk", 34 .default_trigger = "ide-disk",
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index 5f1ce810815f..defc212105f3 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -49,7 +49,7 @@ static void raq_web_led_set(struct led_classdev *led_cdev,
49} 49}
50 50
51static struct led_classdev raq_web_led = { 51static struct led_classdev raq_web_led = {
52 .name = "raq-web", 52 .name = "raq::web",
53 .brightness_set = raq_web_led_set, 53 .brightness_set = raq_web_led_set,
54}; 54};
55 55
@@ -70,7 +70,7 @@ static void raq_power_off_led_set(struct led_classdev *led_cdev,
70} 70}
71 71
72static struct led_classdev raq_power_off_led = { 72static struct led_classdev raq_power_off_led = {
73 .name = "raq-power-off", 73 .name = "raq::power-off",
74 .brightness_set = raq_power_off_led_set, 74 .brightness_set = raq_power_off_led_set,
75 .default_trigger = "power-off", 75 .default_trigger = "power-off",
76}; 76};
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 6b06638eb5b4..7467980b8cf9 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -80,7 +80,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
80 80
81 /* skip leds that aren't available */ 81 /* skip leds that aren't available */
82 if (!gpio_is_valid(template->gpio)) { 82 if (!gpio_is_valid(template->gpio)) {
83 printk(KERN_INFO "Skipping unavilable LED gpio %d (%s)\n", 83 printk(KERN_INFO "Skipping unavailable LED gpio %d (%s)\n",
84 template->gpio, template->name); 84 template->gpio, template->name);
85 return 0; 85 return 0;
86 } 86 }
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index dba8921240f2..708a8017c21d 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -34,7 +34,7 @@ struct pca9532_data {
34 struct i2c_client *client; 34 struct i2c_client *client;
35 struct pca9532_led leds[16]; 35 struct pca9532_led leds[16];
36 struct mutex update_lock; 36 struct mutex update_lock;
37 struct input_dev *idev; 37 struct input_dev *idev;
38 struct work_struct work; 38 struct work_struct work;
39 u8 pwm[2]; 39 u8 pwm[2];
40 u8 psc[2]; 40 u8 psc[2];
@@ -53,9 +53,9 @@ MODULE_DEVICE_TABLE(i2c, pca9532_id);
53 53
54static struct i2c_driver pca9532_driver = { 54static struct i2c_driver pca9532_driver = {
55 .driver = { 55 .driver = {
56 .name = "pca9532", 56 .name = "pca9532",
57 }, 57 },
58 .probe = pca9532_probe, 58 .probe = pca9532_probe,
59 .remove = pca9532_remove, 59 .remove = pca9532_remove,
60 .id_table = pca9532_id, 60 .id_table = pca9532_id,
61}; 61};
@@ -149,7 +149,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev,
149 149
150 if (*delay_on == 0 && *delay_off == 0) { 150 if (*delay_on == 0 && *delay_off == 0) {
151 /* led subsystem ask us for a blink rate */ 151 /* led subsystem ask us for a blink rate */
152 *delay_on = 1000; 152 *delay_on = 1000;
153 *delay_off = 1000; 153 *delay_off = 1000;
154 } 154 }
155 if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6) 155 if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6)
@@ -227,7 +227,7 @@ static int pca9532_configure(struct i2c_client *client,
227 break; 227 break;
228 case PCA9532_TYPE_LED: 228 case PCA9532_TYPE_LED:
229 led->state = pled->state; 229 led->state = pled->state;
230 led->name = pled->name; 230 led->name = pled->name;
231 led->ldev.name = led->name; 231 led->ldev.name = led->name;
232 led->ldev.brightness = LED_OFF; 232 led->ldev.brightness = LED_OFF;
233 led->ldev.brightness_set = pca9532_set_brightness; 233 led->ldev.brightness_set = pca9532_set_brightness;
@@ -254,7 +254,7 @@ static int pca9532_configure(struct i2c_client *client,
254 data->idev->name = pled->name; 254 data->idev->name = pled->name;
255 data->idev->phys = "i2c/pca9532"; 255 data->idev->phys = "i2c/pca9532";
256 data->idev->id.bustype = BUS_HOST; 256 data->idev->id.bustype = BUS_HOST;
257 data->idev->id.vendor = 0x001f; 257 data->idev->id.vendor = 0x001f;
258 data->idev->id.product = 0x0001; 258 data->idev->id.product = 0x0001;
259 data->idev->id.version = 0x0100; 259 data->idev->id.version = 0x0100;
260 data->idev->evbit[0] = BIT_MASK(EV_SND); 260 data->idev->evbit[0] = BIT_MASK(EV_SND);
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
new file mode 100644
index 000000000000..c586d05e336a
--- /dev/null
+++ b/drivers/leds/leds-wm831x-status.c
@@ -0,0 +1,341 @@
1/*
2 * LED driver for WM831x status LEDs
3 *
4 * Copyright(C) 2009 Wolfson Microelectronics PLC.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/leds.h>
16#include <linux/err.h>
17#include <linux/mfd/wm831x/core.h>
18#include <linux/mfd/wm831x/pdata.h>
19#include <linux/mfd/wm831x/status.h>
20
21
22struct wm831x_status {
23 struct led_classdev cdev;
24 struct wm831x *wm831x;
25 struct work_struct work;
26 struct mutex mutex;
27
28 spinlock_t value_lock;
29 int reg; /* Control register */
30 int reg_val; /* Control register value */
31
32 int blink;
33 int blink_time;
34 int blink_cyc;
35 int src;
36 enum led_brightness brightness;
37};
38
39#define to_wm831x_status(led_cdev) \
40 container_of(led_cdev, struct wm831x_status, cdev)
41
42static void wm831x_status_work(struct work_struct *work)
43{
44 struct wm831x_status *led = container_of(work, struct wm831x_status,
45 work);
46 unsigned long flags;
47
48 mutex_lock(&led->mutex);
49
50 led->reg_val &= ~(WM831X_LED_SRC_MASK | WM831X_LED_MODE_MASK |
51 WM831X_LED_DUTY_CYC_MASK | WM831X_LED_DUR_MASK);
52
53 spin_lock_irqsave(&led->value_lock, flags);
54
55 led->reg_val |= led->src << WM831X_LED_SRC_SHIFT;
56 if (led->blink) {
57 led->reg_val |= 2 << WM831X_LED_MODE_SHIFT;
58 led->reg_val |= led->blink_time << WM831X_LED_DUR_SHIFT;
59 led->reg_val |= led->blink_cyc;
60 } else {
61 if (led->brightness != LED_OFF)
62 led->reg_val |= 1 << WM831X_LED_MODE_SHIFT;
63 }
64
65 spin_unlock_irqrestore(&led->value_lock, flags);
66
67 wm831x_reg_write(led->wm831x, led->reg, led->reg_val);
68
69 mutex_unlock(&led->mutex);
70}
71
72static void wm831x_status_set(struct led_classdev *led_cdev,
73 enum led_brightness value)
74{
75 struct wm831x_status *led = to_wm831x_status(led_cdev);
76 unsigned long flags;
77
78 spin_lock_irqsave(&led->value_lock, flags);
79 led->brightness = value;
80 if (value == LED_OFF)
81 led->blink = 0;
82 schedule_work(&led->work);
83 spin_unlock_irqrestore(&led->value_lock, flags);
84}
85
86static int wm831x_status_blink_set(struct led_classdev *led_cdev,
87 unsigned long *delay_on,
88 unsigned long *delay_off)
89{
90 struct wm831x_status *led = to_wm831x_status(led_cdev);
91 unsigned long flags;
92 int ret = 0;
93
94 /* Pick some defaults if we've not been given times */
95 if (*delay_on == 0 && *delay_off == 0) {
96 *delay_on = 250;
97 *delay_off = 250;
98 }
99
100 spin_lock_irqsave(&led->value_lock, flags);
101
102 /* We only have a limited selection of settings, see if we can
103 * support the configuration we're being given */
104 switch (*delay_on) {
105 case 1000:
106 led->blink_time = 0;
107 break;
108 case 250:
109 led->blink_time = 1;
110 break;
111 case 125:
112 led->blink_time = 2;
113 break;
114 case 62:
115 case 63:
116 /* Actually 62.5ms */
117 led->blink_time = 3;
118 break;
119 default:
120 ret = -EINVAL;
121 break;
122 }
123
124 if (ret == 0) {
125 switch (*delay_off / *delay_on) {
126 case 1:
127 led->blink_cyc = 0;
128 break;
129 case 3:
130 led->blink_cyc = 1;
131 break;
132 case 4:
133 led->blink_cyc = 2;
134 break;
135 case 8:
136 led->blink_cyc = 3;
137 break;
138 default:
139 ret = -EINVAL;
140 break;
141 }
142 }
143
144 if (ret == 0)
145 led->blink = 1;
146 else
147 led->blink = 0;
148
149 /* Always update; if we fail turn off blinking since we expect
150 * a software fallback. */
151 schedule_work(&led->work);
152
153 spin_unlock_irqrestore(&led->value_lock, flags);
154
155 return ret;
156}
157
158static const char *led_src_texts[] = {
159 "otp",
160 "power",
161 "charger",
162 "soft",
163};
164
165static ssize_t wm831x_status_src_show(struct device *dev,
166 struct device_attribute *attr, char *buf)
167{
168 struct led_classdev *led_cdev = dev_get_drvdata(dev);
169 struct wm831x_status *led = to_wm831x_status(led_cdev);
170 int i;
171 ssize_t ret = 0;
172
173 mutex_lock(&led->mutex);
174
175 for (i = 0; i < ARRAY_SIZE(led_src_texts); i++)
176 if (i == led->src)
177 ret += sprintf(&buf[ret], "[%s] ", led_src_texts[i]);
178 else
179 ret += sprintf(&buf[ret], "%s ", led_src_texts[i]);
180
181 mutex_unlock(&led->mutex);
182
183 ret += sprintf(&buf[ret], "\n");
184
185 return ret;
186}
187
188static ssize_t wm831x_status_src_store(struct device *dev,
189 struct device_attribute *attr,
190 const char *buf, size_t size)
191{
192 struct led_classdev *led_cdev = dev_get_drvdata(dev);
193 struct wm831x_status *led = to_wm831x_status(led_cdev);
194 char name[20];
195 int i;
196 size_t len;
197
198 name[sizeof(name) - 1] = '\0';
199 strncpy(name, buf, sizeof(name) - 1);
200 len = strlen(name);
201
202 if (len && name[len - 1] == '\n')
203 name[len - 1] = '\0';
204
205 for (i = 0; i < ARRAY_SIZE(led_src_texts); i++) {
206 if (!strcmp(name, led_src_texts[i])) {
207 mutex_lock(&led->mutex);
208
209 led->src = i;
210 schedule_work(&led->work);
211
212 mutex_unlock(&led->mutex);
213 }
214 }
215
216 return size;
217}
218
219static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store);
220
221static int wm831x_status_probe(struct platform_device *pdev)
222{
223 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
224 struct wm831x_pdata *chip_pdata;
225 struct wm831x_status_pdata pdata;
226 struct wm831x_status *drvdata;
227 struct resource *res;
228 int id = pdev->id % ARRAY_SIZE(chip_pdata->status);
229 int ret;
230
231 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
232 if (res == NULL) {
233 dev_err(&pdev->dev, "No I/O resource\n");
234 ret = -EINVAL;
235 goto err;
236 }
237
238 drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL);
239 if (!drvdata)
240 return -ENOMEM;
241 dev_set_drvdata(&pdev->dev, drvdata);
242
243 drvdata->wm831x = wm831x;
244 drvdata->reg = res->start;
245
246 if (wm831x->dev->platform_data)
247 chip_pdata = wm831x->dev->platform_data;
248 else
249 chip_pdata = NULL;
250
251 memset(&pdata, 0, sizeof(pdata));
252 if (chip_pdata && chip_pdata->status[id])
253 memcpy(&pdata, chip_pdata->status[id], sizeof(pdata));
254 else
255 pdata.name = dev_name(&pdev->dev);
256
257 mutex_init(&drvdata->mutex);
258 INIT_WORK(&drvdata->work, wm831x_status_work);
259 spin_lock_init(&drvdata->value_lock);
260
261 /* We cache the configuration register and read startup values
262 * from it. */
263 drvdata->reg_val = wm831x_reg_read(wm831x, drvdata->reg);
264
265 if (drvdata->reg_val & WM831X_LED_MODE_MASK)
266 drvdata->brightness = LED_FULL;
267 else
268 drvdata->brightness = LED_OFF;
269
270 /* Set a default source if configured, otherwise leave the
271 * current hardware setting.
272 */
273 if (pdata.default_src == WM831X_STATUS_PRESERVE) {
274 drvdata->src = drvdata->reg_val;
275 drvdata->src &= WM831X_LED_SRC_MASK;
276 drvdata->src >>= WM831X_LED_SRC_SHIFT;
277 } else {
278 drvdata->src = pdata.default_src - 1;
279 }
280
281 drvdata->cdev.name = pdata.name;
282 drvdata->cdev.default_trigger = pdata.default_trigger;
283 drvdata->cdev.brightness_set = wm831x_status_set;
284 drvdata->cdev.blink_set = wm831x_status_blink_set;
285
286 ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
287 if (ret < 0) {
288 dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
289 goto err_led;
290 }
291
292 ret = device_create_file(drvdata->cdev.dev, &dev_attr_src);
293 if (ret != 0)
294 dev_err(&pdev->dev,
295 "No source control for LED: %d\n", ret);
296
297 return 0;
298
299err_led:
300 led_classdev_unregister(&drvdata->cdev);
301 kfree(drvdata);
302err:
303 return ret;
304}
305
306static int wm831x_status_remove(struct platform_device *pdev)
307{
308 struct wm831x_status *drvdata = platform_get_drvdata(pdev);
309
310 device_remove_file(drvdata->cdev.dev, &dev_attr_src);
311 led_classdev_unregister(&drvdata->cdev);
312 kfree(drvdata);
313
314 return 0;
315}
316
317static struct platform_driver wm831x_status_driver = {
318 .driver = {
319 .name = "wm831x-status",
320 .owner = THIS_MODULE,
321 },
322 .probe = wm831x_status_probe,
323 .remove = wm831x_status_remove,
324};
325
326static int __devinit wm831x_status_init(void)
327{
328 return platform_driver_register(&wm831x_status_driver);
329}
330module_init(wm831x_status_init);
331
332static void wm831x_status_exit(void)
333{
334 platform_driver_unregister(&wm831x_status_driver);
335}
336module_exit(wm831x_status_exit);
337
338MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
339MODULE_DESCRIPTION("WM831x status LED driver");
340MODULE_LICENSE("GPL");
341MODULE_ALIAS("platform:wm831x-status");
diff --git a/drivers/leds/ledtrig-gpio.c b/drivers/leds/ledtrig-gpio.c
index 1bc5db4ece0d..f5913372d691 100644
--- a/drivers/leds/ledtrig-gpio.c
+++ b/drivers/leds/ledtrig-gpio.c
@@ -44,22 +44,22 @@ static void gpio_trig_work(struct work_struct *work)
44 struct gpio_trig_data, work); 44 struct gpio_trig_data, work);
45 int tmp; 45 int tmp;
46 46
47 if (!gpio_data->gpio) 47 if (!gpio_data->gpio)
48 return; 48 return;
49 49
50 tmp = gpio_get_value(gpio_data->gpio); 50 tmp = gpio_get_value(gpio_data->gpio);
51 if (gpio_data->inverted) 51 if (gpio_data->inverted)
52 tmp = !tmp; 52 tmp = !tmp;
53 53
54 if (tmp) { 54 if (tmp) {
55 if (gpio_data->desired_brightness) 55 if (gpio_data->desired_brightness)
56 led_set_brightness(gpio_data->led, 56 led_set_brightness(gpio_data->led,
57 gpio_data->desired_brightness); 57 gpio_data->desired_brightness);
58 else 58 else
59 led_set_brightness(gpio_data->led, LED_FULL); 59 led_set_brightness(gpio_data->led, LED_FULL);
60 } else { 60 } else {
61 led_set_brightness(gpio_data->led, LED_OFF); 61 led_set_brightness(gpio_data->led, LED_OFF);
62 } 62 }
63} 63}
64 64
65static ssize_t gpio_trig_brightness_show(struct device *dev, 65static ssize_t gpio_trig_brightness_show(struct device *dev,