iio: adc: ad7192: Improve f_order computation
authorAlisa-Dariana Roman <alisa.roman@analog.com>
Sun, 24 Sep 2023 21:51:47 +0000 (00:51 +0300)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Thu, 5 Oct 2023 13:44:06 +0000 (14:44 +0100)
Instead of using the f_order member of ad7192_state, a function that
computes the f_order coefficient makes more sense. This coefficient is a
function of the sinc filter and chop filter states.

Remove f_order member of ad7192_state structure. Instead use
ad7192_compute_f_order function to compute the f_order coefficient
according to the sinc filter and chop filter states passed as
parameters.

Add ad7192_get_f_order function that returns the current f_order
coefficient of the device.

Add ad7192_compute_f_adc function that computes the f_adc value
according to the sinc filter and chop filter states passed as
parameters.

Add ad7192_get_f_adc function that returns the current f_adc value of
the device.

Signed-off-by: Alisa-Dariana Roman <alisa.roman@analog.com>
Link: https://lore.kernel.org/r/20230924215148.102491-3-alisadariana@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/ad7192.c

index 6fe3e7b7a60631e424ba625a0b42c983f3c0e7a4..e0be394ccb346bbcab68cbb914843a6f9950d334 100644 (file)
@@ -179,7 +179,6 @@ struct ad7192_state {
        struct clk                      *mclk;
        u16                             int_vref_mv;
        u32                             fclk;
-       u32                             f_order;
        u32                             mode;
        u32                             conf;
        u32                             scale_avail[8][2];
@@ -419,7 +418,6 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
                st->conf |= AD7192_CONF_REFSEL;
 
        st->conf &= ~AD7192_CONF_CHOP;
-       st->f_order = AD7192_NO_SYNC_FILTER;
 
        buf_en = of_property_read_bool(np, "adi,buffer-enable");
        if (buf_en)
@@ -530,22 +528,60 @@ static ssize_t ad7192_set(struct device *dev,
        return ret ? ret : len;
 }
 
+static int ad7192_compute_f_order(bool sinc3_en, bool chop_en)
+{
+       if (!chop_en)
+               return 1;
+
+       if (sinc3_en)
+               return AD7192_SYNC3_FILTER;
+
+       return AD7192_SYNC4_FILTER;
+}
+
+static int ad7192_get_f_order(struct ad7192_state *st)
+{
+       bool sinc3_en, chop_en;
+
+       sinc3_en = FIELD_GET(AD7192_MODE_SINC3, st->mode);
+       chop_en = FIELD_GET(AD7192_CONF_CHOP, st->conf);
+
+       return ad7192_compute_f_order(sinc3_en, chop_en);
+}
+
+static int ad7192_compute_f_adc(struct ad7192_state *st, bool sinc3_en,
+                               bool chop_en)
+{
+       unsigned int f_order = ad7192_compute_f_order(sinc3_en, chop_en);
+
+       return DIV_ROUND_CLOSEST(st->fclk,
+                                f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+}
+
+static int ad7192_get_f_adc(struct ad7192_state *st)
+{
+       unsigned int f_order = ad7192_get_f_order(st);
+
+       return DIV_ROUND_CLOSEST(st->fclk,
+                                f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+}
+
 static void ad7192_get_available_filter_freq(struct ad7192_state *st,
                                                    int *freq)
 {
        unsigned int fadc;
 
        /* Formulas for filter at page 25 of the datasheet */
-       fadc = DIV_ROUND_CLOSEST(st->fclk,
-                                AD7192_SYNC4_FILTER * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+       fadc = ad7192_compute_f_adc(st, false, true);
        freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
 
-       fadc = DIV_ROUND_CLOSEST(st->fclk,
-                                AD7192_SYNC3_FILTER * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+       fadc = ad7192_compute_f_adc(st, true, true);
        freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
 
-       fadc = DIV_ROUND_CLOSEST(st->fclk, FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+       fadc = ad7192_compute_f_adc(st, false, false);
        freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024);
+
+       fadc = ad7192_compute_f_adc(st, true, false);
        freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024);
 }
 
@@ -628,25 +664,21 @@ static int ad7192_set_3db_filter_freq(struct ad7192_state *st,
 
        switch (idx) {
        case 0:
-               st->f_order = AD7192_SYNC4_FILTER;
                st->mode &= ~AD7192_MODE_SINC3;
 
                st->conf |= AD7192_CONF_CHOP;
                break;
        case 1:
-               st->f_order = AD7192_SYNC3_FILTER;
                st->mode |= AD7192_MODE_SINC3;
 
                st->conf |= AD7192_CONF_CHOP;
                break;
        case 2:
-               st->f_order = AD7192_NO_SYNC_FILTER;
                st->mode &= ~AD7192_MODE_SINC3;
 
                st->conf &= ~AD7192_CONF_CHOP;
                break;
        case 3:
-               st->f_order = AD7192_NO_SYNC_FILTER;
                st->mode |= AD7192_MODE_SINC3;
 
                st->conf &= ~AD7192_CONF_CHOP;
@@ -664,8 +696,7 @@ static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
 {
        unsigned int fadc;
 
-       fadc = DIV_ROUND_CLOSEST(st->fclk,
-                                st->f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+       fadc = ad7192_get_f_adc(st);
 
        if (FIELD_GET(AD7192_CONF_CHOP, st->conf))
                return DIV_ROUND_CLOSEST(fadc * 240, 1024);
@@ -713,8 +744,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
                        *val -= 273 * ad7192_get_temp_scale(unipolar);
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SAMP_FREQ:
-               *val = st->fclk /
-                       (st->f_order * 1024 * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
+               *val = DIV_ROUND_CLOSEST(ad7192_get_f_adc(st), 1024);
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
                *val = ad7192_get_3db_filter_freq(st);
@@ -764,7 +794,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
                        break;
                }
 
-               div = st->fclk / (val * st->f_order * 1024);
+               div = st->fclk / (val * ad7192_get_f_order(st) * 1024);
                if (div < 1 || div > 1023) {
                        ret = -EINVAL;
                        break;