History

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

Linus Torvalds committed 17 years ago

Commit cce1d9f2 parents d910fc7 f16a5db11 files · +414 −31Browse files

Unified · Split

11 files
  1. drivers/leds/Kconfig +10 −3
  2. drivers/leds/Makefile +1 −0
  3. drivers/leds/leds-clevo-mail.c +1 −1
  4. drivers/leds/leds-cobalt-qube.c +1 −1
  5. drivers/leds/leds-cobalt-raq.c +2 −2
  6. drivers/leds/leds-gpio.c +1 −1
  7. drivers/leds/leds-pca9532.c +6 −6
  8. drivers/leds/leds-wm831x-status.c +341 −0
  9. drivers/leds/ledtrig-gpio.c +16 −16
  10. drivers/macintosh/via-pmu-led.c +1 −1
  11. include/linux/mfd/wm831x/status.h +34 −0
drivers/leds/Kconfig+10−3
@@ -150,9 +150,9 @@ config LEDS_LP3944 · 149 unmodified lines
150150 tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
151151 depends on LEDS_CLASS && I2C
152152 help
153− This option enables support for LEDs connected to the National
154− Semiconductor LP3944 Lighting Management Unit (LMU) also known as
155− Fun Light Chip.
153+ This option enables support for LEDs connected to the National
154+ Semiconductor LP3944 Lighting Management Unit (LMU) also known as
155+ Fun Light Chip.
156156
157157 To compile this driver as a module, choose M here: the
158158 module will be called leds-lp3944.
@@ -195,6 +195,13 @@ config LEDS_PCA955X · 36 unmodified lines
195195 LED driver chips accessed via the I2C bus. Supported
196196 devices include PCA9550, PCA9551, PCA9552, and PCA9553.
197197
198+config 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+
198205 config LEDS_WM8350
199206 tristate "LED Support for WM8350 AudioPlus PMIC"
200207 depends on LEDS_CLASS && MFD_WM8350
drivers/leds/Makefile+1−0
@@ -26,6 +26,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o · 25 unmodified lines
2626 obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
2727 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
2828 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
29+obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
2930 obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
3031 obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
3132
drivers/leds/leds-clevo-mail.c+1−1
@@ -153,7 +153,7 @@ static struct led_classdev clevo_mail_led = { · 152 unmodified lines
153153 .flags = LED_CORE_SUSPENDRESUME,
154154 };
155155
156−static int __init clevo_mail_led_probe(struct platform_device *pdev)
156+static int __devinit clevo_mail_led_probe(struct platform_device *pdev)
157157 {
158158 return led_classdev_register(&pdev->dev, &clevo_mail_led);
159159 }
drivers/leds/leds-cobalt-qube.c+1−1
@@ -28,7 +28,7 @@ static void qube_front_led_set(struct led_classdev *led_cdev, · 27 unmodified lines
2828 }
2929
3030 static struct led_classdev qube_front_led = {
31− .name = "qube-front",
31+ .name = "qube::front",
3232 .brightness = LED_FULL,
3333 .brightness_set = qube_front_led_set,
3434 .default_trigger = "ide-disk",
drivers/leds/leds-cobalt-raq.c+2−2
@@ -49,7 +49,7 @@ static void raq_web_led_set(struct led_classdev *led_cdev, · 48 unmodified lines
4949 }
5050
5151 static struct led_classdev raq_web_led = {
52− .name = "raq-web",
52+ .name = "raq::web",
5353 .brightness_set = raq_web_led_set,
5454 };
5555
@@ -70,7 +70,7 @@ static void raq_power_off_led_set(struct led_classdev *led_cdev, · 14 unmodified lines
7070 }
7171
7272 static struct led_classdev raq_power_off_led = {
73− .name = "raq-power-off",
73+ .name = "raq::power-off",
7474 .brightness_set = raq_power_off_led_set,
7575 .default_trigger = "power-off",
7676 };
drivers/leds/leds-gpio.c+1−1
@@ -80,7 +80,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, · 79 unmodified lines
8080
8181 /* skip leds that aren't available */
8282 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",
8484 template->gpio, template->name);
8585 return 0;
8686 }
drivers/leds/leds-pca9532.c+6−6
@@ -34,7 +34,7 @@ struct pca9532_data { · 33 unmodified lines
3434 struct i2c_client *client;
3535 struct pca9532_led leds[16];
3636 struct mutex update_lock;
37− struct input_dev *idev;
37+ struct input_dev *idev;
3838 struct work_struct work;
3939 u8 pwm[2];
4040 u8 psc[2];
@@ -53,9 +53,9 @@ MODULE_DEVICE_TABLE(i2c, pca9532_id); · 12 unmodified lines
5353
5454 static struct i2c_driver pca9532_driver = {
5555 .driver = {
56− .name = "pca9532",
56+ .name = "pca9532",
5757 },
58− .probe = pca9532_probe,
58+ .probe = pca9532_probe,
5959 .remove = pca9532_remove,
6060 .id_table = pca9532_id,
6161 };
@@ -149,7 +149,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, · 87 unmodified lines
149149
150150 if (*delay_on == 0 && *delay_off == 0) {
151151 /* led subsystem ask us for a blink rate */
152− *delay_on = 1000;
152+ *delay_on = 1000;
153153 *delay_off = 1000;
154154 }
155155 if (*delay_on != *delay_off || *delay_on > 1690 || *delay_on < 6)
@@ -227,7 +227,7 @@ static int pca9532_configure(struct i2c_client *client, · 71 unmodified lines
227227 break;
228228 case PCA9532_TYPE_LED:
229229 led->state = pled->state;
230− led->name = pled->name;
230+ led->name = pled->name;
231231 led->ldev.name = led->name;
232232 led->ldev.brightness = LED_OFF;
233233 led->ldev.brightness_set = pca9532_set_brightness;
@@ -254,7 +254,7 @@ static int pca9532_configure(struct i2c_client *client, · 20 unmodified lines
254254 data->idev->name = pled->name;
255255 data->idev->phys = "i2c/pca9532";
256256 data->idev->id.bustype = BUS_HOST;
257− data->idev->id.vendor = 0x001f;
257+ data->idev->id.vendor = 0x001f;
258258 data->idev->id.product = 0x0001;
259259 data->idev->id.version = 0x0100;
260260 data->idev->evbit[0] = BIT_MASK(EV_SND);
drivers/leds/leds-wm831x-status.c+341−0
@@ -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+
22+struct 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+
42+static 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+
72+static 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+
86+static 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+
158+static const char *led_src_texts[] = {
159+ "otp",
160+ "power",
161+ "charger",
162+ "soft",
163+};
164+
165+static 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+
188+static 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+
219+static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store);
220+
221+static 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+
299+err_led:
300+ led_classdev_unregister(&drvdata->cdev);
301+ kfree(drvdata);
302+err:
303+ return ret;
304+}
305+
306+static 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+
317+static 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+
326+static int __devinit wm831x_status_init(void)
327+{
328+ return platform_driver_register(&wm831x_status_driver);
329+}
330+module_init(wm831x_status_init);
331+
332+static void wm831x_status_exit(void)
333+{
334+ platform_driver_unregister(&wm831x_status_driver);
335+}
336+module_exit(wm831x_status_exit);
337+
338+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
339+MODULE_DESCRIPTION("WM831x status LED driver");
340+MODULE_LICENSE("GPL");
341+MODULE_ALIAS("platform:wm831x-status");
drivers/leds/ledtrig-gpio.c+16−16
@@ -44,22 +44,22 @@ static void gpio_trig_work(struct work_struct *work) · 43 unmodified lines
4444 struct gpio_trig_data, work);
4545 int tmp;
4646
47− if (!gpio_data->gpio)
48− return;
49−
50− tmp = gpio_get_value(gpio_data->gpio);
51− if (gpio_data->inverted)
52− tmp = !tmp;
53−
54− if (tmp) {
55− if (gpio_data->desired_brightness)
56− led_set_brightness(gpio_data->led,
57− gpio_data->desired_brightness);
58− else
59− led_set_brightness(gpio_data->led, LED_FULL);
60− } else {
61− led_set_brightness(gpio_data->led, LED_OFF);
62− }
47+ if (!gpio_data->gpio)
48+ return;
49+
50+ tmp = gpio_get_value(gpio_data->gpio);
51+ if (gpio_data->inverted)
52+ tmp = !tmp;
53+
54+ if (tmp) {
55+ if (gpio_data->desired_brightness)
56+ led_set_brightness(gpio_data->led,
57+ gpio_data->desired_brightness);
58+ else
59+ led_set_brightness(gpio_data->led, LED_FULL);
60+ } else {
61+ led_set_brightness(gpio_data->led, LED_OFF);
62+ }
6363 }
6464
6565 static ssize_t gpio_trig_brightness_show(struct device *dev,
drivers/macintosh/via-pmu-led.c+1−1
@@ -72,7 +72,7 @@ static void pmu_led_set(struct led_classdev *led_cdev, · 71 unmodified lines
7272 }
7373
7474 static struct led_classdev pmu_led = {
75− .name = "pmu-front-led",
75+ .name = "pmu-led::front",
7676 #ifdef CONFIG_ADB_PMU_LED_IDE
7777 .default_trigger = "ide-disk",
7878 #endif
include/linux/mfd/wm831x/status.h+34−0
@@ -0,0 +1,34 @@
1+/*
2+ * include/linux/mfd/wm831x/status.h -- Status LEDs for WM831x
3+ *
4+ * Copyright 2009 Wolfson Microelectronics PLC.
5+ *
6+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7+ *
8+ * This program is free software; you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License as published by the
10+ * Free Software Foundation; either version 2 of the License, or (at your
11+ * option) any later version.
12+ *
13+ */
14+
15+#ifndef __MFD_WM831X_STATUS_H__
16+#define __MFD_WM831X_STATUS_H__
17+
18+#define WM831X_LED_SRC_MASK 0xC000 /* LED_SRC - [15:14] */
19+#define WM831X_LED_SRC_SHIFT 14 /* LED_SRC - [15:14] */
20+#define WM831X_LED_SRC_WIDTH 2 /* LED_SRC - [15:14] */
21+#define WM831X_LED_MODE_MASK 0x0300 /* LED_MODE - [9:8] */
22+#define WM831X_LED_MODE_SHIFT 8 /* LED_MODE - [9:8] */
23+#define WM831X_LED_MODE_WIDTH 2 /* LED_MODE - [9:8] */
24+#define WM831X_LED_SEQ_LEN_MASK 0x0030 /* LED_SEQ_LEN - [5:4] */
25+#define WM831X_LED_SEQ_LEN_SHIFT 4 /* LED_SEQ_LEN - [5:4] */
26+#define WM831X_LED_SEQ_LEN_WIDTH 2 /* LED_SEQ_LEN - [5:4] */
27+#define WM831X_LED_DUR_MASK 0x000C /* LED_DUR - [3:2] */
28+#define WM831X_LED_DUR_SHIFT 2 /* LED_DUR - [3:2] */
29+#define WM831X_LED_DUR_WIDTH 2 /* LED_DUR - [3:2] */
30+#define WM831X_LED_DUTY_CYC_MASK 0x0003 /* LED_DUTY_CYC - [1:0] */
31+#define WM831X_LED_DUTY_CYC_SHIFT 0 /* LED_DUTY_CYC - [1:0] */
32+#define WM831X_LED_DUTY_CYC_WIDTH 2 /* LED_DUTY_CYC - [1:0] */
33+
34+#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t