iio: adc: mcp3911: add support for oversampling ratio
The chip supports oversampling ratio, so expose it to userspace. Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Link: https://lore.kernel.org/r/20220815061625.35568-9-marcus.folkesson@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
1a84fa695c
commit
6d965885f4
|
@ -41,6 +41,7 @@
|
|||
#define MCP3911_REG_CONFIG 0x0c
|
||||
#define MCP3911_CONFIG_CLKEXT BIT(1)
|
||||
#define MCP3911_CONFIG_VREFEXT BIT(2)
|
||||
#define MCP3911_CONFIG_OSR GENMASK(13, 11)
|
||||
|
||||
#define MCP3911_REG_OFFCAL_CH0 0x0e
|
||||
#define MCP3911_REG_GAINCAL_CH0 0x11
|
||||
|
@ -59,6 +60,8 @@
|
|||
|
||||
#define MCP3911_NUM_CHANNELS 2
|
||||
|
||||
static const int mcp3911_osr_table[] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
|
||||
|
||||
struct mcp3911 {
|
||||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
|
@ -117,6 +120,36 @@ static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
|
|||
return mcp3911_write(adc, reg, val, len);
|
||||
}
|
||||
|
||||
static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
long mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
}
|
||||
}
|
||||
|
||||
static int mcp3911_read_avail(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
const int **vals, int *type, int *length,
|
||||
long info)
|
||||
{
|
||||
switch (info) {
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
*type = IIO_VAL_INT;
|
||||
*vals = mcp3911_osr_table;
|
||||
*length = ARRAY_SIZE(mcp3911_osr_table);
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int mcp3911_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *channel, int *val,
|
||||
int *val2, long mask)
|
||||
|
@ -145,6 +178,15 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev,
|
|||
|
||||
ret = IIO_VAL_INT;
|
||||
break;
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
*val = FIELD_GET(MCP3911_CONFIG_OSR, *val);
|
||||
*val = 32 << *val;
|
||||
ret = IIO_VAL_INT;
|
||||
break;
|
||||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (adc->vref) {
|
||||
|
@ -204,6 +246,17 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
|
|||
MCP3911_STATUSCOM_EN_OFFCAL,
|
||||
MCP3911_STATUSCOM_EN_OFFCAL, 2);
|
||||
break;
|
||||
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
for (int i = 0; i < sizeof(mcp3911_osr_table); i++) {
|
||||
if (val == mcp3911_osr_table[i]) {
|
||||
val = FIELD_PREP(MCP3911_CONFIG_OSR, i);
|
||||
ret = mcp3911_update(adc, MCP3911_REG_CONFIG, MCP3911_CONFIG_OSR,
|
||||
val, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -216,9 +269,12 @@ out:
|
|||
.indexed = 1, \
|
||||
.channel = idx, \
|
||||
.scan_index = idx, \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_shared_by_type_available = \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = 24, \
|
||||
|
@ -278,6 +334,8 @@ out:
|
|||
static const struct iio_info mcp3911_info = {
|
||||
.read_raw = mcp3911_read_raw,
|
||||
.write_raw = mcp3911_write_raw,
|
||||
.read_avail = mcp3911_read_avail,
|
||||
.write_raw_get_fmt = mcp3911_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
static int mcp3911_config(struct mcp3911 *adc)
|
||||
|
|
Loading…
Reference in New Issue