aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/dac/ad5446.c
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-06-04 05:36:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-05 01:02:25 -0400
commitdbdc025bb239ce62c9b4d28c459a98f22ce9ec0a (patch)
tree2858c04b9d18852c1a4f4ca1c60c8e00b6180470 /drivers/iio/dac/ad5446.c
parent20374d1a36df3e20cd6742ba376684e5506254a8 (diff)
staging:iio: Move DAC drivers out of staging
The IIO DAC drivers are in a reasonably good shape. They all make use of channel spec and non of them provides non-documented sysfs attributes. Code style should be OK as well, both checkpatch and coccicheck only report trivial issues. So lets move the whole folder out of staging. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Acked-by: Jonathan Cameron <jic23@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/iio/dac/ad5446.c')
-rw-r--r--drivers/iio/dac/ad5446.c381
1 files changed, 381 insertions, 0 deletions
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
new file mode 100644
index 000000000000..49f557fc673b
--- /dev/null
+++ b/drivers/iio/dac/ad5446.c
@@ -0,0 +1,381 @@
1/*
2 * AD5446 SPI DAC driver
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/interrupt.h>
10#include <linux/workqueue.h>
11#include <linux/device.h>
12#include <linux/kernel.h>
13#include <linux/slab.h>
14#include <linux/sysfs.h>
15#include <linux/list.h>
16#include <linux/spi/spi.h>
17#include <linux/regulator/consumer.h>
18#include <linux/err.h>
19#include <linux/module.h>
20
21#include <linux/iio/iio.h>
22#include <linux/iio/sysfs.h>
23
24#include "ad5446.h"
25
26static int ad5446_write(struct ad5446_state *st, unsigned val)
27{
28 __be16 data = cpu_to_be16(val);
29 return spi_write(st->spi, &data, sizeof(data));
30}
31
32static int ad5660_write(struct ad5446_state *st, unsigned val)
33{
34 uint8_t data[3];
35
36 data[0] = (val >> 16) & 0xFF;
37 data[1] = (val >> 8) & 0xFF;
38 data[2] = val & 0xFF;
39
40 return spi_write(st->spi, data, sizeof(data));
41}
42
43static const char * const ad5446_powerdown_modes[] = {
44 "1kohm_to_gnd", "100kohm_to_gnd", "three_state"
45};
46
47static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev,
48 const struct iio_chan_spec *chan, unsigned int mode)
49{
50 struct ad5446_state *st = iio_priv(indio_dev);
51
52 st->pwr_down_mode = mode + 1;
53
54 return 0;
55}
56
57static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev,
58 const struct iio_chan_spec *chan)
59{
60 struct ad5446_state *st = iio_priv(indio_dev);
61
62 return st->pwr_down_mode - 1;
63}
64
65static const struct iio_enum ad5446_powerdown_mode_enum = {
66 .items = ad5446_powerdown_modes,
67 .num_items = ARRAY_SIZE(ad5446_powerdown_modes),
68 .get = ad5446_get_powerdown_mode,
69 .set = ad5446_set_powerdown_mode,
70};
71
72static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
73 uintptr_t private,
74 const struct iio_chan_spec *chan,
75 char *buf)
76{
77 struct ad5446_state *st = iio_priv(indio_dev);
78
79 return sprintf(buf, "%d\n", st->pwr_down);
80}
81
82static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
83 uintptr_t private,
84 const struct iio_chan_spec *chan,
85 const char *buf, size_t len)
86{
87 struct ad5446_state *st = iio_priv(indio_dev);
88 unsigned int shift;
89 unsigned int val;
90 bool powerdown;
91 int ret;
92
93 ret = strtobool(buf, &powerdown);
94 if (ret)
95 return ret;
96
97 mutex_lock(&indio_dev->mlock);
98 st->pwr_down = powerdown;
99
100 if (st->pwr_down) {
101 shift = chan->scan_type.realbits + chan->scan_type.shift;
102 val = st->pwr_down_mode << shift;
103 } else {
104 val = st->cached_val;
105 }
106
107 ret = st->chip_info->write(st, val);
108 mutex_unlock(&indio_dev->mlock);
109
110 return ret ? ret : len;
111}
112
113static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
114 {
115 .name = "powerdown",
116 .read = ad5446_read_dac_powerdown,
117 .write = ad5446_write_dac_powerdown,
118 },
119 IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum),
120 IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
121 { },
122};
123
124#define _AD5446_CHANNEL(bits, storage, shift, ext) { \
125 .type = IIO_VOLTAGE, \
126 .indexed = 1, \
127 .output = 1, \
128 .channel = 0, \
129 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
130 IIO_CHAN_INFO_SCALE_SHARED_BIT, \
131 .scan_type = IIO_ST('u', (bits), (storage), (shift)), \
132 .ext_info = (ext), \
133}
134
135#define AD5446_CHANNEL(bits, storage, shift) \
136 _AD5446_CHANNEL(bits, storage, shift, NULL)
137
138#define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
139 _AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown)
140
141static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
142 [ID_AD5444] = {
143 .channel = AD5446_CHANNEL(12, 16, 2),
144 .write = ad5446_write,
145 },
146 [ID_AD5446] = {
147 .channel = AD5446_CHANNEL(14, 16, 0),
148 .write = ad5446_write,
149 },
150 [ID_AD5541A] = {
151 .channel = AD5446_CHANNEL(16, 16, 0),
152 .write = ad5446_write,
153 },
154 [ID_AD5512A] = {
155 .channel = AD5446_CHANNEL(12, 16, 4),
156 .write = ad5446_write,
157 },
158 [ID_AD5553] = {
159 .channel = AD5446_CHANNEL(14, 16, 0),
160 .write = ad5446_write,
161 },
162 [ID_AD5601] = {
163 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
164 .write = ad5446_write,
165 },
166 [ID_AD5611] = {
167 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
168 .write = ad5446_write,
169 },
170 [ID_AD5621] = {
171 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
172 .write = ad5446_write,
173 },
174 [ID_AD5620_2500] = {
175 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
176 .int_vref_mv = 2500,
177 .write = ad5446_write,
178 },
179 [ID_AD5620_1250] = {
180 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
181 .int_vref_mv = 1250,
182 .write = ad5446_write,
183 },
184 [ID_AD5640_2500] = {
185 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
186 .int_vref_mv = 2500,
187 .write = ad5446_write,
188 },
189 [ID_AD5640_1250] = {
190 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
191 .int_vref_mv = 1250,
192 .write = ad5446_write,
193 },
194 [ID_AD5660_2500] = {
195 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
196 .int_vref_mv = 2500,
197 .write = ad5660_write,
198 },
199 [ID_AD5660_1250] = {
200 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
201 .int_vref_mv = 1250,
202 .write = ad5660_write,
203 },
204 [ID_AD5662] = {
205 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
206 .write = ad5660_write,
207 },
208};
209
210static int ad5446_read_raw(struct iio_dev *indio_dev,
211 struct iio_chan_spec const *chan,
212 int *val,
213 int *val2,
214 long m)
215{
216 struct ad5446_state *st = iio_priv(indio_dev);
217 unsigned long scale_uv;
218
219 switch (m) {
220 case IIO_CHAN_INFO_RAW:
221 *val = st->cached_val;
222 return IIO_VAL_INT;
223 case IIO_CHAN_INFO_SCALE:
224 scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
225 *val = scale_uv / 1000;
226 *val2 = (scale_uv % 1000) * 1000;
227 return IIO_VAL_INT_PLUS_MICRO;
228
229 }
230 return -EINVAL;
231}
232
233static int ad5446_write_raw(struct iio_dev *indio_dev,
234 struct iio_chan_spec const *chan,
235 int val,
236 int val2,
237 long mask)
238{
239 struct ad5446_state *st = iio_priv(indio_dev);
240 int ret = 0;
241
242 switch (mask) {
243 case IIO_CHAN_INFO_RAW:
244 if (val >= (1 << chan->scan_type.realbits) || val < 0)
245 return -EINVAL;
246
247 val <<= chan->scan_type.shift;
248 mutex_lock(&indio_dev->mlock);
249 st->cached_val = val;
250 if (!st->pwr_down)
251 ret = st->chip_info->write(st, val);
252 mutex_unlock(&indio_dev->mlock);
253 break;
254 default:
255 ret = -EINVAL;
256 }
257
258 return ret;
259}
260
261static const struct iio_info ad5446_info = {
262 .read_raw = ad5446_read_raw,
263 .write_raw = ad5446_write_raw,
264 .driver_module = THIS_MODULE,
265};
266
267static int __devinit ad5446_probe(struct spi_device *spi)
268{
269 struct ad5446_state *st;
270 struct iio_dev *indio_dev;
271 struct regulator *reg;
272 int ret, voltage_uv = 0;
273
274 reg = regulator_get(&spi->dev, "vcc");
275 if (!IS_ERR(reg)) {
276 ret = regulator_enable(reg);
277 if (ret)
278 goto error_put_reg;
279
280 voltage_uv = regulator_get_voltage(reg);
281 }
282
283 indio_dev = iio_device_alloc(sizeof(*st));
284 if (indio_dev == NULL) {
285 ret = -ENOMEM;
286 goto error_disable_reg;
287 }
288 st = iio_priv(indio_dev);
289 st->chip_info =
290 &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
291
292 spi_set_drvdata(spi, indio_dev);
293 st->reg = reg;
294 st->spi = spi;
295
296 /* Establish that the iio_dev is a child of the spi device */
297 indio_dev->dev.parent = &spi->dev;
298 indio_dev->name = spi_get_device_id(spi)->name;
299 indio_dev->info = &ad5446_info;
300 indio_dev->modes = INDIO_DIRECT_MODE;
301 indio_dev->channels = &st->chip_info->channel;
302 indio_dev->num_channels = 1;
303
304 st->pwr_down_mode = MODE_PWRDWN_1k;
305
306 if (st->chip_info->int_vref_mv)
307 st->vref_mv = st->chip_info->int_vref_mv;
308 else if (voltage_uv)
309 st->vref_mv = voltage_uv / 1000;
310 else
311 dev_warn(&spi->dev, "reference voltage unspecified\n");
312
313 ret = iio_device_register(indio_dev);
314 if (ret)
315 goto error_free_device;
316
317 return 0;
318
319error_free_device:
320 iio_device_free(indio_dev);
321error_disable_reg:
322 if (!IS_ERR(reg))
323 regulator_disable(reg);
324error_put_reg:
325 if (!IS_ERR(reg))
326 regulator_put(reg);
327
328 return ret;
329}
330
331static int ad5446_remove(struct spi_device *spi)
332{
333 struct iio_dev *indio_dev = spi_get_drvdata(spi);
334 struct ad5446_state *st = iio_priv(indio_dev);
335
336 iio_device_unregister(indio_dev);
337 if (!IS_ERR(st->reg)) {
338 regulator_disable(st->reg);
339 regulator_put(st->reg);
340 }
341 iio_device_free(indio_dev);
342
343 return 0;
344}
345
346static const struct spi_device_id ad5446_id[] = {
347 {"ad5444", ID_AD5444},
348 {"ad5446", ID_AD5446},
349 {"ad5512a", ID_AD5512A},
350 {"ad5541a", ID_AD5541A},
351 {"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
352 {"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */
353 {"ad5553", ID_AD5553},
354 {"ad5601", ID_AD5601},
355 {"ad5611", ID_AD5611},
356 {"ad5621", ID_AD5621},
357 {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
358 {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
359 {"ad5640-2500", ID_AD5640_2500},
360 {"ad5640-1250", ID_AD5640_1250},
361 {"ad5660-2500", ID_AD5660_2500},
362 {"ad5660-1250", ID_AD5660_1250},
363 {"ad5662", ID_AD5662},
364 {}
365};
366MODULE_DEVICE_TABLE(spi, ad5446_id);
367
368static struct spi_driver ad5446_driver = {
369 .driver = {
370 .name = "ad5446",
371 .owner = THIS_MODULE,
372 },
373 .probe = ad5446_probe,
374 .remove = __devexit_p(ad5446_remove),
375 .id_table = ad5446_id,
376};
377module_spi_driver(ad5446_driver);
378
379MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
380MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
381MODULE_LICENSE("GPL v2");