mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-17 11:29:00 +07:00
iio: adc: ad7124: add 3db filter
This patch adds the LOW_PASS_FILTER_3DB_FREQUENCY attribute in iio_chan_spec for each channel. The used filters are sinc3 or sinc4. The filter type with the highest output data rate is used when setting a low pass frequency in the channel's sysfs. Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
ebf7a11267
commit
cef2760954
@ -70,6 +70,11 @@
|
|||||||
/* AD7124_FILTER_X */
|
/* AD7124_FILTER_X */
|
||||||
#define AD7124_FILTER_FS_MSK GENMASK(10, 0)
|
#define AD7124_FILTER_FS_MSK GENMASK(10, 0)
|
||||||
#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x)
|
#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x)
|
||||||
|
#define AD7124_FILTER_TYPE_MSK GENMASK(23, 21)
|
||||||
|
#define AD7124_FILTER_TYPE_SEL(x) FIELD_PREP(AD7124_FILTER_TYPE_MSK, x)
|
||||||
|
|
||||||
|
#define AD7124_SINC3_FILTER 2
|
||||||
|
#define AD7124_SINC4_FILTER 0
|
||||||
|
|
||||||
enum ad7124_ids {
|
enum ad7124_ids {
|
||||||
ID_AD7124_4,
|
ID_AD7124_4,
|
||||||
@ -119,6 +124,7 @@ struct ad7124_channel_config {
|
|||||||
unsigned int vref_mv;
|
unsigned int vref_mv;
|
||||||
unsigned int pga_bits;
|
unsigned int pga_bits;
|
||||||
unsigned int odr;
|
unsigned int odr;
|
||||||
|
unsigned int filter_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ad7124_state {
|
struct ad7124_state {
|
||||||
@ -138,7 +144,8 @@ static const struct iio_chan_spec ad7124_channel_template = {
|
|||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||||
BIT(IIO_CHAN_INFO_SCALE) |
|
BIT(IIO_CHAN_INFO_SCALE) |
|
||||||
BIT(IIO_CHAN_INFO_OFFSET) |
|
BIT(IIO_CHAN_INFO_OFFSET) |
|
||||||
BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||||
|
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
|
||||||
.scan_type = {
|
.scan_type = {
|
||||||
.sign = 'u',
|
.sign = 'u',
|
||||||
.realbits = 24,
|
.realbits = 24,
|
||||||
@ -281,6 +288,58 @@ static int ad7124_set_channel_gain(struct ad7124_state *st,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ad7124_get_3db_filter_freq(struct ad7124_state *st,
|
||||||
|
unsigned int channel)
|
||||||
|
{
|
||||||
|
unsigned int fadc;
|
||||||
|
|
||||||
|
fadc = st->channel_config[channel].odr;
|
||||||
|
|
||||||
|
switch (st->channel_config[channel].filter_type) {
|
||||||
|
case AD7124_SINC3_FILTER:
|
||||||
|
return DIV_ROUND_CLOSEST(fadc * 230, 1000);
|
||||||
|
case AD7124_SINC4_FILTER:
|
||||||
|
return DIV_ROUND_CLOSEST(fadc * 262, 1000);
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ad7124_set_3db_filter_freq(struct ad7124_state *st,
|
||||||
|
unsigned int channel,
|
||||||
|
unsigned int freq)
|
||||||
|
{
|
||||||
|
unsigned int sinc4_3db_odr;
|
||||||
|
unsigned int sinc3_3db_odr;
|
||||||
|
unsigned int new_filter;
|
||||||
|
unsigned int new_odr;
|
||||||
|
|
||||||
|
sinc4_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 230);
|
||||||
|
sinc3_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 262);
|
||||||
|
|
||||||
|
if (sinc4_3db_odr > sinc3_3db_odr) {
|
||||||
|
new_filter = AD7124_SINC3_FILTER;
|
||||||
|
new_odr = sinc4_3db_odr;
|
||||||
|
} else {
|
||||||
|
new_filter = AD7124_SINC4_FILTER;
|
||||||
|
new_odr = sinc3_3db_odr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st->channel_config[channel].filter_type != new_filter) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
st->channel_config[channel].filter_type = new_filter;
|
||||||
|
ret = ad7124_spi_write_mask(st, AD7124_FILTER(channel),
|
||||||
|
AD7124_FILTER_TYPE_MSK,
|
||||||
|
AD7124_FILTER_TYPE_SEL(new_filter),
|
||||||
|
3);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ad7124_set_channel_odr(st, channel, new_odr);
|
||||||
|
}
|
||||||
|
|
||||||
static int ad7124_read_raw(struct iio_dev *indio_dev,
|
static int ad7124_read_raw(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *chan,
|
struct iio_chan_spec const *chan,
|
||||||
int *val, int *val2, long info)
|
int *val, int *val2, long info)
|
||||||
@ -322,6 +381,9 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,
|
|||||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
*val = st->channel_config[chan->address].odr;
|
*val = st->channel_config[chan->address].odr;
|
||||||
|
|
||||||
|
return IIO_VAL_INT;
|
||||||
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
|
*val = ad7124_get_3db_filter_freq(st, chan->scan_index);
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -355,6 +417,11 @@ static int ad7124_write_raw(struct iio_dev *indio_dev,
|
|||||||
gain = DIV_ROUND_CLOSEST(res, val2);
|
gain = DIV_ROUND_CLOSEST(res, val2);
|
||||||
|
|
||||||
return ad7124_set_channel_gain(st, chan->address, gain);
|
return ad7124_set_channel_gain(st, chan->address, gain);
|
||||||
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
|
if (val2 != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return ad7124_set_3db_filter_freq(st, chan->address, val);
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user