Source
x
/*
* ti-dac082s085.c - Texas Instruments 8/10/12-bit 2/4-channel DAC driver
*
* Copyright (C) 2017 KUNBUS GmbH
*
* http://www.ti.com/lit/ds/symlink/dac082s085.pdf
* http://www.ti.com/lit/ds/symlink/dac102s085.pdf
* http://www.ti.com/lit/ds/symlink/dac122s085.pdf
* http://www.ti.com/lit/ds/symlink/dac084s085.pdf
* http://www.ti.com/lit/ds/symlink/dac104s085.pdf
* http://www.ti.com/lit/ds/symlink/dac124s085.pdf
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (version 2) as
* published by the Free Software Foundation.
*/
enum { dual_8bit, dual_10bit, dual_12bit, quad_8bit, quad_10bit, quad_12bit };
struct ti_dac_spec {
u8 num_channels;
u8 resolution;
};
static const struct ti_dac_spec ti_dac_spec[] = {
[dual_8bit] = { .num_channels = 2, .resolution = 8 },
[dual_10bit] = { .num_channels = 2, .resolution = 10 },
[dual_12bit] = { .num_channels = 2, .resolution = 12 },
[quad_8bit] = { .num_channels = 4, .resolution = 8 },
[quad_10bit] = { .num_channels = 4, .resolution = 10 },
[quad_12bit] = { .num_channels = 4, .resolution = 12 },
};
/**
* struct ti_dac_chip - TI DAC chip
* @lock: protects write sequences
* @vref: regulator generating Vref
* @mesg: SPI message to perform a write
* @xfer: SPI transfer used by @mesg
* @val: cached value of each output
* @powerdown: whether the chip is powered down
* @powerdown_mode: selected by the user
* @resolution: resolution of the chip
* @buf: buffer for @xfer
*/
struct ti_dac_chip {
struct mutex lock;
struct regulator *vref;
struct spi_message mesg;
struct spi_transfer xfer;
u16 val[4];
bool powerdown;
u8 powerdown_mode;
u8 resolution;
u8 buf[2] ____cacheline_aligned;
};
static int ti_dac_cmd(struct ti_dac_chip *ti_dac, u8 cmd, u16 val)
{
u8 shift = 12 - ti_dac->resolution;
ti_dac->buf[0] = cmd | (val >> (8 - shift));
ti_dac->buf[1] = (val << shift) & 0xff;
return spi_sync(ti_dac->mesg.spi, &ti_dac->mesg);
}
static const char * const ti_dac_powerdown_modes[] = {
"2.5kohm_to_gnd", "100kohm_to_gnd", "three_state",
};
static int ti_dac_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
return ti_dac->powerdown_mode;
}
static int ti_dac_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
unsigned int mode)
{