#define AD7192_EXT_FREQ_MHZ_MAX        5120000
 #define AD7192_INT_FREQ_MHZ    4915200
 
+#define AD7192_NO_SYNC_FILTER  1
+#define AD7192_SYNC3_FILTER    3
+#define AD7192_SYNC4_FILTER    4
+
 /* NOTE:
  * The AD7190/2/5 features a dual use data out ready DOUT/RDY output.
  * In order to avoid contentions on the SPI bus, it's therefore necessary
 static int ad7192_setup(struct ad7192_state *st, struct device_node *np)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
-       bool rej60_en, sinc3_en, refin2_en, chop_en;
+       bool rej60_en, refin2_en;
        bool buf_en, bipolar, burnout_curr_en;
        unsigned long long scale_uv;
        int i, ret, id;
        if (rej60_en)
                st->mode |= AD7192_MODE_REJ60;
 
-       sinc3_en = of_property_read_bool(np, "adi,sinc3-filter-enable");
-       if (sinc3_en)
-               st->mode |= AD7192_MODE_SINC3;
-
        refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable");
        if (refin2_en && st->devid != ID_AD7195)
                st->conf |= AD7192_CONF_REFSEL;
 
-       chop_en = of_property_read_bool(np, "adi,chop-enable");
-       if (chop_en) {
-               st->conf |= AD7192_CONF_CHOP;
-               if (sinc3_en)
-                       st->f_order = 3; /* SINC 3rd order */
-               else
-                       st->f_order = 4; /* SINC 4th order */
-       } else {
-               st->f_order = 1;
-       }
+       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)
 
        burnout_curr_en = of_property_read_bool(np,
                                                "adi,burnout-currents-enable");
-       if (burnout_curr_en && buf_en && !chop_en) {
+       if (burnout_curr_en && buf_en) {
                st->conf |= AD7192_CONF_BURN;
        } else if (burnout_curr_en) {
                dev_warn(&st->sd.spi->dev,
        return ret ? ret : len;
 }
 
+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 * AD7192_MODE_RATE(st->mode));
+       freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
+
+       fadc = DIV_ROUND_CLOSEST(st->fclk,
+                                AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode));
+       freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
+
+       fadc = DIV_ROUND_CLOSEST(st->fclk, AD7192_MODE_RATE(st->mode));
+       freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024);
+       freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024);
+}
+
+static ssize_t ad7192_show_filter_avail(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct ad7192_state *st = iio_priv(indio_dev);
+       unsigned int freq_avail[4], i;
+       size_t len = 0;
+
+       ad7192_get_available_filter_freq(st, freq_avail);
+
+       for (i = 0; i < ARRAY_SIZE(freq_avail); i++)
+               len += scnprintf(buf + len, PAGE_SIZE - len,
+                                "%d.%d ", freq_avail[i] / 1000,
+                                freq_avail[i] % 1000);
+
+       buf[len - 1] = '\n';
+
+       return len;
+}
+
+static IIO_DEVICE_ATTR(filter_low_pass_3db_frequency_available,
+                      0444, ad7192_show_filter_avail, NULL, 0);
+
 static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
                       ad7192_show_bridge_switch, ad7192_set,
                       AD7192_REG_GPOCON);
                       AD7192_REG_MODE);
 
 static struct attribute *ad7192_attributes[] = {
+       &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
        &iio_dev_attr_bridge_switch_en.dev_attr.attr,
        &iio_dev_attr_ac_excitation_en.dev_attr.attr,
        NULL
 };
 
 static struct attribute *ad7195_attributes[] = {
+       &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
        &iio_dev_attr_bridge_switch_en.dev_attr.attr,
        NULL
 };
        return unipolar ? 2815 * 2 : 2815;
 }
 
+static int ad7192_set_3db_filter_freq(struct ad7192_state *st,
+                                     int val, int val2)
+{
+       int freq_avail[4], i, ret, freq;
+       unsigned int diff_new, diff_old;
+       int idx = 0;
+
+       diff_old = U32_MAX;
+       freq = val * 1000 + val2;
+
+       ad7192_get_available_filter_freq(st, freq_avail);
+
+       for (i = 0; i < ARRAY_SIZE(freq_avail); i++) {
+               diff_new = abs(freq - freq_avail[i]);
+               if (diff_new < diff_old) {
+                       diff_old = diff_new;
+                       idx = i;
+               }
+       }
+
+       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;
+               break;
+       }
+
+       ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
+       if (ret < 0)
+               return ret;
+
+       return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
+}
+
+static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
+{
+       unsigned int fadc;
+
+       fadc = DIV_ROUND_CLOSEST(st->fclk,
+                                st->f_order * AD7192_MODE_RATE(st->mode));
+
+       if (st->conf & AD7192_CONF_CHOP)
+               return DIV_ROUND_CLOSEST(fadc * 240, 1024);
+       if (st->mode & AD7192_MODE_SINC3)
+               return DIV_ROUND_CLOSEST(fadc * 272, 1024);
+       else
+               return DIV_ROUND_CLOSEST(fadc * 230, 1024);
+}
+
 static int ad7192_read_raw(struct iio_dev *indio_dev,
                           struct iio_chan_spec const *chan,
                           int *val,
                *val = st->fclk /
                        (st->f_order * 1024 * AD7192_MODE_RATE(st->mode));
                return IIO_VAL_INT;
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               *val = ad7192_get_3db_filter_freq(st);
+               *val2 = 1000;
+               return IIO_VAL_FRACTIONAL;
        }
 
        return -EINVAL;
                st->mode |= AD7192_MODE_RATE(div);
                ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
                break;
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000);
+               break;
        default:
                ret = -EINVAL;
        }
                return IIO_VAL_INT_PLUS_NANO;
        case IIO_CHAN_INFO_SAMP_FREQ:
                return IIO_VAL_INT;
+       case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+               return IIO_VAL_INT_PLUS_MICRO;
        default:
                return -EINVAL;
        }
 
        for (i = 0; i < indio_dev->num_channels; i++) {
                *chan = channels[i];
+               chan->info_mask_shared_by_all |=
+                       BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY);
                if (chan->type != IIO_TEMP)
                        chan->info_mask_shared_by_type_available |=
                                BIT(IIO_CHAN_INFO_SCALE);