diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/iio/dac/ds4424.c | 55 |
1 files changed, 21 insertions, 34 deletions
diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c index c61868f2de31..c15eb7b5eb96 100644 --- a/drivers/iio/dac/ds4424.c +++ b/drivers/iio/dac/ds4424.c @@ -5,6 +5,7 @@ * Copyright (C) 2017 Maxim Integrated */ +#include <linux/bits.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/i2c.h> @@ -18,9 +19,10 @@ #define DS4422_MAX_DAC_CHANNELS 2 #define DS4424_MAX_DAC_CHANNELS 4 +#define DS4424_DAC_MASK GENMASK(6, 0) +#define DS4424_DAC_SOURCE BIT(7) + #define DS4424_DAC_ADDR(chan) ((chan) + 0xf8) -#define DS4424_SOURCE_I 1 -#define DS4424_SINK_I 0 #define DS4424_CHANNEL(chan) { \ .type = IIO_CURRENT, \ @@ -30,22 +32,6 @@ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ } -/* - * DS4424 DAC control register 8 bits - * [7] 0: to sink; 1: to source - * [6:0] steps to sink/source - * bit[7] looks like a sign bit, but the value of the register is - * not a two's complement code considering the bit[6:0] is a absolute - * distance from the zero point. - */ -union ds4424_raw_data { - struct { - u8 dx:7; - u8 source_bit:1; - }; - u8 bits; -}; - enum ds4424_device_ids { ID_DS4422, ID_DS4424, @@ -107,21 +93,21 @@ static int ds4424_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { - union ds4424_raw_data raw; - int ret; + int ret, regval; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = ds4424_get_value(indio_dev, val, chan->channel); + ret = ds4424_get_value(indio_dev, ®val, chan->channel); if (ret < 0) { pr_err("%s : ds4424_get_value returned %d\n", __func__, ret); return ret; } - raw.bits = *val; - *val = raw.dx; - if (raw.source_bit == DS4424_SINK_I) + + *val = regval & DS4424_DAC_MASK; + if (!(regval & DS4424_DAC_SOURCE)) *val = -*val; + return IIO_VAL_INT; default: @@ -133,25 +119,26 @@ static int ds4424_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { - union ds4424_raw_data raw; + unsigned int abs_val; if (val2 != 0) return -EINVAL; switch (mask) { case IIO_CHAN_INFO_RAW: - if (val <= S8_MIN || val > S8_MAX) + abs_val = abs(val); + if (abs_val > DS4424_DAC_MASK) return -EINVAL; - if (val > 0) { - raw.source_bit = DS4424_SOURCE_I; - raw.dx = val; - } else { - raw.source_bit = DS4424_SINK_I; - raw.dx = -val; - } + /* + * Currents exiting the IC (Source) are positive. 0 is a valid + * value for no current flow; the direction bit (Source vs Sink) + * is treated as don't-care by the hardware at 0. + */ + if (val > 0) + abs_val |= DS4424_DAC_SOURCE; - return ds4424_set_value(indio_dev, raw.bits, chan); + return ds4424_set_value(indio_dev, abs_val, chan); default: return -EINVAL; |
