3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
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.
9 * LED driver for the DAC124S085 SPI DAC
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>
21 struct dac124s085_led
{
22 struct led_classdev ldev
;
23 struct spi_device
*spi
;
26 char name
[sizeof("dac124s085-3")];
29 struct work_struct work
;
34 struct dac124s085_led leds
[4];
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)
42 static void dac124s085_led_work(struct work_struct
*work
)
44 struct dac124s085_led
*led
= container_of(work
, struct dac124s085_led
,
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
);
55 static void dac124s085_set_brightness(struct led_classdev
*ldev
,
56 enum led_brightness brightness
)
58 struct dac124s085_led
*led
= container_of(ldev
, struct dac124s085_led
,
61 spin_lock(&led
->lock
);
62 led
->brightness
= brightness
;
63 schedule_work(&led
->work
);
64 spin_unlock(&led
->lock
);
67 static int dac124s085_probe(struct spi_device
*spi
)
69 struct dac124s085
*dac
;
70 struct dac124s085_led
*led
;
73 dac
= kzalloc(sizeof(*dac
), GFP_KERNEL
);
77 spi
->bits_per_word
= 16;
79 for (i
= 0; i
< ARRAY_SIZE(dac
->leds
); i
++) {
82 led
->brightness
= LED_OFF
;
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
);
97 spi_set_drvdata(spi
, dac
);
103 led_classdev_unregister(&dac
->leds
[i
].ldev
);
105 spi_set_drvdata(spi
, NULL
);
110 static int dac124s085_remove(struct spi_device
*spi
)
112 struct dac124s085
*dac
= spi_get_drvdata(spi
);
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
);
120 spi_set_drvdata(spi
, NULL
);
126 static struct spi_driver dac124s085_driver
= {
127 .probe
= dac124s085_probe
,
128 .remove
= dac124s085_remove
,
130 .name
= "dac124s085",
131 .owner
= THIS_MODULE
,
135 static int __init
dac124s085_leds_init(void)
137 return spi_register_driver(&dac124s085_driver
);
140 static void __exit
dac124s085_leds_exit(void)
142 spi_unregister_driver(&dac124s085_driver
);
145 module_init(dac124s085_leds_init
);
146 module_exit(dac124s085_leds_exit
);
148 MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
149 MODULE_DESCRIPTION("DAC124S085 LED driver");
150 MODULE_LICENSE("GPL v2");