]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iio: adc: ad7768-1: add multiple scan types to support 16-bits mode
authorJonathan Santos <Jonathan.Santos@analog.com>
Wed, 11 Jun 2025 11:51:11 +0000 (08:51 -0300)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Thu, 26 Jun 2025 18:32:54 +0000 (19:32 +0100)
When the device is configured to decimation x8, only possible in the
sinc5 filter, output data is reduced to 16 bits in order to support
1 MHz of sampling frequency due to clock limitation.

Use multiple scan types feature to enable the driver to switch
scan type at runtime, making it possible to support both 24-bit and
16-bit resolution.

Reviewed-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/08780fd4a59885f1f250759ce655420bd1dbb383.1749569957.git.Jonathan.Santos@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/ad7768-1.c

index 6efecb0e88b668cfb8e395ae34a5fddb2ad7f2cf..55913763313de03f7ac6fa97f09a05b4d84e35e8 100644 (file)
@@ -140,6 +140,15 @@ struct ad7768_clk_configuration {
        enum ad7768_pwrmode pwrmode;
 };
 
+enum ad7768_scan_type {
+       AD7768_SCAN_TYPE_NORMAL,
+       AD7768_SCAN_TYPE_HIGH_SPEED,
+};
+
+static const int ad7768_mclk_div_rates[] = {
+       16, 8, 4, 2,
+};
+
 static const struct ad7768_clk_configuration ad7768_clk_config[] = {
        { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_8, 16,  AD7768_FAST_MODE },
        { AD7768_MCLK_DIV_2, AD7768_DEC_RATE_16, 32,  AD7768_FAST_MODE },
@@ -154,6 +163,22 @@ static const struct ad7768_clk_configuration ad7768_clk_config[] = {
        { AD7768_MCLK_DIV_16, AD7768_DEC_RATE_1024, 16384, AD7768_ECO_MODE },
 };
 
+static const struct iio_scan_type ad7768_scan_type[] = {
+       [AD7768_SCAN_TYPE_NORMAL] = {
+               .sign = 's',
+               .realbits = 24,
+               .storagebits = 32,
+               .shift = 8,
+               .endianness = IIO_BE,
+       },
+       [AD7768_SCAN_TYPE_HIGH_SPEED] = {
+               .sign = 's',
+               .realbits = 16,
+               .storagebits = 16,
+               .endianness = IIO_BE,
+       },
+};
+
 static const struct iio_chan_spec ad7768_channels[] = {
        {
                .type = IIO_VOLTAGE,
@@ -163,13 +188,9 @@ static const struct iio_chan_spec ad7768_channels[] = {
                .indexed = 1,
                .channel = 0,
                .scan_index = 0,
-               .scan_type = {
-                       .sign = 's',
-                       .realbits = 24,
-                       .storagebits = 32,
-                       .shift = 8,
-                       .endianness = IIO_BE,
-               },
+               .has_ext_scan_type = 1,
+               .ext_scan_type = ad7768_scan_type,
+               .num_ext_scan_type = ARRAY_SIZE(ad7768_scan_type),
        },
 };
 
@@ -182,6 +203,7 @@ struct ad7768_state {
        unsigned int vcm_output_sel;
        struct clk *mclk;
        unsigned int mclk_freq;
+       unsigned int dec_rate;
        unsigned int samp_freq;
        struct completion completion;
        struct iio_trigger *trig;
@@ -319,6 +341,15 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev)
        if (ret)
                return ret;
 
+       /*
+        * When the decimation rate is set to x8, the ADC data precision is
+        * reduced from 24 bits to 16 bits. Since the AD7768_REG_ADC_DATA
+        * register provides 24-bit data, the precision is reduced by
+        * right-shifting the read value by 8 bits.
+        */
+       if (st->dec_rate == 8)
+               readval >>= 8;
+
        /*
         * Any SPI configuration of the AD7768-1 can only be
         * performed in continuous conversion mode.
@@ -532,6 +563,8 @@ static int ad7768_set_freq(struct ad7768_state *st,
        if (ret < 0)
                return ret;
 
+       st->dec_rate = ad7768_clk_config[idx].clk_div /
+                      ad7768_mclk_div_rates[ad7768_clk_config[idx].mclk_div];
        st->samp_freq = DIV_ROUND_CLOSEST(st->mclk_freq,
                                          ad7768_clk_config[idx].clk_div);
 
@@ -565,8 +598,13 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
                           int *val, int *val2, long info)
 {
        struct ad7768_state *st = iio_priv(indio_dev);
+       const struct iio_scan_type *scan_type;
        int scale_uv, ret;
 
+       scan_type = iio_get_current_scan_type(indio_dev, chan);
+       if (IS_ERR(scan_type))
+               return PTR_ERR(scan_type);
+
        switch (info) {
        case IIO_CHAN_INFO_RAW:
                if (!iio_device_claim_direct(indio_dev))
@@ -577,7 +615,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
                iio_device_release_direct(indio_dev);
                if (ret < 0)
                        return ret;
-               *val = sign_extend32(ret, chan->scan_type.realbits - 1);
+               *val = sign_extend32(ret, scan_type->realbits - 1);
 
                return IIO_VAL_INT;
 
@@ -587,7 +625,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
                        return scale_uv;
 
                *val = (scale_uv * 2) / 1000;
-               *val2 = chan->scan_type.realbits;
+               *val2 = scan_type->realbits;
 
                return IIO_VAL_FRACTIONAL_LOG2;
 
@@ -631,11 +669,21 @@ static const struct attribute_group ad7768_group = {
        .attrs = ad7768_attributes,
 };
 
+static int ad7768_get_current_scan_type(const struct iio_dev *indio_dev,
+                                       const struct iio_chan_spec *chan)
+{
+       struct ad7768_state *st = iio_priv(indio_dev);
+
+       return st->dec_rate == 8 ?
+              AD7768_SCAN_TYPE_HIGH_SPEED : AD7768_SCAN_TYPE_NORMAL;
+}
+
 static const struct iio_info ad7768_info = {
        .attrs = &ad7768_group,
        .read_raw = &ad7768_read_raw,
        .write_raw = &ad7768_write_raw,
        .read_label = ad7768_read_label,
+       .get_current_scan_type = &ad7768_get_current_scan_type,
        .debugfs_reg_access = &ad7768_reg_access,
 };
 
@@ -690,9 +738,15 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct ad7768_state *st = iio_priv(indio_dev);
+       const struct iio_scan_type *scan_type;
        int ret;
 
-       ret = spi_read(st->spi, &st->data.scan.chan, 3);
+       scan_type = iio_get_current_scan_type(indio_dev, &indio_dev->channels[0]);
+       if (IS_ERR(scan_type))
+               goto out;
+
+       ret = spi_read(st->spi, &st->data.scan.chan,
+                      BITS_TO_BYTES(scan_type->realbits));
        if (ret < 0)
                goto out;