aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/leds-dac124s085.c150
3 files changed, 160 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 90d39e5803cd..16a94088beee 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -190,6 +190,13 @@ config LEDS_DA903X
190 This option enables support for on-chip LED drivers found 190 This option enables support for on-chip LED drivers found
191 on Dialog Semiconductor DA9030/DA9034 PMICs. 191 on Dialog Semiconductor DA9030/DA9034 PMICs.
192 192
193config LEDS_DAC124S085
194 tristate "LED Support for DAC124S085 SPI DAC"
195 depends on LEDS_CLASS && SPI
196 help
197 This option enables support for DAC124S085 SPI DAC from NatSemi,
198 which can be used to control up to four LEDs.
199
193comment "LED Triggers" 200comment "LED Triggers"
194 201
195config LEDS_TRIGGERS 202config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 9d76f0f160a4..4157e86b9747 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -25,6 +25,9 @@ obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
25obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o 25obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
26obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o 26obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
27 27
28# LED SPI Drivers
29obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
30
28# LED Triggers 31# LED Triggers
29obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 32obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
30obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o 33obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
new file mode 100644
index 000000000000..098d9aae7259
--- /dev/null
+++ b/drivers/leds/leds-dac124s085.c
@@ -0,0 +1,150 @@
1/*
2 * Copyright 2008
3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
4 *
5 * This file is subject to the terms and conditions of version 2 of
6 * the GNU General Public License. See the file COPYING in the main
7 * directory of this archive for more details.
8 *
9 * LED driver for the DAC124S085 SPI DAC
10 */
11
12#include <linux/gfp.h>
13#include <linux/leds.h>
14#include <linux/module.h>
15#include <linux/mutex.h>
16#include <linux/slab.h>
17#include <linux/spinlock.h>
18#include <linux/workqueue.h>
19#include <linux/spi/spi.h>
20
21struct dac124s085_led {
22 struct led_classdev ldev;
23 struct spi_device *spi;
24 int id;
25 int brightness;
26 char name[sizeof("dac124s085-3")];
27
28 struct mutex mutex;
29 struct work_struct work;
30 spinlock_t lock;
31};
32
33struct dac124s085 {
34 struct dac124s085_led leds[4];
35};
36
37#define REG_WRITE (0 << 12)
38#define REG_WRITE_UPDATE (1 << 12)
39#define ALL_WRITE_UPDATE (2 << 12)
40#define POWER_DOWN_OUTPUT (3 << 12)
41
42static void dac124s085_led_work(struct work_struct *work)
43{
44 struct dac124s085_led *led = container_of(work, struct dac124s085_led,
45 work);
46 u16 word;
47
48 mutex_lock(&led->mutex);
49 word = cpu_to_le16(((led->id) << 14) | REG_WRITE_UPDATE |
50 (led->brightness & 0xfff));
51 spi_write(led->spi, (const u8 *)&word, sizeof(word));
52 mutex_unlock(&led->mutex);
53}
54
55static void dac124s085_set_brightness(struct led_classdev *ldev,
56 enum led_brightness brightness)
57{
58 struct dac124s085_led *led = container_of(ldev, struct dac124s085_led,
59 ldev);
60
61 spin_lock(&led->lock);
62 led->brightness = brightness;
63 schedule_work(&led->work);
64 spin_unlock(&led->lock);
65}
66
67static int dac124s085_probe(struct spi_device *spi)
68{
69 struct dac124s085 *dac;
70 struct dac124s085_led *led;
71 int i, ret;
72
73 dac = kzalloc(sizeof(*dac), GFP_KERNEL);
74 if (!dac)
75 return -ENOMEM;
76
77 spi->bits_per_word = 16;
78
79 for (i = 0; i < ARRAY_SIZE(dac->leds); i++) {
80 led = dac->leds + i;
81 led->id = i;
82 led->brightness = LED_OFF;
83 led->spi = spi;
84 snprintf(led->name, sizeof(led->name), "dac124s085-%d", i);
85 spin_lock_init(&led->lock);
86 INIT_WORK(&led->work, dac124s085_led_work);
87 mutex_init(&led->mutex);
88 led->ldev.name = led->name;
89 led->ldev.brightness = LED_OFF;
90 led->ldev.max_brightness = 0xfff;
91 led->ldev.brightness_set = dac124s085_set_brightness;
92 ret = led_classdev_register(&spi->dev, &led->ldev);
93 if (ret < 0)
94 goto eledcr;
95 }
96
97 spi_set_drvdata(spi, dac);
98
99 return 0;
100
101eledcr:
102 while (i--)
103 led_classdev_unregister(&dac->leds[i].ldev);
104
105 spi_set_drvdata(spi, NULL);
106 kfree(dac);
107 return ret;
108}
109
110static int dac124s085_remove(struct spi_device *spi)
111{
112 struct dac124s085 *dac = spi_get_drvdata(spi);
113 int i;
114
115 for (i = 0; i < ARRAY_SIZE(dac->leds); i++) {
116 led_classdev_unregister(&dac->leds[i].ldev);
117 cancel_work_sync(&dac->leds[i].work);
118 }
119
120 spi_set_drvdata(spi, NULL);
121 kfree(dac);
122
123 return 0;
124}
125
126static struct spi_driver dac124s085_driver = {
127 .probe = dac124s085_probe,
128 .remove = dac124s085_remove,
129 .driver = {
130 .name = "dac124s085",
131 .owner = THIS_MODULE,
132 },
133};
134
135static int __init dac124s085_leds_init(void)
136{
137 return spi_register_driver(&dac124s085_driver);
138}
139
140static void __exit dac124s085_leds_exit(void)
141{
142 spi_unregister_driver(&dac124s085_driver);
143}
144
145module_init(dac124s085_leds_init);
146module_exit(dac124s085_leds_exit);
147
148MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
149MODULE_DESCRIPTION("DAC124S085 LED driver");
150MODULE_LICENSE("GPL v2");