[PATCH v5 10/20] iio: adc: ad7768: Add sampling frequency controls
From: Janani Sunil
Date: Fri Aug 28 2026 - 11:35:40 EST
Expose the requested sampling frequency and available rates for each
channel. Validate requests against the rates supported by the power mode
tables and apply them when buffered capture starts.
Signed-off-by: Janani Sunil <janani.sunil@xxxxxxxxxx>
---
drivers/iio/adc/ad7768.c | 116 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 109 insertions(+), 7 deletions(-)
diff --git a/drivers/iio/adc/ad7768.c b/drivers/iio/adc/ad7768.c
index 00d6f1dce591..1245ec94b637 100644
--- a/drivers/iio/adc/ad7768.c
+++ b/drivers/iio/adc/ad7768.c
@@ -130,6 +130,9 @@ static const struct ad7768_power_mode_info ad7768_power_modes[] = {
{ .mode = AD7768_POWER_MODE_POWER_MODE_FAST, .mclk_div = 4 },
};
+#define AD7768_MAX_FREQS \
+ (AD7768_MAX_FREQ_PER_MODE + ARRAY_SIZE(ad7768_power_modes))
+
struct ad7768_precharge_config {
bool prebufp_en;
bool prebufn_en;
@@ -167,6 +170,8 @@ struct ad7768_state {
unsigned int power_mode_idx;
const struct ad7768_chip_info *chip_info;
struct ad7768_avail_freq avail_freq[ARRAY_SIZE(ad7768_power_modes)];
+ unsigned int n_freqs;
+ int freqs[AD7768_MAX_FREQS];
unsigned int ch_freq[AD7768_MAX_CHANNEL];
struct iio_backend *back;
unsigned int vref_uV[2];
@@ -496,6 +501,32 @@ static int ad7768_set_lowest_noise_mode(struct ad7768_state *st,
return -EINVAL;
}
+static bool ad7768_freq_supported_in_any_mode(const struct ad7768_state *st,
+ unsigned int freq)
+{
+ for (unsigned int mode_idx = 0;
+ mode_idx < ARRAY_SIZE(ad7768_power_modes); mode_idx++) {
+ if (ad7768_find_freq_config(st, mode_idx, freq))
+ return true;
+ }
+
+ return false;
+}
+
+static int ad7768_set_sampling_freq(struct iio_dev *indio_dev,
+ unsigned int freq, unsigned int channel)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ if (!freq || !ad7768_freq_supported_in_any_mode(st, freq))
+ return -EINVAL;
+
+ guard(mutex)(&st->lock);
+ st->ch_freq[channel] = freq;
+
+ return 0;
+}
+
static int ad7768_find_matching_mode(const bool *mode_used,
const unsigned int *mode_freq,
unsigned int freq)
@@ -656,21 +687,74 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long info)
{
struct ad7768_state *st = iio_priv(indio_dev);
- unsigned int vref_idx;
- if (info != IIO_CHAN_INFO_SCALE)
+ switch (info) {
+ case IIO_CHAN_INFO_SCALE: {
+ unsigned int vref_idx;
+
+ vref_idx = chan->channel >= st->chip_info->num_channels / 2;
+ *val = 2 * st->vref_uV[vref_idx] / 1000;
+ *val2 = chan->scan_type.realbits;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ: {
+ guard(mutex)(&st->lock);
+ *val = st->ch_freq[chan->channel];
+
+ return IIO_VAL_INT;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7768_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long info)
+{
+ if (info == IIO_CHAN_INFO_SAMP_FREQ)
+ return IIO_VAL_INT;
+
+ return -EINVAL;
+}
+
+static int ad7768_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ if (IIO_DEV_ACQUIRE_FAILED(claim))
+ return -EBUSY;
+
+ if (info == IIO_CHAN_INFO_SAMP_FREQ)
+ return ad7768_set_sampling_freq(indio_dev, val, chan->channel);
+
+ return -EINVAL;
+}
+
+static int ad7768_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long info)
+{
+ struct ad7768_state *st = iio_priv(indio_dev);
+
+ if (info != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
- vref_idx = chan->channel >= st->chip_info->num_channels / 2;
- *val = 2 * st->vref_uV[vref_idx] / 1000;
- *val2 = chan->scan_type.realbits;
+ *vals = st->freqs;
+ *type = IIO_VAL_INT;
+ *length = st->n_freqs;
- return IIO_VAL_FRACTIONAL_LOG2;
+ return IIO_AVAIL_LIST;
}
static const struct iio_info ad7768_info = {
.debugfs_reg_access = ad7768_reg_access,
.read_raw = ad7768_read_raw,
+ .write_raw_get_fmt = ad7768_write_raw_get_fmt,
+ .write_raw = ad7768_write_raw,
+ .read_avail = ad7768_read_avail,
.update_scan_mode = ad7768_update_scan_mode,
};
@@ -743,6 +827,21 @@ static void ad7768_set_available_sampling_freqs(struct ad7768_state *st)
if (st->datalines == 1 &&
st->chip_info->num_channels == AD7768_MAX_CHANNEL)
st->avail_freq[ARRAY_SIZE(ad7768_power_modes) - 1].n_freqs--;
+
+ for (unsigned int mode_idx = 0;
+ mode_idx < ARRAY_SIZE(ad7768_power_modes); mode_idx++) {
+ const struct ad7768_avail_freq *avail_freq;
+
+ avail_freq = &st->avail_freq[mode_idx];
+ for (unsigned int i = 0; i < avail_freq->n_freqs; i++) {
+ unsigned int freq = avail_freq->freq_cfg[i].freq_hz;
+
+ if (st->n_freqs && st->freqs[st->n_freqs - 1] >= freq)
+ continue;
+
+ st->freqs[st->n_freqs++] = freq;
+ }
+ }
}
static int ad7768_init_sampling_freqs(struct ad7768_state *st)
@@ -841,7 +940,10 @@ static int ad7768_parse_config(struct iio_dev *indio_dev,
chan[chan_idx] = (struct iio_chan_spec) {
.type = IIO_VOLTAGE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_separate_available =
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
.indexed = 1,
.channel = channel,
.scan_index = channel,
--
2.43.0