aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/dac/ad5686.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/iio/dac/ad5686.c')
-rw-r--r--drivers/staging/iio/dac/ad5686.c133
1 files changed, 50 insertions, 83 deletions
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c
index fd67cfa5edb6..48389e1c19f1 100644
--- a/drivers/staging/iio/dac/ad5686.c
+++ b/drivers/staging/iio/dac/ad5686.c
@@ -7,9 +7,9 @@
*/
#include <linux/interrupt.h>
-#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -25,10 +25,7 @@
#define AD5686_ADDR(x) ((x) << 16)
#define AD5686_CMD(x) ((x) << 20)
-#define AD5686_ADDR_DAC0 0x1
-#define AD5686_ADDR_DAC1 0x2
-#define AD5686_ADDR_DAC2 0x4
-#define AD5686_ADDR_DAC3 0x8
+#define AD5686_ADDR_DAC(chan) (0x1 << (chan))
#define AD5686_ADDR_ALL_DAC 0xF
#define AD5686_CMD_NOOP 0x0
@@ -96,63 +93,35 @@ enum ad5686_supported_device_ids {
ID_AD5685,
ID_AD5686,
};
-
+#define AD5868_CHANNEL(chan, bits, shift) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .output = 1, \
+ .channel = chan, \
+ .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \
+ .address = AD5686_ADDR_DAC(chan), \
+ .scan_type = IIO_ST('u', bits, 16, shift) \
+}
static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
[ID_AD5684] = {
- .channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC0,
- 0, IIO_ST('u', 12, 16, 4), 0),
- .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC1,
- 1, IIO_ST('u', 12, 16, 4), 0),
- .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC2,
- 2, IIO_ST('u', 12, 16, 4), 0),
- .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC3,
- 3, IIO_ST('u', 12, 16, 4), 0),
+ .channel[0] = AD5868_CHANNEL(0, 12, 4),
+ .channel[1] = AD5868_CHANNEL(1, 12, 4),
+ .channel[2] = AD5868_CHANNEL(2, 12, 4),
+ .channel[3] = AD5868_CHANNEL(3, 12, 4),
.int_vref_mv = 2500,
},
[ID_AD5685] = {
- .channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC0,
- 0, IIO_ST('u', 14, 16, 2), 0),
- .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC1,
- 1, IIO_ST('u', 14, 16, 2), 0),
- .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC2,
- 2, IIO_ST('u', 14, 16, 2), 0),
- .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC3,
- 3, IIO_ST('u', 14, 16, 2), 0),
+ .channel[0] = AD5868_CHANNEL(0, 14, 2),
+ .channel[1] = AD5868_CHANNEL(1, 14, 2),
+ .channel[2] = AD5868_CHANNEL(2, 14, 2),
+ .channel[3] = AD5868_CHANNEL(3, 14, 2),
.int_vref_mv = 2500,
},
[ID_AD5686] = {
- .channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC0,
- 0, IIO_ST('u', 16, 16, 0), 0),
- .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC1,
- 1, IIO_ST('u', 16, 16, 0), 0),
- .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC2,
- 2, IIO_ST('u', 16, 16, 0), 0),
- .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0,
- (1 << IIO_CHAN_INFO_SCALE_SHARED),
- AD5686_ADDR_DAC3,
- 3, IIO_ST('u', 16, 16, 0), 0),
+ .channel[0] = AD5868_CHANNEL(0, 16, 0),
+ .channel[1] = AD5868_CHANNEL(1, 16, 0),
+ .channel[2] = AD5868_CHANNEL(2, 16, 0),
+ .channel[3] = AD5868_CHANNEL(3, 16, 0),
.int_vref_mv = 2500,
},
};
@@ -274,11 +243,12 @@ static ssize_t ad5686_write_dac_powerdown(struct device *dev,
return ret ? ret : len;
}
-static IIO_CONST_ATTR(out_powerdown_mode_available,
+static IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
"1kohm_to_gnd 100kohm_to_gnd three_state");
-#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \
- IIO_DEVICE_ATTR(out##_num##_powerdown_mode, S_IRUGO | S_IWUSR, \
+#define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \
+ IIO_DEVICE_ATTR(out_voltage##_num##_powerdown_mode, \
+ S_IRUGO | S_IWUSR, \
ad5686_read_powerdown_mode, \
ad5686_write_powerdown_mode, _num)
@@ -287,8 +257,9 @@ static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1);
static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2);
static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3);
-#define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \
- IIO_DEVICE_ATTR(out##_num##_powerdown, S_IRUGO | S_IWUSR, \
+#define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \
+ IIO_DEVICE_ATTR(out_voltage##_num##_powerdown, \
+ S_IRUGO | S_IWUSR, \
ad5686_read_dac_powerdown, \
ad5686_write_dac_powerdown, _num)
@@ -298,15 +269,15 @@ static IIO_DEV_ATTR_DAC_POWERDOWN(2);
static IIO_DEV_ATTR_DAC_POWERDOWN(3);
static struct attribute *ad5686_attributes[] = {
- &iio_dev_attr_out0_powerdown.dev_attr.attr,
- &iio_dev_attr_out1_powerdown.dev_attr.attr,
- &iio_dev_attr_out2_powerdown.dev_attr.attr,
- &iio_dev_attr_out3_powerdown.dev_attr.attr,
- &iio_dev_attr_out0_powerdown_mode.dev_attr.attr,
- &iio_dev_attr_out1_powerdown_mode.dev_attr.attr,
- &iio_dev_attr_out2_powerdown_mode.dev_attr.attr,
- &iio_dev_attr_out3_powerdown_mode.dev_attr.attr,
- &iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr,
+ &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr,
+ &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr,
+ &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr,
+ &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr,
+ &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
NULL,
};
@@ -356,7 +327,7 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case 0:
- if (val > (1 << chan->scan_type.realbits))
+ if (val > (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
@@ -420,16 +391,16 @@ static int __devinit ad5686_probe(struct spi_device *spi)
indio_dev->channels = st->chip_info->channel;
indio_dev->num_channels = AD5686_DAC_CHANNELS;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
regdone = 1;
ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0,
!!voltage_uv, 0);
if (ret)
goto error_disable_reg;
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_disable_reg;
+
return 0;
error_disable_reg:
@@ -439,10 +410,7 @@ error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
- if (regdone)
- iio_device_unregister(indio_dev);
- else
- iio_free_device(indio_dev);
+ iio_free_device(indio_dev);
return ret;
}
@@ -451,14 +419,13 @@ static int __devexit ad5686_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad5686_state *st = iio_priv(indio_dev);
- struct regulator *reg = st->reg;
-
- if (!IS_ERR(reg)) {
- regulator_disable(reg);
- regulator_put(reg);
- }
iio_device_unregister(indio_dev);
+ if (!IS_ERR(st->reg)) {
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+ }
+ iio_free_device(indio_dev);
return 0;
}