#define AD7150_STATUS_OUT1         (1 << 3)
 #define AD7150_STATUS_OUT2         (1 << 5)
 #define AD7150_CH1_DATA_HIGH       1
-#define AD7150_CH1_DATA_LOW        2
 #define AD7150_CH2_DATA_HIGH       3
-#define AD7150_CH2_DATA_LOW        4
 #define AD7150_CH1_AVG_HIGH        5
-#define AD7150_CH1_AVG_LOW         6
 #define AD7150_CH2_AVG_HIGH        7
-#define AD7150_CH2_AVG_LOW         8
 #define AD7150_CH1_SENSITIVITY     9
 #define AD7150_CH1_THR_HOLD_H      9
 #define AD7150_CH1_TIMEOUT         10
-#define AD7150_CH1_THR_HOLD_L      10
 #define AD7150_CH1_SETUP           11
 #define AD7150_CH2_SENSITIVITY     12
 #define AD7150_CH2_THR_HOLD_H      12
 #define AD7150_CH2_TIMEOUT         13
-#define AD7150_CH2_THR_HOLD_L      13
 #define AD7150_CH2_SETUP           14
 #define AD7150_CFG                 15
 #define AD7150_CFG_FIX             (1 << 7)
 
 #define AD7150_MAX_CONV_MODE       4
 
-/*
- * struct ad7150_chip_info - chip specifc information
+/**
+ * Todo list:
+ * - Review whether old_state usage makes sense.
+ * - get rid of explicit control of conversion mode
  */
 
+/**
+ * struct ad7150_chip_info - instance specific chip data
+ * @client: i2c client for this device
+ * @current_event: device always has one type of event enabled.
+ *     This element stores the event code of the current one.
+ * @threshold: thresholds for simple capacitance value events
+ * @thresh_sensitivity: threshold for simple capacitance offset
+ *     from 'average' value.
+ * @mag_sensitity: threshold for magnitude of capacitance offset from
+ *     from 'average' value.
+ * @thresh_timeout: a timeout, in samples from the moment an
+ *     adaptive threshold event occurs to when the average
+ *     value jumps to current value.
+ * @mag_timeout: a timeout, in sample from the moment an
+ *     adaptive magnitude event occurs to when the average
+ *     value jumps to the current value.
+ * @old_state: store state from previous event, allowing confirmation
+ *     of new condition.
+ * @conversion_mode: the current conversion mode.
+ * @state_lock: ensure consistent state of this structure wrt the
+ *     hardware.
+ */
 struct ad7150_chip_info {
        struct i2c_client *client;
-       bool inter;
-       u16 ch1_threshold;     /* Ch1 Threshold (in fixed threshold mode) */
-       u8  ch1_sensitivity;   /* Ch1 Sensitivity (in adaptive threshold mode) */
-       u8  ch1_timeout;       /* Ch1 Timeout (in adaptive threshold mode) */
-       u8  ch1_setup;
-       u16 ch2_threshold;     /* Ch2 Threshold (in fixed threshold mode) */
-       u8  ch2_sensitivity;   /* Ch1 Sensitivity (in adaptive threshold mode) */
-       u8  ch2_timeout;       /* Ch1 Timeout (in adaptive threshold mode) */
-       u8  ch2_setup;
-       u8  powerdown_timer;
-       char threshold_mode[10]; /* adaptive/fixed threshold mode */
+       u64 current_event;
+       u16 threshold[2][2];
+       u8 thresh_sensitivity[2][2];
+       u8 mag_sensitivity[2][2];
+       u8 thresh_timeout[2][2];
+       u8 mag_timeout[2][2];
        int old_state;
        char *conversion_mode;
+       struct mutex state_lock;
 };
 
 struct ad7150_conversion_mode {
        { "power-down", 3 },
 };
 
-/*
- * ad7150 register access by I2C
- */
-
-static int ad7150_i2c_read(struct ad7150_chip_info *chip, u8 reg, u8 *data, int len)
-{
-       struct i2c_client *client = chip->client;
-       int ret = 0;
-
-       ret = i2c_master_send(client, ®, 1);
-       if (ret < 0) {
-               dev_err(&client->dev, "I2C write error\n");
-               return ret;
-       }
-
-       ret = i2c_master_recv(client, data, len);
-       if (ret < 0) {
-               dev_err(&client->dev, "I2C read error\n");
-               return ret;
-       }
-
-       return ret;
-}
-
-static int ad7150_i2c_write(struct ad7150_chip_info *chip, u8 reg, u8 data)
-{
-       struct i2c_client *client = chip->client;
-       int ret = 0;
-
-       u8 tx[2] = {
-               reg,
-               data,
-       };
-
-       ret = i2c_master_send(client, tx, 2);
-       if (ret < 0)
-               dev_err(&client->dev, "I2C write error\n");
-
-       return ret;
-}
-
 /*
  * sysfs nodes
  */
 
-#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show)                             \
+#define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show)                     \
        IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0)
 #define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store)              \
        IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(_show)                              \
-       IIO_DEVICE_ATTR(available_threshold_modes, S_IRUGO, _show, NULL, 0)
-#define IIO_DEV_ATTR_THRESHOLD_MODE(_mode, _show, _store)              \
-       IIO_DEVICE_ATTR(threshold_mode, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH1_THRESHOLD(_mode, _show, _store)              \
-       IIO_DEVICE_ATTR(ch1_threshold, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH2_THRESHOLD(_mode, _show, _store)              \
-       IIO_DEVICE_ATTR(ch2_threshold, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH1_SENSITIVITY(_mode, _show, _store)             \
-       IIO_DEVICE_ATTR(ch1_sensitivity, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH2_SENSITIVITY(_mode, _show, _store)             \
-       IIO_DEVICE_ATTR(ch2_sensitivity, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH1_TIMEOUT(_mode, _show, _store)         \
-       IIO_DEVICE_ATTR(ch1_timeout, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH2_TIMEOUT(_mode, _show, _store)         \
-       IIO_DEVICE_ATTR(ch2_timeout, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH1_VALUE(_show)          \
-       IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0)
-#define IIO_DEV_ATTR_CH2_VALUE(_show)          \
-       IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0)
-#define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store)           \
-       IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store)              \
-       IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0)
-#define IIO_DEV_ATTR_POWERDOWN_TIMER(_mode, _show, _store)              \
-       IIO_DEVICE_ATTR(powerdown_timer, _mode, _show, _store, 0)
 
 static ssize_t ad7150_show_conversion_modes(struct device *dev,
                struct device_attribute *attr,
        int len = 0;
 
        for (i = 0; i < AD7150_MAX_CONV_MODE; i++)
-               len += sprintf(buf + len, "%s\n", ad7150_conv_mode_table[i].name);
+               len += sprintf(buf + len, "%s\n",
+                              ad7150_conv_mode_table[i].name);
 
        return len;
 }
        struct iio_dev *dev_info = dev_get_drvdata(dev);
        struct ad7150_chip_info *chip = iio_priv(dev_info);
        u8 cfg;
-       int i;
+       int i, ret;
 
-       ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1);
+       ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG);
+       if (ret < 0)
+               return ret;
+       cfg = ret;
 
        for (i = 0; i < AD7150_MAX_CONV_MODE; i++) {
                if (strncmp(buf, ad7150_conv_mode_table[i].name,
-                               strlen(ad7150_conv_mode_table[i].name) - 1) == 0) {
+                               strlen(ad7150_conv_mode_table[i].name) - 1) ==
+                   0) {
                        chip->conversion_mode = ad7150_conv_mode_table[i].name;
                        cfg |= 0x18 | ad7150_conv_mode_table[i].reg_cfg;
-                       ad7150_i2c_write(chip, AD7150_CFG, cfg);
+                       ret = i2c_smbus_write_byte_data(chip->client,
+                                                       AD7150_CFG,
+                                                       cfg);
+                       if (ret < 0)
+                               return ret;
                        return len;
                }
        }
                ad7150_show_conversion_mode,
                ad7150_store_conversion_mode);
 
-static ssize_t ad7150_show_threshold_modes(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       return sprintf(buf, "adaptive\nfixed\n");
-}
-
-static IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(ad7150_show_threshold_modes);
-
-static ssize_t ad7150_show_ch1_value(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       u8 data[2];
-
-       ad7150_i2c_read(chip, AD7150_CH1_DATA_HIGH, data, 2);
-       return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]);
-}
-
-static IIO_DEV_ATTR_CH1_VALUE(ad7150_show_ch1_value);
-
-static ssize_t ad7150_show_ch2_value(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       u8 data[2];
-
-       ad7150_i2c_read(chip, AD7150_CH2_DATA_HIGH, data, 2);
-       return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]);
-}
-
-static IIO_DEV_ATTR_CH2_VALUE(ad7150_show_ch2_value);
-
-static ssize_t ad7150_show_threshold_mode(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "%s\n", chip->threshold_mode);
-}
-
-static ssize_t ad7150_store_threshold_mode(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       u8 cfg;
-
-       ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1);
-
-       if (strncmp(buf, "fixed", 5) == 0) {
-               strcpy(chip->threshold_mode, "fixed");
-               cfg |= AD7150_CFG_FIX;
-               ad7150_i2c_write(chip, AD7150_CFG, cfg);
-
-               return len;
-       } else if (strncmp(buf, "adaptive", 8) == 0) {
-               strcpy(chip->threshold_mode, "adaptive");
-               cfg &= ~AD7150_CFG_FIX;
-               ad7150_i2c_write(chip, AD7150_CFG, cfg);
-
-               return len;
-       }
-
-       dev_err(dev, "not supported threshold mode\n");
-       return -EINVAL;
-}
-
-static IIO_DEV_ATTR_THRESHOLD_MODE(S_IRUGO | S_IWUSR,
-               ad7150_show_threshold_mode,
-               ad7150_store_threshold_mode);
-
-static ssize_t ad7150_show_ch1_threshold(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "%d\n", chip->ch1_threshold);
-}
+static const u8 ad7150_addresses[][6] = {
+       { AD7150_CH1_DATA_HIGH, AD7150_CH1_AVG_HIGH,
+         AD7150_CH1_SETUP, AD7150_CH1_THR_HOLD_H,
+         AD7150_CH1_SENSITIVITY, AD7150_CH1_TIMEOUT },
+       { AD7150_CH2_DATA_HIGH, AD7150_CH2_AVG_HIGH,
+         AD7150_CH2_SETUP, AD7150_CH2_THR_HOLD_H,
+         AD7150_CH2_SENSITIVITY, AD7150_CH2_TIMEOUT },
+};
 
-static ssize_t ad7150_store_ch1_threshold(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+static int ad7150_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long mask)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
        int ret;
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
 
-       ret = strict_strtoul(buf, 10, &data);
-
-       if ((!ret) && (data < 0x10000)) {
-               ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_H, data >> 8);
-               ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_L, data);
-               chip->ch1_threshold = data;
-               return len;
+       switch (mask) {
+       case 0:
+               ret = i2c_smbus_read_word_data(chip->client,
+                                       ad7150_addresses[chan->channel][0]);
+               if (ret < 0)
+                       return ret;
+               *val = swab16(ret);
+               return IIO_VAL_INT;
+       case (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE):
+               ret = i2c_smbus_read_word_data(chip->client,
+                                       ad7150_addresses[chan->channel][1]);
+               if (ret < 0)
+                       return ret;
+               *val = swab16(ret);
+               return IIO_VAL_INT;
+       default:
+               return -EINVAL;
        }
-
-       return -EINVAL;
-}
-
-static IIO_DEV_ATTR_CH1_THRESHOLD(S_IRUGO | S_IWUSR,
-               ad7150_show_ch1_threshold,
-               ad7150_store_ch1_threshold);
-
-static ssize_t ad7150_show_ch2_threshold(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "%d\n", chip->ch2_threshold);
 }
 
-static ssize_t ad7150_store_ch2_threshold(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
        int ret;
+       u8 threshtype;
+       bool adaptive;
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+                       IIO_EV_DIR_RISING);
 
-       ret = strict_strtoul(buf, 10, &data);
-
-       if ((!ret) && (data < 0x10000)) {
-               ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_H, data >> 8);
-               ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_L, data);
-               chip->ch2_threshold = data;
-               return len;
-       }
+       ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG);
+       if (ret < 0)
+               return ret;
 
+       threshtype = (ret >> 5) & 0x03;
+       adaptive = !!(ret & 0x80);
+
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               if (rising)
+                       return adaptive && (threshtype == 0x1);
+               else
+                       return adaptive && (threshtype == 0x0);
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               if (rising)
+                       return adaptive && (threshtype == 0x3);
+               else
+                       return adaptive && (threshtype == 0x2);
+
+       case IIO_EV_TYPE_THRESH:
+               if (rising)
+                       return !adaptive && (threshtype == 0x1);
+               else
+                       return !adaptive && (threshtype == 0x0);
+       };
        return -EINVAL;
 }
 
-static IIO_DEV_ATTR_CH2_THRESHOLD(S_IRUGO | S_IWUSR,
-               ad7150_show_ch2_threshold,
-               ad7150_store_ch2_threshold);
-
-static ssize_t ad7150_show_ch1_sensitivity(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "%d\n", chip->ch1_sensitivity);
-}
-
-static ssize_t ad7150_store_ch1_sensitivity(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+/* lock should be held */
+static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
        int ret;
+       u16 value;
+       u8 sens, timeout;
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
+       int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+                       IIO_EV_DIR_RISING);
+
+       if (event_code != chip->current_event)
+               return 0;
+
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+               /* Note completely different from the adaptive versions */
+       case IIO_EV_TYPE_THRESH:
+               value = chip->threshold[rising][chan];
+               ret = i2c_smbus_write_word_data(chip->client,
+                                               ad7150_addresses[chan][3],
+                                               swab16(value));
+               if (ret < 0)
+                       return ret;
+               return 0;
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               sens = chip->mag_sensitivity[rising][chan];
+               timeout = chip->mag_timeout[rising][chan];
+               break;
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               sens = chip->thresh_sensitivity[rising][chan];
+               timeout = chip->thresh_timeout[rising][chan];
+               break;
+       default:
+               return -EINVAL;
+       };
+       ret = i2c_smbus_write_byte_data(chip->client,
+                                       ad7150_addresses[chan][4],
+                                       sens);
+       if (ret < 0)
+               return ret;
 
-       ret = strict_strtoul(buf, 10, &data);
-
-       if ((!ret) && (data < 0x100)) {
-               ad7150_i2c_write(chip, AD7150_CH1_SENSITIVITY, data);
-               chip->ch1_sensitivity = data;
-               return len;
-       }
-
-       return -EINVAL;
-}
-
-static IIO_DEV_ATTR_CH1_SENSITIVITY(S_IRUGO | S_IWUSR,
-               ad7150_show_ch1_sensitivity,
-               ad7150_store_ch1_sensitivity);
-
-static ssize_t ad7150_show_ch2_sensitivity(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
+       ret = i2c_smbus_write_byte_data(chip->client,
+                                       ad7150_addresses[chan][5],
+                                       timeout);
+       if (ret < 0)
+               return ret;
 
-       return sprintf(buf, "%d\n", chip->ch2_sensitivity);
+       return 0;
 }
 
-static ssize_t ad7150_store_ch2_sensitivity(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+static int ad7150_write_event_config(struct iio_dev *indio_dev,
+                                    u64 event_code, int state)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
+       u8 thresh_type, cfg, adaptive;
        int ret;
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+                       IIO_EV_DIR_RISING);
 
-       ret = strict_strtoul(buf, 10, &data);
-
-       if ((!ret) && (data < 0x100)) {
-               ad7150_i2c_write(chip, AD7150_CH2_SENSITIVITY, data);
-               chip->ch2_sensitivity = data;
-               return len;
-       }
-
-       return -EINVAL;
-}
-
-static IIO_DEV_ATTR_CH2_SENSITIVITY(S_IRUGO | S_IWUSR,
-               ad7150_show_ch2_sensitivity,
-               ad7150_store_ch2_sensitivity);
-
-static ssize_t ad7150_show_ch1_timeout(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "%d\n", chip->ch1_timeout);
-}
+       /* Something must always be turned on */
+       if (state == 0)
+               return -EINVAL;
 
-static ssize_t ad7150_store_ch1_timeout(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
-       int ret;
+       if (event_code == chip->current_event)
+               return 0;
+       mutex_lock(&chip->state_lock);
+       ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG);
+       if (ret < 0)
+               goto error_ret;
 
-       ret = strict_strtoul(buf, 10, &data);
+       cfg = ret & ~((0x03 << 5) | (0x1 << 7));
+
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               adaptive = 1;
+               if (rising)
+                       thresh_type = 0x1;
+               else
+                       thresh_type = 0x0;
+               break;
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               adaptive = 1;
+               if (rising)
+                       thresh_type = 0x3;
+               else
+                       thresh_type = 0x2;
+               break;
+       case IIO_EV_TYPE_THRESH:
+               adaptive = 0;
+               if (rising)
+                       thresh_type = 0x1;
+               else
+                       thresh_type = 0x0;
+               break;
+       default:
+               ret = -EINVAL;
+               goto error_ret;
+       };
 
-       if ((!ret) && (data < 0x100)) {
-               ad7150_i2c_write(chip, AD7150_CH1_TIMEOUT, data);
-               chip->ch1_timeout = data;
-               return len;
-       }
+       cfg |= (!adaptive << 7) | (thresh_type << 5);
 
-       return -EINVAL;
-}
+       ret = i2c_smbus_write_byte_data(chip->client, AD7150_CFG, cfg);
+       if (ret < 0)
+               goto error_ret;
 
-static IIO_DEV_ATTR_CH1_TIMEOUT(S_IRUGO | S_IWUSR,
-               ad7150_show_ch1_timeout,
-               ad7150_store_ch1_timeout);
+       chip->current_event = event_code;
 
-static ssize_t ad7150_show_ch2_timeout(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
+       /* update control attributes */
+       ret = ad7150_write_event_params(indio_dev, event_code);
+error_ret:
+       mutex_unlock(&chip->state_lock);
 
-       return sprintf(buf, "%d\n", chip->ch2_timeout);
+       return 0;
 }
 
-static ssize_t ad7150_store_ch2_timeout(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+static int ad7150_read_event_value(struct iio_dev *indio_dev,
+                                  u64 event_code,
+                                  int *val)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &data);
+       int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+                       IIO_EV_DIR_RISING);
 
-       if ((!ret) && (data < 0x100)) {
-               ad7150_i2c_write(chip, AD7150_CH2_TIMEOUT, data);
-               chip->ch2_timeout = data;
-               return len;
-       }
+       /* Complex register sharing going on here */
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               *val = chip->mag_sensitivity[rising][chan];
+               return 0;
 
-       return -EINVAL;
-}
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               *val = chip->thresh_sensitivity[rising][chan];
+               return 0;
 
-static IIO_DEV_ATTR_CH2_TIMEOUT(S_IRUGO | S_IWUSR,
-               ad7150_show_ch2_timeout,
-               ad7150_store_ch2_timeout);
+       case IIO_EV_TYPE_THRESH:
+               *val = chip->threshold[rising][chan];
+               return 0;
 
-static ssize_t ad7150_show_ch1_setup(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "0x%02x\n", chip->ch1_setup);
+       default:
+               return -EINVAL;
+       };
 }
 
-static ssize_t ad7150_store_ch1_setup(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
+static int ad7150_write_event_value(struct iio_dev *indio_dev,
+                                  u64 event_code,
+                                  int val)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
        int ret;
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
+       int chan = IIO_EVENT_CODE_EXTRACT_NUM(event_code);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
+                       IIO_EV_DIR_RISING);
+
+       mutex_lock(&chip->state_lock);
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               chip->mag_sensitivity[rising][chan] = val;
+               break;
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               chip->thresh_sensitivity[rising][chan] = val;
+               break;
+       case IIO_EV_TYPE_THRESH:
+               chip->threshold[rising][chan] = val;
+               break;
+       default:
+               ret = -EINVAL;
+               goto error_ret;
+       };
 
-       ret = strict_strtoul(buf, 10, &data);
-
-       if ((!ret) && (data < 0x100)) {
-               ad7150_i2c_write(chip, AD7150_CH1_SETUP, data);
-               chip->ch1_setup = data;
-               return len;
-       }
-
+       /* write back if active */
+       ret = ad7150_write_event_params(indio_dev, event_code);
 
-       return -EINVAL;
+       mutex_unlock(&chip->state_lock);
+error_ret:
+       return ret;
 }
 
-static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR,
-               ad7150_show_ch1_setup,
-               ad7150_store_ch1_setup);
-
-static ssize_t ad7150_show_ch2_setup(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
+static ssize_t ad7150_show_timeout(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
 {
        struct iio_dev *dev_info = dev_get_drvdata(dev);
        struct ad7150_chip_info *chip = iio_priv(dev_info);
+       struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+       u8 value;
+
+       /* use the event code for consistency reasons */
+       int chan = IIO_EVENT_CODE_EXTRACT_NUM(this_attr->address);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address)
+                       == IIO_EV_DIR_RISING);
+
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) {
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               value = chip->mag_timeout[rising][chan];
+               break;
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               value = chip->thresh_timeout[rising][chan];
+               break;
+       default:
+               return -EINVAL;
+       };
 
-       return sprintf(buf, "0x%02x\n", chip->ch2_setup);
+       return sprintf(buf, "%d\n", value);
 }
 
-static ssize_t ad7150_store_ch2_setup(struct device *dev,
+static ssize_t ad7150_store_timeout(struct device *dev,
                struct device_attribute *attr,
                const char *buf,
                size_t len)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct ad7150_chip_info *chip = iio_priv(indio_dev);
+       struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+       int chan = IIO_EVENT_CODE_EXTRACT_NUM(this_attr->address);
+       int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) ==
+                       IIO_EV_DIR_RISING);
+       u8 data;
        int ret;
 
-       ret = strict_strtoul(buf, 10, &data);
-
-       if ((!ret) && (data < 0x100)) {
-               ad7150_i2c_write(chip, AD7150_CH2_SETUP, data);
-               chip->ch2_setup = data;
-               return len;
-       }
-
-       return -EINVAL;
-}
-
-static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR,
-               ad7150_show_ch2_setup,
-               ad7150_store_ch2_setup);
-
-static ssize_t ad7150_show_powerdown_timer(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-
-       return sprintf(buf, "0x%02x\n", chip->powerdown_timer);
-}
+       ret = kstrtou8(buf, 10, &data);
+       if (ret < 0)
+               return ret;
 
-static ssize_t ad7150_store_powerdown_timer(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t len)
-{
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct ad7150_chip_info *chip = iio_priv(dev_info);
-       unsigned long data;
-       int ret;
+       mutex_lock(&chip->state_lock);
+       switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) {
+       case IIO_EV_TYPE_MAG_ADAPTIVE:
+               chip->mag_timeout[rising][chan] = data;
+               break;
+       case IIO_EV_TYPE_THRESH_ADAPTIVE:
+               chip->thresh_timeout[rising][chan] = data;
+               break;
+       default:
+               ret = -EINVAL;
+               goto error_ret;
+       };
 
-       ret = strict_strtoul(buf, 10, &data);
+       ret = ad7150_write_event_params(indio_dev, this_attr->address);
+error_ret:
+       mutex_unlock(&chip->state_lock);
 
-       if ((!ret) && (data < 0x40)) {
-               chip->powerdown_timer = data;
-               return len;
-       }
+       if (ret < 0)
+               return ret;
 
-       return -EINVAL;
+       return len;
 }
 
-static IIO_DEV_ATTR_POWERDOWN_TIMER(S_IRUGO | S_IWUSR,
-               ad7150_show_powerdown_timer,
-               ad7150_store_powerdown_timer);
+#define AD7150_TIMEOUT(chan, type, dir, ev_type, ev_dir)               \
+       IIO_DEVICE_ATTR(in_capacitance##chan##_##type##_##dir##_timeout, \
+               S_IRUGO | S_IWUSR,                                      \
+               &ad7150_show_timeout,                                   \
+               &ad7150_store_timeout,                                  \
+               IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE,                   \
+                                    chan,                              \
+                                    IIO_EV_TYPE_##ev_type,             \
+                                    IIO_EV_DIR_##ev_dir))
+static AD7150_TIMEOUT(0, mag_adaptive, rising, MAG_ADAPTIVE, RISING);
+static AD7150_TIMEOUT(0, mag_adaptive, falling, MAG_ADAPTIVE, FALLING);
+static AD7150_TIMEOUT(1, mag_adaptive, rising, MAG_ADAPTIVE, RISING);
+static AD7150_TIMEOUT(1, mag_adaptive, falling, MAG_ADAPTIVE, FALLING);
+static AD7150_TIMEOUT(0, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING);
+static AD7150_TIMEOUT(0, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING);
+static AD7150_TIMEOUT(1, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING);
+static AD7150_TIMEOUT(1, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING);
+
+static const struct iio_chan_spec ad7150_channels[] = {
+       {
+               .type = IIO_CAPACITANCE,
+               .indexed = 1,
+               .channel = 0,
+               .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE),
+               .event_mask =
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_RISING) |
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_FALLING) |
+               IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_RISING) |
+               IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_FALLING)
+       }, {
+               .type = IIO_CAPACITANCE,
+               .indexed = 1,
+               .channel = 1,
+               .info_mask = (1 << IIO_CHAN_INFO_AVERAGE_RAW_SEPARATE),
+               .event_mask =
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_RISING) |
+               IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_FALLING) |
+               IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_RISING) |
+               IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_FALLING)
+       },
+};
 
 static struct attribute *ad7150_attributes[] = {
        &iio_dev_attr_available_conversion_modes.dev_attr.attr,
        &iio_dev_attr_conversion_mode.dev_attr.attr,
-       &iio_dev_attr_available_threshold_modes.dev_attr.attr,
-       &iio_dev_attr_threshold_mode.dev_attr.attr,
-       &iio_dev_attr_ch1_threshold.dev_attr.attr,
-       &iio_dev_attr_ch2_threshold.dev_attr.attr,
-       &iio_dev_attr_ch1_timeout.dev_attr.attr,
-       &iio_dev_attr_ch2_timeout.dev_attr.attr,
-       &iio_dev_attr_ch1_setup.dev_attr.attr,
-       &iio_dev_attr_ch2_setup.dev_attr.attr,
-       &iio_dev_attr_ch1_sensitivity.dev_attr.attr,
-       &iio_dev_attr_ch2_sensitivity.dev_attr.attr,
-       &iio_dev_attr_powerdown_timer.dev_attr.attr,
-       &iio_dev_attr_ch1_value.dev_attr.attr,
-       &iio_dev_attr_ch2_value.dev_attr.attr,
        NULL,
 };
 
        struct ad7150_chip_info *chip = iio_priv(indio_dev);
        u8 int_status;
        s64 timestamp = iio_get_time_ns();
+       int ret;
 
-       ad7150_i2c_read(chip, AD7150_STATUS, &int_status, 1);
+       ret = i2c_smbus_read_byte_data(chip->client, AD7150_STATUS);
+       if (ret < 0)
+               return IRQ_HANDLED;
+
+       int_status = ret;
 
        if ((int_status & AD7150_STATUS_OUT1) &&
            !(chip->old_state & AD7150_STATUS_OUT1))
                                                    IIO_EV_TYPE_THRESH,
                                                    IIO_EV_DIR_FALLING),
                               timestamp);
+       /* store the status to avoid repushing same events */
+       chip->old_state = int_status;
+
        return IRQ_HANDLED;
 }
 
-static IIO_CONST_ATTR(ch1_high_en, "1");
-static IIO_CONST_ATTR(ch2_high_en, "1");
-static IIO_CONST_ATTR(ch1_low_en, "1");
-static IIO_CONST_ATTR(ch2_low_en, "1");
-
+/* Timeouts not currently handled by core */
 static struct attribute *ad7150_event_attributes[] = {
-       &iio_const_attr_ch1_high_en.dev_attr.attr,
-       &iio_const_attr_ch2_high_en.dev_attr.attr,
-       &iio_const_attr_ch1_low_en.dev_attr.attr,
-       &iio_const_attr_ch2_low_en.dev_attr.attr,
+       &iio_dev_attr_in_capacitance0_mag_adaptive_rising_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance0_mag_adaptive_falling_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance1_mag_adaptive_rising_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance1_mag_adaptive_falling_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance0_thresh_adaptive_rising_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance0_thresh_adaptive_falling_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance1_thresh_adaptive_rising_timeout
+       .dev_attr.attr,
+       &iio_dev_attr_in_capacitance1_thresh_adaptive_falling_timeout
+       .dev_attr.attr,
        NULL,
 };
 
        .attrs = &ad7150_attribute_group,
        .event_attrs = &ad7150_event_attribute_group,
        .driver_module = THIS_MODULE,
+       .read_raw = &ad7150_read_raw,
+       .read_event_config = &ad7150_read_event_config,
+       .write_event_config = &ad7150_write_event_config,
+       .read_event_value = &ad7150_read_event_value,
+       .write_event_value = &ad7150_write_event_value,
 };
+
 /*
  * device probe and remove
  */
                goto error_ret;
        }
        chip = iio_priv(indio_dev);
+       mutex_init(&chip->state_lock);
        /* this is only used for device removal purposes */
        i2c_set_clientdata(client, indio_dev);
 
        chip->client = client;
 
-       /* Establish that the iio_dev is a child of the i2c device */
        indio_dev->name = id->name;
+       indio_dev->channels = ad7150_channels;
+       indio_dev->num_channels = ARRAY_SIZE(ad7150_channels);
+       /* Establish that the iio_dev is a child of the i2c device */
        indio_dev->dev.parent = &client->dev;
 
        indio_dev->info = &ad7150_info;
        if (ret)
                goto error_free_irq;
 
-
-       dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq);
+       dev_info(&client->dev, "%s capacitive sensor registered,irq: %d\n",
+                id->name, client->irq);
 
        return 0;
 error_free_irq: