Source
x
/*
* AD7303 Digital to analog converters driver
*
* Copyright 2013 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
/**
* struct ad7303_state - driver instance specific data
* @spi: the device for this driver instance
* @config: cached config register value
* @dac_cache: current DAC raw value (chip does not support readback)
* @data: spi transfer buffer
*/
struct ad7303_state {
struct spi_device *spi;
uint16_t config;
uint8_t dac_cache[2];
struct regulator *vdd_reg;
struct regulator *vref_reg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 data ____cacheline_aligned;
};
static int ad7303_write(struct ad7303_state *st, unsigned int chan,
uint8_t val)
{
st->data = cpu_to_be16(AD7303_CMD_UPDATE_DAC |
(chan << AD7303_CFG_ADDR_OFFSET) |
st->config | val);
return spi_write(st->spi, &st->data, sizeof(st->data));
}
static ssize_t ad7303_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct ad7303_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", (bool)(st->config &
AD7303_CFG_POWER_DOWN(chan->channel)));
}
static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
struct ad7303_state *st = iio_priv(indio_dev);
bool pwr_down;
int ret;
ret = strtobool(buf, &pwr_down);
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
if (pwr_down)
st->config |= AD7303_CFG_POWER_DOWN(chan->channel);
else
st->config &= ~AD7303_CFG_POWER_DOWN(chan->channel);
/* There is no noop cmd which allows us to only update the powerdown
* mode, so just write one of the DAC channels again */
ad7303_write(st, chan->channel, st->dac_cache[chan->channel]);