summaryrefslogtreecommitdiff
path: root/drivers/iio/proximity
diff options
context:
space:
mode:
authorStephen Boyd <swboyd@chromium.org>2020-10-07 04:17:32 +0300
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2020-10-10 19:38:37 +0300
commit08f0411c48f27703f0db2bd287890fdedf5bef5e (patch)
tree18d7f09018b77cc64c3aa3eb236d0afd35c3bb89 /drivers/iio/proximity
parentad2b473e2ba39b43df4d2cad77ab6130665d8c31 (diff)
downloadlinux-08f0411c48f27703f0db2bd287890fdedf5bef5e.tar.xz
iio: sx9310: Support setting hysteresis values
Add support for setting the hysteresis as a shifted value of a channel's proximity threshold. Each channel can have a different threshold, but the hysteresis applies to all channels as a right shift factor. Therefore, duplicate the hysteresis value across all channels and make it depend on the channel's proximity threshold. This is sort of odd but seems to work in practice as most of the time only one channel is used. Signed-off-by: Stephen Boyd <swboyd@chromium.org> Cc: Daniel Campello <campello@chromium.org> Cc: Lars-Peter Clausen <lars@metafoo.de> Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net> Cc: Douglas Anderson <dianders@chromium.org> Cc: Gwendal Grignou <gwendal@chromium.org> Cc: Evan Green <evgreen@chromium.org> Link: https://lore.kernel.org/r/20201007011735.1346994-4-swboyd@chromium.org Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/proximity')
-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;
}