]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/iio/dac/ad5446.c
staging: iio: drop "select IIO_SIMPLE_DUMMY_EVGEN"
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / iio / dac / ad5446.c
CommitLineData
b5a49481
MH
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>
99c97852 19#include <linux/module.h>
b5a49481
MH
20
21#include "../iio.h"
22#include "../sysfs.h"
23#include "dac.h"
24
25#include "ad5446.h"
26
d846263d
MH
27static void ad5446_store_sample(struct ad5446_state *st, unsigned val)
28{
29 st->data.d16 = cpu_to_be16(AD5446_LOAD |
30 (val << st->chip_info->left_shift));
31}
32
33static void ad5542_store_sample(struct ad5446_state *st, unsigned val)
34{
35 st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift);
36}
37
38static void ad5620_store_sample(struct ad5446_state *st, unsigned val)
39{
40 st->data.d16 = cpu_to_be16(AD5620_LOAD |
41 (val << st->chip_info->left_shift));
42}
43
44static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
45{
46 val |= AD5660_LOAD;
47 st->data.d24[0] = (val >> 16) & 0xFF;
48 st->data.d24[1] = (val >> 8) & 0xFF;
49 st->data.d24[2] = val & 0xFF;
50}
51
bbed4dc7
MH
52static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode)
53{
54 st->data.d16 = cpu_to_be16(mode << 14);
55}
56
57static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
58{
59 unsigned val = mode << 16;
60
61 st->data.d24[0] = (val >> 16) & 0xFF;
62 st->data.d24[1] = (val >> 8) & 0xFF;
63 st->data.d24[2] = val & 0xFF;
64}
65
b5a49481
MH
66static ssize_t ad5446_write(struct device *dev,
67 struct device_attribute *attr,
68 const char *buf,
69 size_t len)
70{
638e59fc
JC
71 struct iio_dev *indio_dev = dev_get_drvdata(dev);
72 struct ad5446_state *st = iio_priv(indio_dev);
b5a49481
MH
73 int ret;
74 long val;
75
76 ret = strict_strtol(buf, 10, &val);
77 if (ret)
78 goto error_ret;
79
80 if (val > RES_MASK(st->chip_info->bits)) {
81 ret = -EINVAL;
82 goto error_ret;
83 }
84
638e59fc 85 mutex_lock(&indio_dev->mlock);
bbed4dc7 86 st->cached_val = val;
d846263d 87 st->chip_info->store_sample(st, val);
b5a49481 88 ret = spi_sync(st->spi, &st->msg);
638e59fc 89 mutex_unlock(&indio_dev->mlock);
b5a49481
MH
90
91error_ret:
92 return ret ? ret : len;
93}
94
95static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0);
96
97static ssize_t ad5446_show_scale(struct device *dev,
98 struct device_attribute *attr,
99 char *buf)
100{
638e59fc
JC
101 struct iio_dev *indio_dev = dev_get_drvdata(dev);
102 struct ad5446_state *st = iio_priv(indio_dev);
b5a49481
MH
103 /* Corresponds to Vref / 2^(bits) */
104 unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
105
41135b1c 106 return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
b5a49481 107}
322c9563 108static IIO_DEVICE_ATTR(out_voltage_scale, S_IRUGO, ad5446_show_scale, NULL, 0);
b5a49481 109
bbed4dc7
MH
110static ssize_t ad5446_write_powerdown_mode(struct device *dev,
111 struct device_attribute *attr,
112 const char *buf, size_t len)
113{
638e59fc
JC
114 struct iio_dev *indio_dev = dev_get_drvdata(dev);
115 struct ad5446_state *st = iio_priv(indio_dev);
bbed4dc7
MH
116
117 if (sysfs_streq(buf, "1kohm_to_gnd"))
118 st->pwr_down_mode = MODE_PWRDWN_1k;
119 else if (sysfs_streq(buf, "100kohm_to_gnd"))
120 st->pwr_down_mode = MODE_PWRDWN_100k;
121 else if (sysfs_streq(buf, "three_state"))
122 st->pwr_down_mode = MODE_PWRDWN_TRISTATE;
123 else
124 return -EINVAL;
125
126 return len;
127}
128
129static ssize_t ad5446_read_powerdown_mode(struct device *dev,
130 struct device_attribute *attr, char *buf)
131{
638e59fc
JC
132 struct iio_dev *indio_dev = dev_get_drvdata(dev);
133 struct ad5446_state *st = iio_priv(indio_dev);
bbed4dc7
MH
134
135 char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
136
137 return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
138}
139
140static ssize_t ad5446_read_dac_powerdown(struct device *dev,
141 struct device_attribute *attr,
142 char *buf)
143{
638e59fc
JC
144 struct iio_dev *indio_dev = dev_get_drvdata(dev);
145 struct ad5446_state *st = iio_priv(indio_dev);
bbed4dc7
MH
146
147 return sprintf(buf, "%d\n", st->pwr_down);
148}
149
150static ssize_t ad5446_write_dac_powerdown(struct device *dev,
151 struct device_attribute *attr,
152 const char *buf, size_t len)
153{
638e59fc
JC
154 struct iio_dev *indio_dev = dev_get_drvdata(dev);
155 struct ad5446_state *st = iio_priv(indio_dev);
bbed4dc7
MH
156 unsigned long readin;
157 int ret;
158
159 ret = strict_strtol(buf, 10, &readin);
160 if (ret)
161 return ret;
162
163 if (readin > 1)
164 ret = -EINVAL;
165
638e59fc 166 mutex_lock(&indio_dev->mlock);
bbed4dc7
MH
167 st->pwr_down = readin;
168
169 if (st->pwr_down)
170 st->chip_info->store_pwr_down(st, st->pwr_down_mode);
171 else
172 st->chip_info->store_sample(st, st->cached_val);
173
174 ret = spi_sync(st->spi, &st->msg);
638e59fc 175 mutex_unlock(&indio_dev->mlock);
bbed4dc7
MH
176
177 return ret ? ret : len;
178}
179
322c9563 180static IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO | S_IWUSR,
bbed4dc7
MH
181 ad5446_read_powerdown_mode,
182 ad5446_write_powerdown_mode, 0);
183
322c9563 184static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
bbed4dc7
MH
185 "1kohm_to_gnd 100kohm_to_gnd three_state");
186
322c9563 187static IIO_DEVICE_ATTR(out_voltage0_powerdown, S_IRUGO | S_IWUSR,
bbed4dc7
MH
188 ad5446_read_dac_powerdown,
189 ad5446_write_dac_powerdown, 0);
190
b5a49481 191static struct attribute *ad5446_attributes[] = {
322c9563
JC
192 &iio_dev_attr_out_voltage0_raw.dev_attr.attr,
193 &iio_dev_attr_out_voltage_scale.dev_attr.attr,
194 &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
195 &iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
196 &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
b5a49481
MH
197 NULL,
198};
199
bbed4dc7
MH
200static mode_t ad5446_attr_is_visible(struct kobject *kobj,
201 struct attribute *attr, int n)
202{
203 struct device *dev = container_of(kobj, struct device, kobj);
638e59fc
JC
204 struct iio_dev *indio_dev = dev_get_drvdata(dev);
205 struct ad5446_state *st = iio_priv(indio_dev);
bbed4dc7
MH
206
207 mode_t mode = attr->mode;
208
209 if (!st->chip_info->store_pwr_down &&
322c9563
JC
210 (attr == &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr ||
211 attr == &iio_dev_attr_out_voltage_powerdown_mode.
212 dev_attr.attr ||
bbed4dc7 213 attr ==
322c9563
JC
214 &iio_const_attr_out_voltage_powerdown_mode_available.
215 dev_attr.attr))
bbed4dc7
MH
216 mode = 0;
217
218 return mode;
219}
220
b5a49481
MH
221static const struct attribute_group ad5446_attribute_group = {
222 .attrs = ad5446_attributes,
bbed4dc7 223 .is_visible = ad5446_attr_is_visible,
b5a49481
MH
224};
225
226static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
227 [ID_AD5444] = {
228 .bits = 12,
229 .storagebits = 16,
230 .left_shift = 2,
d846263d 231 .store_sample = ad5446_store_sample,
b5a49481
MH
232 },
233 [ID_AD5446] = {
234 .bits = 14,
235 .storagebits = 16,
236 .left_shift = 0,
d846263d 237 .store_sample = ad5446_store_sample,
b5a49481 238 },
67d1c1f4
MH
239 [ID_AD5541A] = {
240 .bits = 16,
241 .storagebits = 16,
242 .left_shift = 0,
243 .store_sample = ad5542_store_sample,
244 },
b5a49481
MH
245 [ID_AD5542A] = {
246 .bits = 16,
247 .storagebits = 16,
248 .left_shift = 0,
d846263d 249 .store_sample = ad5542_store_sample,
b5a49481 250 },
0772268a
MH
251 [ID_AD5543] = {
252 .bits = 16,
253 .storagebits = 16,
254 .left_shift = 0,
255 .store_sample = ad5542_store_sample,
256 },
b5a49481
MH
257 [ID_AD5512A] = {
258 .bits = 12,
259 .storagebits = 16,
260 .left_shift = 4,
d846263d
MH
261 .store_sample = ad5542_store_sample,
262 },
0772268a
MH
263 [ID_AD5553] = {
264 .bits = 14,
265 .storagebits = 16,
266 .left_shift = 0,
267 .store_sample = ad5542_store_sample,
268 },
2b61535a
MH
269 [ID_AD5601] = {
270 .bits = 8,
271 .storagebits = 16,
272 .left_shift = 6,
273 .store_sample = ad5542_store_sample,
274 .store_pwr_down = ad5620_store_pwr_down,
275 },
276 [ID_AD5611] = {
277 .bits = 10,
278 .storagebits = 16,
279 .left_shift = 4,
280 .store_sample = ad5542_store_sample,
281 .store_pwr_down = ad5620_store_pwr_down,
282 },
283 [ID_AD5621] = {
284 .bits = 12,
285 .storagebits = 16,
286 .left_shift = 2,
287 .store_sample = ad5542_store_sample,
288 .store_pwr_down = ad5620_store_pwr_down,
289 },
d846263d
MH
290 [ID_AD5620_2500] = {
291 .bits = 12,
292 .storagebits = 16,
293 .left_shift = 2,
d846263d
MH
294 .int_vref_mv = 2500,
295 .store_sample = ad5620_store_sample,
bbed4dc7 296 .store_pwr_down = ad5620_store_pwr_down,
d846263d
MH
297 },
298 [ID_AD5620_1250] = {
299 .bits = 12,
300 .storagebits = 16,
301 .left_shift = 2,
d846263d
MH
302 .int_vref_mv = 1250,
303 .store_sample = ad5620_store_sample,
bbed4dc7 304 .store_pwr_down = ad5620_store_pwr_down,
d846263d
MH
305 },
306 [ID_AD5640_2500] = {
307 .bits = 14,
308 .storagebits = 16,
309 .left_shift = 0,
d846263d
MH
310 .int_vref_mv = 2500,
311 .store_sample = ad5620_store_sample,
bbed4dc7 312 .store_pwr_down = ad5620_store_pwr_down,
d846263d
MH
313 },
314 [ID_AD5640_1250] = {
315 .bits = 14,
316 .storagebits = 16,
317 .left_shift = 0,
d846263d
MH
318 .int_vref_mv = 1250,
319 .store_sample = ad5620_store_sample,
bbed4dc7 320 .store_pwr_down = ad5620_store_pwr_down,
d846263d
MH
321 },
322 [ID_AD5660_2500] = {
323 .bits = 16,
324 .storagebits = 24,
325 .left_shift = 0,
d846263d
MH
326 .int_vref_mv = 2500,
327 .store_sample = ad5660_store_sample,
bbed4dc7 328 .store_pwr_down = ad5660_store_pwr_down,
d846263d
MH
329 },
330 [ID_AD5660_1250] = {
331 .bits = 16,
332 .storagebits = 24,
333 .left_shift = 0,
d846263d
MH
334 .int_vref_mv = 1250,
335 .store_sample = ad5660_store_sample,
bbed4dc7 336 .store_pwr_down = ad5660_store_pwr_down,
b5a49481
MH
337 },
338};
339
6fe8135f
JC
340static const struct iio_info ad5446_info = {
341 .attrs = &ad5446_attribute_group,
342 .driver_module = THIS_MODULE,
343};
344
b5a49481
MH
345static int __devinit ad5446_probe(struct spi_device *spi)
346{
347 struct ad5446_state *st;
86729fc4
JC
348 struct iio_dev *indio_dev;
349 struct regulator *reg;
b5a49481
MH
350 int ret, voltage_uv = 0;
351
86729fc4
JC
352 reg = regulator_get(&spi->dev, "vcc");
353 if (!IS_ERR(reg)) {
354 ret = regulator_enable(reg);
b5a49481
MH
355 if (ret)
356 goto error_put_reg;
357
86729fc4 358 voltage_uv = regulator_get_voltage(reg);
b5a49481
MH
359 }
360
86729fc4
JC
361 indio_dev = iio_allocate_device(sizeof(*st));
362 if (indio_dev == NULL) {
363 ret = -ENOMEM;
364 goto error_disable_reg;
365 }
366 st = iio_priv(indio_dev);
b5a49481
MH
367 st->chip_info =
368 &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
369
86729fc4
JC
370 spi_set_drvdata(spi, indio_dev);
371 st->reg = reg;
b5a49481
MH
372 st->spi = spi;
373
b5a49481 374 /* Estabilish that the iio_dev is a child of the spi device */
86729fc4
JC
375 indio_dev->dev.parent = &spi->dev;
376 indio_dev->name = spi_get_device_id(spi)->name;
377 indio_dev->info = &ad5446_info;
378 indio_dev->modes = INDIO_DIRECT_MODE;
b5a49481
MH
379
380 /* Setup default message */
381
d846263d
MH
382 st->xfer.tx_buf = &st->data;
383 st->xfer.len = st->chip_info->storagebits / 8;
b5a49481
MH
384
385 spi_message_init(&st->msg);
386 spi_message_add_tail(&st->xfer, &st->msg);
387
d846263d 388 switch (spi_get_device_id(spi)->driver_data) {
bbed4dc7
MH
389 case ID_AD5620_2500:
390 case ID_AD5620_1250:
391 case ID_AD5640_2500:
392 case ID_AD5640_1250:
393 case ID_AD5660_2500:
394 case ID_AD5660_1250:
395 st->vref_mv = st->chip_info->int_vref_mv;
396 break;
397 default:
398 if (voltage_uv)
399 st->vref_mv = voltage_uv / 1000;
400 else
401 dev_warn(&spi->dev,
402 "reference voltage unspecified\n");
d846263d 403 }
b5a49481 404
86729fc4 405 ret = iio_device_register(indio_dev);
b5a49481
MH
406 if (ret)
407 goto error_free_device;
408
409 return 0;
410
411error_free_device:
86729fc4 412 iio_free_device(indio_dev);
b5a49481 413error_disable_reg:
86729fc4
JC
414 if (!IS_ERR(reg))
415 regulator_disable(reg);
b5a49481 416error_put_reg:
86729fc4
JC
417 if (!IS_ERR(reg))
418 regulator_put(reg);
419
b5a49481
MH
420 return ret;
421}
422
423static int ad5446_remove(struct spi_device *spi)
424{
86729fc4
JC
425 struct iio_dev *indio_dev = spi_get_drvdata(spi);
426 struct ad5446_state *st = iio_priv(indio_dev);
b5a49481
MH
427
428 iio_device_unregister(indio_dev);
d2fffd6c
JC
429 if (!IS_ERR(st->reg)) {
430 regulator_disable(st->reg);
431 regulator_put(st->reg);
b5a49481 432 }
d2fffd6c
JC
433 iio_free_device(indio_dev);
434
b5a49481
MH
435 return 0;
436}
437
438static const struct spi_device_id ad5446_id[] = {
439 {"ad5444", ID_AD5444},
440 {"ad5446", ID_AD5446},
b5a49481 441 {"ad5512a", ID_AD5512A},
67d1c1f4 442 {"ad5541a", ID_AD5541A},
bd51c0b0
MH
443 {"ad5542a", ID_AD5542A},
444 {"ad5543", ID_AD5543},
445 {"ad5553", ID_AD5553},
2b61535a
MH
446 {"ad5601", ID_AD5601},
447 {"ad5611", ID_AD5611},
448 {"ad5621", ID_AD5621},
d846263d
MH
449 {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
450 {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
451 {"ad5640-2500", ID_AD5640_2500},
452 {"ad5640-1250", ID_AD5640_1250},
453 {"ad5660-2500", ID_AD5660_2500},
454 {"ad5660-1250", ID_AD5660_1250},
b5a49481
MH
455 {}
456};
457
458static struct spi_driver ad5446_driver = {
459 .driver = {
460 .name = "ad5446",
461 .bus = &spi_bus_type,
462 .owner = THIS_MODULE,
463 },
464 .probe = ad5446_probe,
465 .remove = __devexit_p(ad5446_remove),
466 .id_table = ad5446_id,
467};
468
469static int __init ad5446_init(void)
470{
471 return spi_register_driver(&ad5446_driver);
472}
473module_init(ad5446_init);
474
475static void __exit ad5446_exit(void)
476{
477 spi_unregister_driver(&ad5446_driver);
478}
479module_exit(ad5446_exit);
480
481MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
482MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
483MODULE_LICENSE("GPL v2");
484MODULE_ALIAS("spi:ad5446");