Skip to content

Commit b2dbba2

Browse files
dlechjic23
authored andcommitted
iio: adc: ad7124: support fractional sampling_frequency
Modify the attribute read/write functions for sampling_frequency and filter_low_pass_3db_frequency to return fractional values. These ADCs support output data rates in the single digits, so being able to specify fractional values is necessary to use all possible sampling frequencies. Signed-off-by: David Lechner <dlechner@baylibre.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent d904b8e commit b2dbba2

1 file changed

Lines changed: 39 additions & 26 deletions

File tree

drivers/iio/adc/ad7124.c

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ struct ad7124_channel_config {
166166
bool buf_negative;
167167
unsigned int vref_mv;
168168
unsigned int pga_bits;
169-
unsigned int odr;
170169
unsigned int odr_sel_bits;
171170
unsigned int filter_type;
172171
unsigned int calibration_offset;
@@ -285,7 +284,17 @@ static u32 ad7124_get_fclk_hz(struct ad7124_state *st)
285284
return fclk_hz;
286285
}
287286

288-
static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, unsigned int odr)
287+
static u32 ad7124_get_fadc_divisor(struct ad7124_state *st, unsigned int channel)
288+
{
289+
/*
290+
* The output data rate (f_ADC) is f_CLK / divisor. We are returning
291+
* the divisor.
292+
*/
293+
return st->channels[channel].cfg.odr_sel_bits * 32 * 4;
294+
}
295+
296+
static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel,
297+
unsigned int odr, unsigned int odr_micro)
289298
{
290299
unsigned int fclk, factor, odr_sel_bits;
291300

@@ -300,29 +309,28 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel
300309
* FS[10:0] can have a value from 1 to 2047
301310
*/
302311
factor = 32 * 4; /* N = 4 for default sinc4 filter. */
303-
odr_sel_bits = clamp(DIV_ROUND_CLOSEST(fclk, odr * factor), 1, 2047);
312+
odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor +
313+
odr_micro * factor / MICRO);
314+
odr_sel_bits = clamp(odr_sel_bits, 1, 2047);
304315

305316
if (odr_sel_bits != st->channels[channel].cfg.odr_sel_bits)
306317
st->channels[channel].cfg.live = false;
307318

308-
/* fADC = fCLK / (FS[10:0] x 32) */
309-
st->channels[channel].cfg.odr = DIV_ROUND_CLOSEST(fclk, odr_sel_bits *
310-
factor);
311319
st->channels[channel].cfg.odr_sel_bits = odr_sel_bits;
312320
}
313321

314-
static int ad7124_get_3db_filter_freq(struct ad7124_state *st,
315-
unsigned int channel)
322+
static int ad7124_get_3db_filter_factor(struct ad7124_state *st,
323+
unsigned int channel)
316324
{
317-
unsigned int fadc;
318-
319-
fadc = st->channels[channel].cfg.odr;
320-
325+
/*
326+
* 3dB point is the f_CLK rate times some factor. This functions returns
327+
* the factor times 1000.
328+
*/
321329
switch (st->channels[channel].cfg.filter_type) {
322330
case AD7124_FILTER_FILTER_SINC3:
323-
return DIV_ROUND_CLOSEST(fadc * 272, 1000);
331+
return 272;
324332
case AD7124_FILTER_FILTER_SINC4:
325-
return DIV_ROUND_CLOSEST(fadc * 230, 1000);
333+
return 230;
326334
default:
327335
return -EINVAL;
328336
}
@@ -346,7 +354,6 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_
346354
bool buf_negative;
347355
unsigned int vref_mv;
348356
unsigned int pga_bits;
349-
unsigned int odr;
350357
unsigned int odr_sel_bits;
351358
unsigned int filter_type;
352359
unsigned int calibration_offset;
@@ -363,7 +370,6 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_
363370
cfg->buf_negative == cfg_aux->buf_negative &&
364371
cfg->vref_mv == cfg_aux->vref_mv &&
365372
cfg->pga_bits == cfg_aux->pga_bits &&
366-
cfg->odr == cfg_aux->odr &&
367373
cfg->odr_sel_bits == cfg_aux->odr_sel_bits &&
368374
cfg->filter_type == cfg_aux->filter_type &&
369375
cfg->calibration_offset == cfg_aux->calibration_offset &&
@@ -718,16 +724,23 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,
718724

719725
case IIO_CHAN_INFO_SAMP_FREQ:
720726
mutex_lock(&st->cfgs_lock);
721-
*val = st->channels[chan->address].cfg.odr;
727+
*val = ad7124_get_fclk_hz(st);
728+
*val2 = ad7124_get_fadc_divisor(st, chan->address);
722729
mutex_unlock(&st->cfgs_lock);
723730

724-
return IIO_VAL_INT;
725-
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
726-
mutex_lock(&st->cfgs_lock);
727-
*val = ad7124_get_3db_filter_freq(st, chan->scan_index);
728-
mutex_unlock(&st->cfgs_lock);
731+
return IIO_VAL_FRACTIONAL;
732+
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: {
733+
guard(mutex)(&st->cfgs_lock);
729734

730-
return IIO_VAL_INT;
735+
ret = ad7124_get_3db_filter_factor(st, chan->address);
736+
if (ret < 0)
737+
return ret;
738+
739+
/* 3dB point is the f_CLK rate times a fractional value */
740+
*val = ret * ad7124_get_fclk_hz(st);
741+
*val2 = MILLI * ad7124_get_fadc_divisor(st, chan->address);
742+
return IIO_VAL_FRACTIONAL;
743+
}
731744
default:
732745
return -EINVAL;
733746
}
@@ -744,10 +757,10 @@ static int ad7124_write_raw(struct iio_dev *indio_dev,
744757

745758
switch (info) {
746759
case IIO_CHAN_INFO_SAMP_FREQ:
747-
if (val2 != 0 || val == 0)
760+
if (val2 < 0 || val < 0 || (val2 == 0 && val == 0))
748761
return -EINVAL;
749762

750-
ad7124_set_channel_odr(st, chan->address, val);
763+
ad7124_set_channel_odr(st, chan->address, val, val2);
751764

752765
return 0;
753766
case IIO_CHAN_INFO_SCALE:
@@ -1296,7 +1309,7 @@ static int ad7124_setup(struct ad7124_state *st)
12961309
* regardless of the selected power mode. Round it up to 10 and
12971310
* set all channels to this default value.
12981311
*/
1299-
ad7124_set_channel_odr(st, i, 10);
1312+
ad7124_set_channel_odr(st, i, 10, 0);
13001313
}
13011314

13021315
ad7124_disable_all(&st->sd);

0 commit comments

Comments
 (0)