diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/iio/dac/Kconfig | 5 | ||||
-rw-r--r-- | drivers/staging/iio/dac/ad5064.c | 122 |
2 files changed, 107 insertions, 20 deletions
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig index 66b2504a1ed..ab8516d76bc 100644 --- a/drivers/staging/iio/dac/Kconfig +++ b/drivers/staging/iio/dac/Kconfig | |||
@@ -4,11 +4,12 @@ | |||
4 | menu "Digital to analog converters" | 4 | menu "Digital to analog converters" |
5 | 5 | ||
6 | config AD5064 | 6 | config AD5064 |
7 | tristate "Analog Devices AD5064/64-1/65/44/45/24/25 DAC driver" | 7 | tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/68 DAC driver" |
8 | depends on SPI | 8 | depends on SPI |
9 | help | 9 | help |
10 | Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, | 10 | Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, |
11 | AD5045, AD5064, AD5064-1, AD5065 Digital to Analog Converter. | 11 | AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5668 Digital to Analog |
12 | Converter. | ||
12 | 13 | ||
13 | To compile this driver as a module, choose M here: the | 14 | To compile this driver as a module, choose M here: the |
14 | module will be called ad5064. | 15 | module will be called ad5064. |
diff --git a/drivers/staging/iio/dac/ad5064.c b/drivers/staging/iio/dac/ad5064.c index 865e81fc2da..6dab0645aa6 100644 --- a/drivers/staging/iio/dac/ad5064.c +++ b/drivers/staging/iio/dac/ad5064.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1 Digital to analog converters | 2 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, |
3 | * driver | 3 | * AD5668 Digital to analog converters driver |
4 | * | 4 | * |
5 | * Copyright 2011 Analog Devices Inc. | 5 | * Copyright 2011 Analog Devices Inc. |
6 | * | 6 | * |
@@ -20,7 +20,7 @@ | |||
20 | #include "../sysfs.h" | 20 | #include "../sysfs.h" |
21 | #include "dac.h" | 21 | #include "dac.h" |
22 | 22 | ||
23 | #define AD5064_MAX_DAC_CHANNELS 4 | 23 | #define AD5064_MAX_DAC_CHANNELS 8 |
24 | #define AD5064_MAX_VREFS 4 | 24 | #define AD5064_MAX_VREFS 4 |
25 | 25 | ||
26 | #define AD5064_ADDR(x) ((x) << 20) | 26 | #define AD5064_ADDR(x) ((x) << 20) |
@@ -37,7 +37,10 @@ | |||
37 | #define AD5064_CMD_CLEAR 0x5 | 37 | #define AD5064_CMD_CLEAR 0x5 |
38 | #define AD5064_CMD_LDAC_MASK 0x6 | 38 | #define AD5064_CMD_LDAC_MASK 0x6 |
39 | #define AD5064_CMD_RESET 0x7 | 39 | #define AD5064_CMD_RESET 0x7 |
40 | #define AD5064_CMD_DAISY_CHAIN_ENABLE 0x8 | 40 | #define AD5064_CMD_CONFIG 0x8 |
41 | |||
42 | #define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) | ||
43 | #define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) | ||
41 | 44 | ||
42 | #define AD5064_LDAC_PWRDN_NONE 0x0 | 45 | #define AD5064_LDAC_PWRDN_NONE 0x0 |
43 | #define AD5064_LDAC_PWRDN_1K 0x1 | 46 | #define AD5064_LDAC_PWRDN_1K 0x1 |
@@ -47,12 +50,15 @@ | |||
47 | /** | 50 | /** |
48 | * struct ad5064_chip_info - chip specific information | 51 | * struct ad5064_chip_info - chip specific information |
49 | * @shared_vref: whether the vref supply is shared between channels | 52 | * @shared_vref: whether the vref supply is shared between channels |
53 | * @internal_vref: internal reference voltage. 0 if the chip has no internal | ||
54 | * vref. | ||
50 | * @channel: channel specification | 55 | * @channel: channel specification |
51 | * @num_channels: number of channels | 56 | * @num_channels: number of channels |
52 | */ | 57 | */ |
53 | 58 | ||
54 | struct ad5064_chip_info { | 59 | struct ad5064_chip_info { |
55 | bool shared_vref; | 60 | bool shared_vref; |
61 | unsigned long internal_vref; | ||
56 | const struct iio_chan_spec *channels; | 62 | const struct iio_chan_spec *channels; |
57 | unsigned int num_channels; | 63 | unsigned int num_channels; |
58 | }; | 64 | }; |
@@ -65,6 +71,8 @@ struct ad5064_chip_info { | |||
65 | * @pwr_down: whether channel is powered down | 71 | * @pwr_down: whether channel is powered down |
66 | * @pwr_down_mode: channel's current power down mode | 72 | * @pwr_down_mode: channel's current power down mode |
67 | * @dac_cache: current DAC raw value (chip does not support readback) | 73 | * @dac_cache: current DAC raw value (chip does not support readback) |
74 | * @use_internal_vref: set to true if the internal reference voltage should be | ||
75 | * used. | ||
68 | * @data: spi transfer buffers | 76 | * @data: spi transfer buffers |
69 | */ | 77 | */ |
70 | 78 | ||
@@ -75,6 +83,7 @@ struct ad5064_state { | |||
75 | bool pwr_down[AD5064_MAX_DAC_CHANNELS]; | 83 | bool pwr_down[AD5064_MAX_DAC_CHANNELS]; |
76 | u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; | 84 | u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; |
77 | unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; | 85 | unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; |
86 | bool use_internal_vref; | ||
78 | 87 | ||
79 | /* | 88 | /* |
80 | * DMA (thus cache coherency maintenance) requires the | 89 | * DMA (thus cache coherency maintenance) requires the |
@@ -91,6 +100,12 @@ enum ad5064_type { | |||
91 | ID_AD5064, | 100 | ID_AD5064, |
92 | ID_AD5064_1, | 101 | ID_AD5064_1, |
93 | ID_AD5065, | 102 | ID_AD5065, |
103 | ID_AD5628_1, | ||
104 | ID_AD5628_2, | ||
105 | ID_AD5648_1, | ||
106 | ID_AD5648_2, | ||
107 | ID_AD5668_1, | ||
108 | ID_AD5668_2, | ||
94 | }; | 109 | }; |
95 | 110 | ||
96 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, | 111 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, |
@@ -196,6 +211,18 @@ static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, | |||
196 | return ret ? ret : len; | 211 | return ret ? ret : len; |
197 | } | 212 | } |
198 | 213 | ||
214 | static int ad5064_get_vref(struct ad5064_state *st, | ||
215 | struct iio_chan_spec const *chan) | ||
216 | { | ||
217 | unsigned int i; | ||
218 | |||
219 | if (st->use_internal_vref) | ||
220 | return st->chip_info->internal_vref; | ||
221 | |||
222 | i = st->chip_info->shared_vref ? 0 : chan->channel; | ||
223 | return regulator_get_voltage(st->vref_reg[i].consumer); | ||
224 | } | ||
225 | |||
199 | static int ad5064_read_raw(struct iio_dev *indio_dev, | 226 | static int ad5064_read_raw(struct iio_dev *indio_dev, |
200 | struct iio_chan_spec const *chan, | 227 | struct iio_chan_spec const *chan, |
201 | int *val, | 228 | int *val, |
@@ -203,7 +230,6 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, | |||
203 | long m) | 230 | long m) |
204 | { | 231 | { |
205 | struct ad5064_state *st = iio_priv(indio_dev); | 232 | struct ad5064_state *st = iio_priv(indio_dev); |
206 | unsigned int vref; | ||
207 | int scale_uv; | 233 | int scale_uv; |
208 | 234 | ||
209 | switch (m) { | 235 | switch (m) { |
@@ -211,8 +237,7 @@ static int ad5064_read_raw(struct iio_dev *indio_dev, | |||
211 | *val = st->dac_cache[chan->channel]; | 237 | *val = st->dac_cache[chan->channel]; |
212 | return IIO_VAL_INT; | 238 | return IIO_VAL_INT; |
213 | case IIO_CHAN_INFO_SCALE: | 239 | case IIO_CHAN_INFO_SCALE: |
214 | vref = st->chip_info->shared_vref ? 0 : chan->channel; | 240 | scale_uv = ad5064_get_vref(st, chan); |
215 | scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer); | ||
216 | if (scale_uv < 0) | 241 | if (scale_uv < 0) |
217 | return scale_uv; | 242 | return scale_uv; |
218 | 243 | ||
@@ -293,6 +318,10 @@ const struct iio_chan_spec name[] = { \ | |||
293 | AD5064_CHANNEL(1, bits), \ | 318 | AD5064_CHANNEL(1, bits), \ |
294 | AD5064_CHANNEL(2, bits), \ | 319 | AD5064_CHANNEL(2, bits), \ |
295 | AD5064_CHANNEL(3, bits), \ | 320 | AD5064_CHANNEL(3, bits), \ |
321 | AD5064_CHANNEL(4, bits), \ | ||
322 | AD5064_CHANNEL(5, bits), \ | ||
323 | AD5064_CHANNEL(6, bits), \ | ||
324 | AD5064_CHANNEL(7, bits), \ | ||
296 | } | 325 | } |
297 | 326 | ||
298 | static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); | 327 | static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); |
@@ -335,6 +364,42 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | |||
335 | .channels = ad5064_channels, | 364 | .channels = ad5064_channels, |
336 | .num_channels = 2, | 365 | .num_channels = 2, |
337 | }, | 366 | }, |
367 | [ID_AD5628_1] = { | ||
368 | .shared_vref = true, | ||
369 | .internal_vref = 2500000, | ||
370 | .channels = ad5024_channels, | ||
371 | .num_channels = 8, | ||
372 | }, | ||
373 | [ID_AD5628_2] = { | ||
374 | .shared_vref = true, | ||
375 | .internal_vref = 5000000, | ||
376 | .channels = ad5024_channels, | ||
377 | .num_channels = 8, | ||
378 | }, | ||
379 | [ID_AD5648_1] = { | ||
380 | .shared_vref = true, | ||
381 | .internal_vref = 2500000, | ||
382 | .channels = ad5044_channels, | ||
383 | .num_channels = 8, | ||
384 | }, | ||
385 | [ID_AD5648_2] = { | ||
386 | .shared_vref = true, | ||
387 | .internal_vref = 5000000, | ||
388 | .channels = ad5044_channels, | ||
389 | .num_channels = 8, | ||
390 | }, | ||
391 | [ID_AD5668_1] = { | ||
392 | .shared_vref = true, | ||
393 | .internal_vref = 2500000, | ||
394 | .channels = ad5064_channels, | ||
395 | .num_channels = 8, | ||
396 | }, | ||
397 | [ID_AD5668_2] = { | ||
398 | .shared_vref = true, | ||
399 | .internal_vref = 5000000, | ||
400 | .channels = ad5064_channels, | ||
401 | .num_channels = 8, | ||
402 | }, | ||
338 | }; | 403 | }; |
339 | 404 | ||
340 | static inline unsigned int ad5064_num_vref(struct ad5064_state *st) | 405 | static inline unsigned int ad5064_num_vref(struct ad5064_state *st) |
@@ -378,12 +443,22 @@ static int __devinit ad5064_probe(struct spi_device *spi) | |||
378 | 443 | ||
379 | ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), | 444 | ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), |
380 | st->vref_reg); | 445 | st->vref_reg); |
381 | if (ret) | 446 | if (ret) { |
382 | goto error_free; | 447 | if (!st->chip_info->internal_vref) |
383 | 448 | goto error_free; | |
384 | ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); | 449 | st->use_internal_vref = true; |
385 | if (ret) | 450 | ret = ad5064_spi_write(st, AD5064_CMD_CONFIG, 0, |
386 | goto error_free_reg; | 451 | AD5064_CONFIG_INT_VREF_ENABLE, 0); |
452 | if (ret) { | ||
453 | dev_err(&spi->dev, "Failed to enable internal vref: %d\n", | ||
454 | ret); | ||
455 | goto error_free; | ||
456 | } | ||
457 | } else { | ||
458 | ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); | ||
459 | if (ret) | ||
460 | goto error_free_reg; | ||
461 | } | ||
387 | 462 | ||
388 | for (i = 0; i < st->chip_info->num_channels; ++i) { | 463 | for (i = 0; i < st->chip_info->num_channels; ++i) { |
389 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; | 464 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; |
@@ -404,9 +479,11 @@ static int __devinit ad5064_probe(struct spi_device *spi) | |||
404 | return 0; | 479 | return 0; |
405 | 480 | ||
406 | error_disable_reg: | 481 | error_disable_reg: |
407 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | 482 | if (!st->use_internal_vref) |
483 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | ||
408 | error_free_reg: | 484 | error_free_reg: |
409 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | 485 | if (!st->use_internal_vref) |
486 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | ||
410 | error_free: | 487 | error_free: |
411 | iio_free_device(indio_dev); | 488 | iio_free_device(indio_dev); |
412 | 489 | ||
@@ -421,8 +498,10 @@ static int __devexit ad5064_remove(struct spi_device *spi) | |||
421 | 498 | ||
422 | iio_device_unregister(indio_dev); | 499 | iio_device_unregister(indio_dev); |
423 | 500 | ||
424 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | 501 | if (!st->use_internal_vref) { |
425 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | 502 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); |
503 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | ||
504 | } | ||
426 | 505 | ||
427 | iio_free_device(indio_dev); | 506 | iio_free_device(indio_dev); |
428 | 507 | ||
@@ -437,6 +516,13 @@ static const struct spi_device_id ad5064_id[] = { | |||
437 | {"ad5064", ID_AD5064}, | 516 | {"ad5064", ID_AD5064}, |
438 | {"ad5064-1", ID_AD5064_1}, | 517 | {"ad5064-1", ID_AD5064_1}, |
439 | {"ad5065", ID_AD5065}, | 518 | {"ad5065", ID_AD5065}, |
519 | {"ad5628-1", ID_AD5628_1}, | ||
520 | {"ad5628-2", ID_AD5628_2}, | ||
521 | {"ad5648-1", ID_AD5648_1}, | ||
522 | {"ad5648-2", ID_AD5648_2}, | ||
523 | {"ad5668-1", ID_AD5668_1}, | ||
524 | {"ad5668-2", ID_AD5668_2}, | ||
525 | {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ | ||
440 | {} | 526 | {} |
441 | }; | 527 | }; |
442 | MODULE_DEVICE_TABLE(spi, ad5064_id); | 528 | MODULE_DEVICE_TABLE(spi, ad5064_id); |
@@ -453,5 +539,5 @@ static struct spi_driver ad5064_driver = { | |||
453 | module_spi_driver(ad5064_driver); | 539 | module_spi_driver(ad5064_driver); |
454 | 540 | ||
455 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 541 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
456 | MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65 DAC"); | 542 | MODULE_DESCRIPTION("Analog Devices AD5024/25/44/45/64/64-1/65, AD5628/48/68 DAC"); |
457 | MODULE_LICENSE("GPL v2"); | 543 | MODULE_LICENSE("GPL v2"); |