Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging:iio:dac:ad5791: Allow asymmetrical reference voltages

The ad5791 currently assumes that the negative and positive supply have the
same absolute value, which is not necessarily true. This patch introduces a
offset attribute which will contain the negative supply voltage scaled
according to the iio spec. The raw attribute now accepts values in the range
of 0 to max instead of -max/2 to max/2.

While we are at it also fix the vref span calculation. Since both positive and
negative reference voltages are specificed as absolute values we need to add
them and not subtract them to get the reference voltage span.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Lars-Peter Clausen and committed by
Greg Kroah-Hartman
9dc9961d 021c0a38

+18 -8
+16 -8
drivers/staging/iio/dac/ad5791.c
··· 77 77 .indexed = 1, \ 78 78 .address = AD5791_ADDR_DAC0, \ 79 79 .channel = 0, \ 80 - .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED), \ 80 + .info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED) | \ 81 + (1 << IIO_CHAN_INFO_OFFSET_SHARED), \ 81 82 .scan_type = IIO_ST('u', bits, 24, shift) \ 82 83 } 83 84 ··· 226 225 long m) 227 226 { 228 227 struct ad5791_state *st = iio_priv(indio_dev); 228 + u64 val64; 229 229 int ret; 230 230 231 231 switch (m) { ··· 236 234 return ret; 237 235 *val &= AD5791_DAC_MASK; 238 236 *val >>= chan->scan_type.shift; 239 - *val -= (1 << (chan->scan_type.realbits - 1)); 240 237 return IIO_VAL_INT; 241 238 case (1 << IIO_CHAN_INFO_SCALE_SHARED): 242 239 *val = 0; 243 240 *val2 = (st->vref_mv * 1000) >> chan->scan_type.realbits; 244 241 return IIO_VAL_INT_PLUS_MICRO; 242 + case (1 << IIO_CHAN_INFO_OFFSET_SHARED): 243 + val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); 244 + do_div(val64, st->vref_mv); 245 + *val = -val64; 246 + return IIO_VAL_INT; 245 247 default: 246 248 return -EINVAL; 247 249 } ··· 263 257 264 258 switch (mask) { 265 259 case 0: 266 - val += (1 << (chan->scan_type.realbits - 1)); 267 260 val &= AD5791_RES_MASK(chan->scan_type.realbits); 268 261 val <<= chan->scan_type.shift; 269 262 ··· 314 309 st->pwr_down = true; 315 310 st->spi = spi; 316 311 317 - if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) 318 - st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000; 319 - else if (pdata) 320 - st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv; 321 - else 312 + if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) { 313 + st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; 314 + st->vref_neg_mv = neg_voltage_uv / 1000; 315 + } else if (pdata) { 316 + st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv; 317 + st->vref_neg_mv = pdata->vref_neg_mv; 318 + } else { 322 319 dev_warn(&spi->dev, "reference voltage unspecified\n"); 320 + } 323 321 324 322 ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); 325 323 if (ret)
+2
drivers/staging/iio/dac/ad5791.h
··· 82 82 * @reg_vss: negative supply regulator 83 83 * @chip_info: chip model specific constants 84 84 * @vref_mv: actual reference voltage used 85 + * @vref_neg_mv: voltage of the negative supply 85 86 * @pwr_down_mode current power down mode 86 87 */ 87 88 ··· 92 91 struct regulator *reg_vss; 93 92 const struct ad5791_chip_info *chip_info; 94 93 unsigned short vref_mv; 94 + unsigned int vref_neg_mv; 95 95 unsigned ctrl; 96 96 unsigned pwr_down_mode; 97 97 bool pwr_down;