Skip to content

Commit 08a9e5f

Browse files
dlechjic23
authored andcommitted
iio: adc: ad7124: fix sample rate for multi-channel use
Change how the FS[10:0] field of the FILTER register is calculated to get consistent sample rates when only one channel is enabled vs when multiple channels are enabled in a buffered read. By default, the AD7124 allows larger sampling frequencies when only one channel is enabled. It assumes that you will discard the first sample or so to allow for settling time and then no additional settling time is needed between samples because there is no multiplexing due to only one channel being enabled. The conversion formula to convert between the sampling frequency and the FS[10:0] field is: fADC = fCLK / (FS[10:0] x 32) which is what the driver has been using. On the other hand, when multiple channels are enabled, there is additional settling time needed when switching between channels so the calculation to convert between becomes: fADC = fCLK / (FS[10:0] x 32 x N) where N depends on if SINGLE_CYCLE is set, the selected filter type and, in some cases, the power mode. The FILTER register has a SINGLE_CYCLE bit that can be set to force the single channel case to use the same timing as the multi-channel case. Before this change, the first formula was always used, so if all of the in_voltageY_sampling_frequency attributes were set to 10 Hz, then doing a buffered read with 1 channel enabled would result in the requested sampling frequency of 10 Hz. But when more than one channel was enabled, the actual sampling frequency would be 2.5 Hz per channel, which is 1/4 of the requested frequency. After this change, the SINGLE_CYCLE flag is now always enabled and the multi-channel formula is now always used. This causes the sampling frequency to be consistent regardless of the number of channels enabled. For now, we are hard-coding N = 4 since the driver doesn't yet support other filter types other than the default sinc4 filter. The AD7124_FILTER_FS define is moved while we are touching this to keep the bit fields in descending order to be consistent with the rest of the file. Signed-off-by: David Lechner <dlechner@baylibre.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent ee905c9 commit 08a9e5f

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

drivers/iio/adc/ad7124.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@
9393
#define AD7124_CONFIG_PGA GENMASK(2, 0)
9494

9595
/* AD7124_FILTER_X */
96-
#define AD7124_FILTER_FS GENMASK(10, 0)
9796
#define AD7124_FILTER_FILTER GENMASK(23, 21)
9897
#define AD7124_FILTER_FILTER_SINC4 0
9998
#define AD7124_FILTER_FILTER_SINC3 2
99+
#define AD7124_FILTER_SINGLE_CYCLE BIT(16)
100+
#define AD7124_FILTER_FS GENMASK(10, 0)
100101

101102
#define AD7124_MAX_CONFIGS 8
102103
#define AD7124_MAX_CHANNELS 16
@@ -285,18 +286,20 @@ static u32 ad7124_get_fclk_hz(struct ad7124_state *st)
285286

286287
static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, unsigned int odr)
287288
{
288-
unsigned int fclk, odr_sel_bits;
289+
unsigned int fclk, factor, odr_sel_bits;
289290

290291
fclk = ad7124_get_fclk_hz(st);
291292

292293
/*
293-
* FS[10:0] = fCLK / (fADC x 32) where:
294+
* FS[10:0] = fCLK / (fADC x 32 * N) where:
294295
* fADC is the output data rate
295296
* fCLK is the master clock frequency
297+
* N is number of conversions per sample (depends on filter type)
296298
* FS[10:0] are the bits in the filter register
297299
* FS[10:0] can have a value from 1 to 2047
298300
*/
299-
odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * 32);
301+
factor = 32 * 4; /* N = 4 for default sinc4 filter. */
302+
odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor);
300303
if (odr_sel_bits < 1)
301304
odr_sel_bits = 1;
302305
else if (odr_sel_bits > 2047)
@@ -306,7 +309,8 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel
306309
st->channels[channel].cfg.live = false;
307310

308311
/* fADC = fCLK / (FS[10:0] x 32) */
309-
st->channels[channel].cfg.odr = DIV_ROUND_CLOSEST(fclk, odr_sel_bits * 32);
312+
st->channels[channel].cfg.odr = DIV_ROUND_CLOSEST(fclk, odr_sel_bits *
313+
factor);
310314
st->channels[channel].cfg.odr_sel_bits = odr_sel_bits;
311315
}
312316

@@ -439,10 +443,20 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co
439443
if (ret < 0)
440444
return ret;
441445

446+
/*
447+
* NB: AD7124_FILTER_SINGLE_CYCLE is always set so that we get the same
448+
* sampling frequency even when only one channel is enabled in a
449+
* buffered read. If it was not set, the N in ad7124_set_channel_odr()
450+
* would be 1 and we would get a faster sampling frequency than what
451+
* was requested.
452+
*/
442453
tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) |
454+
AD7124_FILTER_SINGLE_CYCLE |
443455
FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits);
444456
return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot),
445-
AD7124_FILTER_FILTER | AD7124_FILTER_FS,
457+
AD7124_FILTER_FILTER |
458+
AD7124_FILTER_SINGLE_CYCLE |
459+
AD7124_FILTER_FS,
446460
tmp, 3);
447461
}
448462

0 commit comments

Comments
 (0)