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/leds.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/slab.h>
16 #include <linux/spinlock.h>
17 #include <linux/workqueue.h>
18 #include <linux/spi/spi.h>
20 struct dac124s085_led
{
21 struct led_classdev ldev
;
22 struct spi_device
*spi
;
25 char name
[sizeof("dac124s085-3")];
28 struct work_struct work
;
33 struct dac124s085_led leds
[4];
36 #define REG_WRITE (0 << 12)
37 #define REG_WRITE_UPDATE (1 << 12)
38 #define ALL_WRITE_UPDATE (2 << 12)
39 #define POWER_DOWN_OUTPUT (3 << 12)
41 static void dac124s085_led_work(struct work_struct
*work
)
43 struct dac124s085_led
*led
= container_of(work
, struct dac124s085_led
,
47 mutex_lock(&led
->mutex
);
48 word
= cpu_to_le16(((led
->id
) << 14) | REG_WRITE_UPDATE
|
49 (led
->brightness
& 0xfff));
50 spi_write(led
->spi
, (const u8
*)&word
, sizeof(word
));
51 mutex_unlock(&led
->mutex
);
54 static void dac124s085_set_brightness(struct led_classdev
*ldev
,
55 enum led_brightness brightness
)
57 struct dac124s085_led
*led
= container_of(ldev
, struct dac124s085_led
,
60 spin_lock(&led
->lock
);
61 led
->brightness
= brightness
;
62 schedule_work(&led
->work
);
63 spin_unlock(&led
->lock
);
66 static int dac124s085_probe(struct spi_device
*spi
)
68 struct dac124s085
*dac
;
69 struct dac124s085_led
*led
;
72 dac
= kzalloc(sizeof(*dac
), GFP_KERNEL
);
76 spi
->bits_per_word
= 16;
78 for (i
= 0; i
< ARRAY_SIZE(dac
->leds
); i
++) {
81 led
->brightness
= LED_OFF
;
83 snprintf(led
->name
, sizeof(led
->name
), "dac124s085-%d", i
);
84 spin_lock_init(&led
->lock
);
85 INIT_WORK(&led
->work
, dac124s085_led_work
);
86 mutex_init(&led
->mutex
);
87 led
->ldev
.name
= led
->name
;
88 led
->ldev
.brightness
= LED_OFF
;
89 led
->ldev
.max_brightness
= 0xfff;
90 led
->ldev
.brightness_set
= dac124s085_set_brightness
;
91 ret
= led_classdev_register(&spi
->dev
, &led
->ldev
);
96 spi_set_drvdata(spi
, dac
);
102 led_classdev_unregister(&dac
->leds
[i
].ldev
);
104 spi_set_drvdata(spi
, NULL
);
109 static int dac124s085_remove(struct spi_device
*spi
)
111 struct dac124s085
*dac
= spi_get_drvdata(spi
);
114 for (i
= 0; i
< ARRAY_SIZE(dac
->leds
); i
++) {
115 led_classdev_unregister(&dac
->leds
[i
].ldev
);
116 cancel_work_sync(&dac
->leds
[i
].work
);
119 spi_set_drvdata(spi
, NULL
);
125 static struct spi_driver dac124s085_driver
= {
126 .probe
= dac124s085_probe
,
127 .remove
= dac124s085_remove
,
129 .name
= "dac124s085",
130 .owner
= THIS_MODULE
,
134 static int __init
dac124s085_leds_init(void)
136 return spi_register_driver(&dac124s085_driver
);
139 static void __exit
dac124s085_leds_exit(void)
141 spi_unregister_driver(&dac124s085_driver
);
144 module_init(dac124s085_leds_init
);
145 module_exit(dac124s085_leds_exit
);
147 MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
148 MODULE_DESCRIPTION("DAC124S085 LED driver");
149 MODULE_LICENSE("GPL v2");
150 MODULE_ALIAS("spi:dac124s085");