summaryrefslogtreecommitdiff
path: root/drivers/iio/proximity/sx9310.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/proximity/sx9310.c')
-rw-r--r--drivers/iio/proximity/sx9310.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c
index 148f2d862601..940c415ece6b 100644
--- a/drivers/iio/proximity/sx9310.c
+++ b/drivers/iio/proximity/sx9310.c
@@ -75,6 +75,7 @@
#define SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900 0x03
#define SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500 0x05
#define SX9310_REG_PROX_CTRL10 0x1a
+#define SX9310_REG_PROX_CTRL10_HYST_MASK GENMASK(5, 4)
#define SX9310_REG_PROX_CTRL10_HYST_6PCT (0x01 << 4)
#define SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2 0x01
#define SX9310_REG_PROX_CTRL11 0x1b
@@ -149,7 +150,9 @@ static const struct iio_event_spec sx9310_events[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_EITHER,
- .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_VALUE),
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_HYSTERESIS) |
+ BIT(IIO_EV_INFO_VALUE),
},
};
@@ -574,6 +577,30 @@ static int sx9310_read_thresh(struct sx9310_data *data,
return IIO_VAL_INT;
}
+static int sx9310_read_hysteresis(struct sx9310_data *data,
+ const struct iio_chan_spec *chan, int *val)
+{
+ unsigned int regval, pthresh;
+ int ret;
+
+ ret = sx9310_read_thresh(data, chan, &pthresh);
+ if (ret < 0)
+ return ret;
+
+ ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL10, &regval);
+ if (ret)
+ return ret;
+
+ regval = FIELD_GET(SX9310_REG_PROX_CTRL10_HYST_MASK, regval);
+ if (!regval)
+ regval = 5;
+
+ /* regval is at most 5 */
+ *val = pthresh >> (5 - regval);
+
+ return IIO_VAL_INT;
+}
+
static int sx9310_read_event_val(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
@@ -588,6 +615,8 @@ static int sx9310_read_event_val(struct iio_dev *indio_dev,
switch (info) {
case IIO_EV_INFO_VALUE:
return sx9310_read_thresh(data, chan, val);
+ case IIO_EV_INFO_HYSTERESIS:
+ return sx9310_read_hysteresis(data, chan, val);
default:
return -EINVAL;
}
@@ -623,6 +652,35 @@ static int sx9310_write_thresh(struct sx9310_data *data,
return ret;
}
+static int sx9310_write_hysteresis(struct sx9310_data *data,
+ const struct iio_chan_spec *chan, int _val)
+{
+ unsigned int hyst, val = _val;
+ int ret, pthresh;
+
+ ret = sx9310_read_thresh(data, chan, &pthresh);
+ if (ret < 0)
+ return ret;
+
+ if (val == 0)
+ hyst = 0;
+ else if (val == pthresh >> 2)
+ hyst = 3;
+ else if (val == pthresh >> 3)
+ hyst = 2;
+ else if (val == pthresh >> 4)
+ hyst = 1;
+ else
+ return -EINVAL;
+
+ hyst = FIELD_PREP(SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
+ mutex_lock(&data->mutex);
+ ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
+ SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
static int sx9310_write_event_val(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
@@ -638,6 +696,8 @@ static int sx9310_write_event_val(struct iio_dev *indio_dev,
switch (info) {
case IIO_EV_INFO_VALUE:
return sx9310_write_thresh(data, chan, val);
+ case IIO_EV_INFO_HYSTERESIS:
+ return sx9310_write_hysteresis(data, chan, val);
default:
return -EINVAL;
}