/* * Dither signal can also be scaled. * Available dither scale strings corresponding to "dither_scale" field in * "struct ad5766_state".
*/ staticconstchar * const ad5766_dither_scales[] = { "1", "0.75", "0.5", "0.25",
};
/** * struct ad5766_state - driver instance specific data * @spi: SPI device * @lock: Lock used to restrict concurrent access to SPI device * @chip_info: Chip model specific constants * @gpio_reset: Reset GPIO, used to reset the device * @crt_range: Current selected output range * @dither_enable: Power enable bit for each channel dither block (for * example, D15 = DAC 15,D8 = DAC 8, and D0 = DAC 0) * 0 - Normal operation, 1 - Power down * @dither_invert: Inverts the dither signal applied to the selected DAC * outputs * @dither_source: Selects between 2 possible sources: * 1: N0, 2: N1 * Two bits are used for each channel * @dither_scale: Two bits are used for each of the 16 channels: * 0: 1 SCALING, 1: 0.75 SCALING, 2: 0.5 SCALING, * 3: 0.25 SCALING. * @data: SPI transfer buffers
*/ struct ad5766_state { struct spi_device *spi; struct mutex lock; conststruct ad5766_chip_info *chip_info; struct gpio_desc *gpio_reset; enum ad5766_voltage_range crt_range;
u16 dither_enable;
u16 dither_invert;
u32 dither_source;
u32 dither_scale; union {
u32 d32;
u16 w16[2];
u8 b8[4];
} data[3] __aligned(IIO_DMA_MINALIGN);
};
mutex_lock(&st->lock);
ret = __ad5766_spi_write(st, AD5766_CMD_WR_DAC_REG(dac), data);
mutex_unlock(&st->lock);
return ret;
}
staticint ad5766_reset(struct ad5766_state *st)
{ int ret;
if (st->gpio_reset) {
gpiod_set_value_cansleep(st->gpio_reset, 1);
ndelay(100); /* t_reset >= 100ns */
gpiod_set_value_cansleep(st->gpio_reset, 0);
} else {
ret = __ad5766_spi_write(st, AD5766_CMD_SW_FULL_RESET,
AD5766_FULL_RESET_CODE); if (ret < 0) return ret;
}
/* * Minimum time between a reset and the subsequent successful write is * typically 25 ns
*/
ndelay(25);
return 0;
}
staticint ad5766_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m)
{ struct ad5766_state *st = iio_priv(indio_dev); int ret;
switch (m) { case IIO_CHAN_INFO_RAW:
ret = ad5766_read(indio_dev, chan->address, val); if (ret) return ret;
return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET:
*val = ad5766_span_tbl[st->crt_range].min;
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_scale);
ret = ad5766_write(dev, AD5766_CMD_DITHER_SCALE_1, val); if (ret) return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_scale);
staticint ad5766_get_output_range(struct ad5766_state *st)
{ int i, ret, min, max, tmp[2];
ret = device_property_read_u32_array(&st->spi->dev, "output-range-microvolts",
tmp, 2); if (ret) return ret;
min = tmp[0] / 1000000;
max = tmp[1] / 1000000; for (i = 0; i < ARRAY_SIZE(ad5766_span_tbl); i++) { if (ad5766_span_tbl[i].min != min ||
ad5766_span_tbl[i].max != max) continue;
st->crt_range = i;
return 0;
}
return -EINVAL;
}
staticint ad5766_default_setup(struct ad5766_state *st)
{
uint16_t val; int ret, i;
/* Always issue a reset before writing to the span register. */
ret = ad5766_reset(st); if (ret) return ret;
ret = ad5766_get_output_range(st); if (ret) return ret;
/* Dither power down */
st->dither_enable = GENMASK(15, 0);
ret = __ad5766_spi_write(st, AD5766_CMD_WR_PWR_DITHER,
st->dither_enable); if (ret) return ret;
st->dither_source = 0; for (i = 0; i < ARRAY_SIZE(ad5766_channels); i++)
st->dither_source |= AD5766_DITHER_SOURCE(i, 0);
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_source);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SIG_1, val); if (ret) return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_source);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SIG_2, val); if (ret) return ret;
st->dither_scale = 0;
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_scale);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SCALE_1, val); if (ret) return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_scale);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SCALE_2, val); if (ret) return ret;
st->dither_invert = 0;
ret = __ad5766_spi_write(st, AD5766_CMD_INV_DITHER, st->dither_invert); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.