Commit ad2b473e authored by Stephen Boyd's avatar Stephen Boyd Committed by Jonathan Cameron
Browse files

iio: sx9310: Support setting proximity thresholds



Add support to set the proximity thresholds for each channel.

Signed-off-by: default avatarStephen 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-3-swboyd@chromium.org


Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 227c83fa
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@
#define   SX9310_REG_PROX_CTRL7_AVGNEGFILT_2		(0x01 << 3)
#define   SX9310_REG_PROX_CTRL7_AVGPOSFILT_512		0x05
#define SX9310_REG_PROX_CTRL8				0x18
#define   SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK		GENMASK(7, 3)
#define SX9310_REG_PROX_CTRL9				0x19
#define   SX9310_REG_PROX_CTRL8_9_PTHRESH_28		(0x08 << 3)
#define   SX9310_REG_PROX_CTRL8_9_PTHRESH_96		(0x11 << 3)
@@ -531,6 +532,117 @@ static int sx9310_read_avail(struct iio_dev *indio_dev,
	return -EINVAL;
}

static const unsigned int sx9310_pthresh_codes[] = {
	2, 4, 6, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 72, 80, 88, 96, 112,
	128, 144, 160, 192, 224, 256, 320, 384, 512, 640, 768, 1024, 1536
};

static int sx9310_get_thresh_reg(unsigned int channel)
{
	switch (channel) {
	case 0:
	case 3:
		return SX9310_REG_PROX_CTRL8;
	case 1:
	case 2:
		return SX9310_REG_PROX_CTRL9;
	}

	return -EINVAL;
}

static int sx9310_read_thresh(struct sx9310_data *data,
			      const struct iio_chan_spec *chan, int *val)
{
	unsigned int reg;
	unsigned int regval;
	int ret;

	reg = ret = sx9310_get_thresh_reg(chan->channel);
	if (ret < 0)
		return ret;

	ret = regmap_read(data->regmap, reg, &regval);
	if (ret)
		return ret;

	regval = FIELD_GET(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
	if (regval > ARRAY_SIZE(sx9310_pthresh_codes))
		return -EINVAL;

	*val = sx9310_pthresh_codes[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,
				 enum iio_event_direction dir,
				 enum iio_event_info info, int *val, int *val2)
{
	struct sx9310_data *data = iio_priv(indio_dev);

	if (chan->type != IIO_PROXIMITY)
		return -EINVAL;

	switch (info) {
	case IIO_EV_INFO_VALUE:
		return sx9310_read_thresh(data, chan, val);
	default:
		return -EINVAL;
	}
}

static int sx9310_write_thresh(struct sx9310_data *data,
			       const struct iio_chan_spec *chan, int val)
{
	unsigned int reg;
	unsigned int regval;
	int ret, i;

	reg = ret = sx9310_get_thresh_reg(chan->channel);
	if (ret < 0)
		return ret;

	for (i = 0; i < ARRAY_SIZE(sx9310_pthresh_codes); i++) {
		if (sx9310_pthresh_codes[i] == val) {
			regval = i;
			break;
		}
	}

	if (i == ARRAY_SIZE(sx9310_pthresh_codes))
		return -EINVAL;

	regval = FIELD_PREP(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
	mutex_lock(&data->mutex);
	ret = regmap_update_bits(data->regmap, reg,
				 SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
	mutex_unlock(&data->mutex);

	return ret;
}


static int sx9310_write_event_val(struct iio_dev *indio_dev,
				  const struct iio_chan_spec *chan,
				  enum iio_event_type type,
				  enum iio_event_direction dir,
				  enum iio_event_info info, int val, int val2)
{
	struct sx9310_data *data = iio_priv(indio_dev);

	if (chan->type != IIO_PROXIMITY)
		return -EINVAL;

	switch (info) {
	case IIO_EV_INFO_VALUE:
		return sx9310_write_thresh(data, chan, val);
	default:
		return -EINVAL;
	}
}

static int sx9310_set_samp_freq(struct sx9310_data *data, int val, int val2)
{
	int i, ret;
@@ -744,6 +856,8 @@ static const struct iio_info sx9310_info = {
	.attrs = &sx9310_attribute_group,
	.read_raw = sx9310_read_raw,
	.read_avail = sx9310_read_avail,
	.read_event_value = sx9310_read_event_val,
	.write_event_value = sx9310_write_event_val,
	.write_raw = sx9310_write_raw,
	.read_event_config = sx9310_read_event_config,
	.write_event_config = sx9310_write_event_config,