linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200
@ 2023-05-09 14:01 Astrid Rost
  2023-05-09 14:01 ` [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200 Astrid Rost
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="No", Size: 1599 bytes --]

Add a more complete support for vncl4040 and vcnl4200, which allows to
change the distance of proximity detection and interrupt support for the
illumination sensor.

Proximity:
  - Interrupt support (new on vcnl4200).
  - Adaptable integration time (new on vcnl4200) - the sampling rate
    changes according to this value.
  - Debounce times - interrupt is asserted if the value is above or
    below a certain threshold.
  - Oversampling ratio - Amount of LED pulses per measurement.
  - Calibration bias - LED current calibration of the sensor.
Illumination:
  - Interrupt support.
  - Adaptable integration time - the sampling rate and scale changes
    according to this value.
  - Debounce times – interrupt is asserted if the value is above or
    below a certain threshold.

changes v2:
- [PATCH v2 3/7] Fixed calculation of al_scale.
  Fix the value of vcnl4040 according to the data-sheet.
  Use div_u64 for the division.

Astrid Rost (7):
  [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200
  [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it for vcnl4200
  [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200
  [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200
  [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200
  [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200
  [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias for 4040/4200

 drivers/iio/light/vcnl4000.c | 723 +++++++++++++++++++++++++++++++----
 1 file changed, 654 insertions(+), 69 deletions(-)

--
2.30.2


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-13 18:57   ` Jonathan Cameron
  2023-05-09 14:01 ` [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it " Astrid Rost
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

Add proximity interrupt support for vcnl4200 (similar to vcnl4040).
Add support to configure proximity sensor interrupts and threshold
limits. If an interrupt is detected an event will be pushed to the
event interface.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 56d3963d3d66..13568454baff 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -65,6 +65,7 @@
 #define VCNL4200_PS_DATA	0x08 /* Proximity data */
 #define VCNL4200_AL_DATA	0x09 /* Ambient light data */
 #define VCNL4040_INT_FLAGS	0x0b /* Interrupt register */
+#define VCNL4200_INT_FLAGS	0x0d /* Interrupt register */
 #define VCNL4200_DEV_ID		0x0e /* Device ID, slave address and version */
 
 #define VCNL4040_DEV_ID		0x0c /* Device ID and version */
@@ -1004,8 +1005,14 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
 	struct iio_dev *indio_dev = p;
 	struct vcnl4000_data *data = iio_priv(indio_dev);
 	int ret;
+	int reg;
 
-	ret = i2c_smbus_read_word_data(data->client, VCNL4040_INT_FLAGS);
+	if (data->id == VCNL4200)
+		reg = VCNL4200_INT_FLAGS;
+	else
+		reg = VCNL4040_INT_FLAGS;
+
+	ret = i2c_smbus_read_word_data(data->client, reg);
 	if (ret < 0)
 		return IRQ_HANDLED;
 
@@ -1321,9 +1328,10 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
 		.measure_light = vcnl4200_measure_light,
 		.measure_proximity = vcnl4200_measure_proximity,
 		.set_power_state = vcnl4200_set_power_state,
-		.channels = vcnl4000_channels,
+		.channels = vcnl4040_channels,
 		.num_channels = ARRAY_SIZE(vcnl4000_channels),
-		.info = &vcnl4000_info,
+		.info = &vcnl4040_info,
+		.irq_thread = vcnl4040_irq_thread,
 	},
 };
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it for vcnl4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
  2023-05-09 14:01 ` [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200 Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-14 17:24   ` Jonathan Cameron
  2023-05-09 14:01 ` [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200 Astrid Rost
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

Add ps_it attributes for vcnl4200 (similar to vcnl4040).
Add read/write attribute for proximity integration time.
Read attribute for available proximity integration times.
Change sampling rate depending on integration time.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 52 +++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 13568454baff..e14475070ac3 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -124,6 +124,15 @@ static const int vcnl4040_ps_it_times[][2] = {
 	{0, 800},
 };
 
+static const int vcnl4200_ps_it_times[][2] = {
+	{0, 96},
+	{0, 144},
+	{0, 192},
+	{0, 384},
+	{0, 768},
+	{0, 864},
+};
+
 #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
 
 enum vcnl4000_device_ids {
@@ -500,6 +509,16 @@ static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
 static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
 {
 	int ret;
+	const int(*ps_it_times)[][2];
+	int size;
+
+	if (data->id == VCNL4200) {
+		ps_it_times = &vcnl4200_ps_it_times;
+		size = ARRAY_SIZE(vcnl4200_ps_it_times);
+	} else {
+		ps_it_times = &vcnl4040_ps_it_times;
+		size = ARRAY_SIZE(vcnl4040_ps_it_times);
+	}
 
 	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
 	if (ret < 0)
@@ -507,11 +526,11 @@ static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
 
 	ret = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
 
-	if (ret >= ARRAY_SIZE(vcnl4040_ps_it_times))
+	if (ret >= size)
 		return -EINVAL;
 
-	*val = vcnl4040_ps_it_times[ret][0];
-	*val2 = vcnl4040_ps_it_times[ret][1];
+	*val = (*ps_it_times)[ret][0];
+	*val2 = (*ps_it_times)[ret][1];
 
 	return 0;
 }
@@ -521,9 +540,19 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
 	unsigned int i;
 	int ret, index = -1;
 	u16 regval;
+	const int(*ps_it_times)[][2];
+	int size;
 
-	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_it_times); i++) {
-		if (val == vcnl4040_ps_it_times[i][1]) {
+	if (data->id == VCNL4200) {
+		ps_it_times = &vcnl4200_ps_it_times;
+		size = ARRAY_SIZE(vcnl4200_ps_it_times);
+	} else {
+		ps_it_times = &vcnl4040_ps_it_times;
+		size = ARRAY_SIZE(vcnl4040_ps_it_times);
+	}
+
+	for (i = 0; i < size; i++) {
+		if (val == (*ps_it_times)[i][1]) {
 			index = i;
 			break;
 		}
@@ -532,6 +561,8 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
 	if (index < 0)
 		return -EINVAL;
 
+	data->vcnl4200_ps.sampling_rate = ktime_set(0, val * 60000);
+
 	mutex_lock(&data->vcnl4000_lock);
 
 	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
@@ -619,11 +650,18 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
 			       const int **vals, int *type, int *length,
 			       long mask)
 {
+	struct vcnl4000_data *data = iio_priv(indio_dev);
+
 	switch (mask) {
 	case IIO_CHAN_INFO_INT_TIME:
-		*vals = (int *)vcnl4040_ps_it_times;
+		if (data->id == VCNL4200) {
+			*vals = (int *)vcnl4200_ps_it_times;
+			*length = 2 * ARRAY_SIZE(vcnl4200_ps_it_times);
+		} else {
+			*vals = (int *)vcnl4040_ps_it_times;
+			*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
+		}
 		*type = IIO_VAL_INT_PLUS_MICRO;
-		*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
 		return IIO_AVAIL_LIST;
 	default:
 		return -EINVAL;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
  2023-05-09 14:01 ` [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200 Astrid Rost
  2023-05-09 14:01 ` [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it " Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-14 17:28   ` Jonathan Cameron
  2023-05-09 14:01 ` [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200 Astrid Rost
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="No", Size: 6234 bytes --]

Add illumination integration time for vcnl4040 and vcnl4200.
Add read/write attribute for illumination integration time and read
attribute for available integration times.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 147 ++++++++++++++++++++++++++++++++---
 1 file changed, 135 insertions(+), 12 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index e14475070ac3..d7445b6755fa 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -80,6 +80,7 @@
 #define VCNL4000_SELF_TIMED_EN	BIT(0) /* start self-timed measurement */
 
 #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
+#define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
 #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
 #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
 #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
@@ -133,6 +134,20 @@ static const int vcnl4200_ps_it_times[][2] = {
 	{0, 864},
 };
 
+static const int vcnl4040_als_it_times[][2] = {
+	{0, 80000},
+	{0, 160000},
+	{0, 320000},
+	{0, 640000},
+};
+
+static const int vcnl4200_als_it_times[][2] = {
+	{0, 50000},
+	{0, 100000},
+	{0, 200000},
+	{0, 400000},
+};
+
 #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
 
 enum vcnl4000_device_ids {
@@ -334,7 +349,7 @@ static int vcnl4200_init(struct vcnl4000_data *data)
 		data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
 		/* Default wait time is 5ms, add 20% tolerance. */
 		data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
-		data->al_scale = 120000;
+		data->al_scale = 100000;
 		break;
 	}
 	mutex_init(&data->vcnl4200_al.lock);
@@ -506,6 +521,85 @@ static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
 	return ret;
 }
 
+static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2)
+{
+	int ret;
+	const int(*als_it_times)[][2];
+	int size;
+
+	if (data->id == VCNL4200) {
+		als_it_times = &vcnl4200_als_it_times;
+		size = ARRAY_SIZE(vcnl4200_als_it_times);
+	} else {
+		als_it_times = &vcnl4040_als_it_times;
+		size = ARRAY_SIZE(vcnl4040_als_it_times);
+	}
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
+	if (ret < 0)
+		return ret;
+
+	ret = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
+
+	if (ret >= size)
+		return -EINVAL;
+
+	*val = (*als_it_times)[ret][0];
+	*val2 = (*als_it_times)[ret][1];
+
+	return 0;
+}
+
+static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val)
+{
+	unsigned int i;
+	int ret, index = -1;
+	u16 regval;
+	const int(*als_it_times)[][2];
+	int size;
+
+	if (data->id == VCNL4200) {
+		als_it_times = &vcnl4200_als_it_times;
+		size = ARRAY_SIZE(vcnl4200_als_it_times);
+	} else {
+		als_it_times = &vcnl4040_als_it_times;
+		size = ARRAY_SIZE(vcnl4040_als_it_times);
+	}
+
+	for (i = 0; i < size; i++) {
+		if (val == (*als_it_times)[i][1]) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index < 0)
+		return -EINVAL;
+
+	data->vcnl4200_al.sampling_rate = ktime_set(0, val * 1200000);
+	if (data->id == VCNL4200)
+		/* 24000 µlux/step * 50000 µs / val  */
+		data->al_scale = div_u64(1200000000, val);
+	else
+		/* 100000 µlux/step * 80000 µs / val */
+		data->al_scale = div_u64(8000000000, val);
+
+	mutex_lock(&data->vcnl4000_lock);
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
+	if (ret < 0)
+		goto out;
+
+	regval = (ret & ~VCNL4040_ALS_CONF_IT) |
+	    FIELD_PREP(VCNL4040_ALS_CONF_IT, index);
+	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
+					regval);
+
+out:
+	mutex_unlock(&data->vcnl4000_lock);
+	return ret;
+}
+
 static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
 {
 	int ret;
@@ -616,9 +710,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 		*val2 = data->al_scale;
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_INT_TIME:
-		if (chan->type != IIO_PROXIMITY)
+		switch (chan->type) {
+		case IIO_LIGHT:
+			ret = vcnl4040_read_als_it(data, val, val2);
+			break;
+		case IIO_PROXIMITY:
+			ret = vcnl4040_read_ps_it(data, val, val2);
+			break;
+		default:
 			return -EINVAL;
-		ret = vcnl4040_read_ps_it(data, val, val2);
+		}
 		if (ret < 0)
 			return ret;
 		return IIO_VAL_INT_PLUS_MICRO;
@@ -637,9 +738,14 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_INT_TIME:
 		if (val != 0)
 			return -EINVAL;
-		if (chan->type != IIO_PROXIMITY)
+		switch (chan->type) {
+		case IIO_LIGHT:
+			return vcnl4040_write_als_it(data, val2);
+		case IIO_PROXIMITY:
+			return vcnl4040_write_ps_it(data, val2);
+		default:
 			return -EINVAL;
-		return vcnl4040_write_ps_it(data, val2);
+		}
 	default:
 		return -EINVAL;
 	}
@@ -654,12 +760,27 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_INT_TIME:
-		if (data->id == VCNL4200) {
-			*vals = (int *)vcnl4200_ps_it_times;
-			*length = 2 * ARRAY_SIZE(vcnl4200_ps_it_times);
-		} else {
-			*vals = (int *)vcnl4040_ps_it_times;
-			*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
+		switch (chan->type) {
+		case IIO_LIGHT:
+			if (data->id == VCNL4200) {
+				*vals = (int *)vcnl4200_als_it_times;
+				*length = 2 * ARRAY_SIZE(vcnl4200_als_it_times);
+			} else {
+				*vals = (int *)vcnl4040_als_it_times;
+				*length = 2 * ARRAY_SIZE(vcnl4040_als_it_times);
+			}
+			break;
+		case IIO_PROXIMITY:
+			if (data->id == VCNL4200) {
+				*vals = (int *)vcnl4200_ps_it_times;
+				*length = 2 * ARRAY_SIZE(vcnl4200_ps_it_times);
+			} else {
+				*vals = (int *)vcnl4040_ps_it_times;
+				*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
+			}
+			break;
+		default:
+			return -EINVAL;
 		}
 		*type = IIO_VAL_INT_PLUS_MICRO;
 		return IIO_AVAIL_LIST;
@@ -1289,7 +1410,9 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
 	{
 		.type = IIO_LIGHT,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-			BIT(IIO_CHAN_INFO_SCALE),
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_INT_TIME),
+		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
 	}, {
 		.type = IIO_PROXIMITY,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
                   ` (2 preceding siblings ...)
  2023-05-09 14:01 ` [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200 Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-14 17:31   ` Jonathan Cameron
  2023-05-09 14:01 ` [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200 Astrid Rost
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

Add support to configure illumination sensor interrupts and threshold
limits for vcnl4040 and vcnl4200. If an interrupt is detected an event
will be pushed to the event interface.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 197 ++++++++++++++++++++++++++---------
 1 file changed, 146 insertions(+), 51 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index d7445b6755fa..68eea686b2dc 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -62,6 +62,8 @@
 #define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */
 #define VCNL4040_PS_THDL_LM	0x06 /* Proximity threshold low */
 #define VCNL4040_PS_THDH_LM	0x07 /* Proximity threshold high */
+#define VCNL4040_ALS_THDL_LM	0x02 /* Ambient light threshold low */
+#define VCNL4040_ALS_THDH_LM	0x01 /* Ambient light threshold high */
 #define VCNL4200_PS_DATA	0x08 /* Proximity data */
 #define VCNL4200_AL_DATA	0x09 /* Ambient light data */
 #define VCNL4040_INT_FLAGS	0x0b /* Interrupt register */
@@ -81,11 +83,14 @@
 
 #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
 #define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
+#define VCNL4040_ALS_CONF_INT_EN	BIT(1) /* Ambient light Interrupt enable */
 #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
 #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
 #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
 #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
 #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
+#define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
+#define VCNL4040_ALS_FALLING		BIT(13) /* Ambient Light cross low threshold */
 
 /* Bit masks for interrupt registers. */
 #define VCNL4010_INT_THR_SEL	BIT(0) /* Select threshold interrupt source */
@@ -170,6 +175,7 @@ struct vcnl4000_data {
 	int rev;
 	int al_scale;
 	u8 ps_int;		/* proximity interrupt mode */
+	u8 als_int;		/* ambient light interrupt mode*/
 	const struct vcnl4000_chip_spec *chip_spec;
 	struct mutex vcnl4000_lock;
 	struct vcnl4200_channel vcnl4200_al;
@@ -288,7 +294,7 @@ static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
 	int ret;
 
 	/* Do not power down if interrupts are enabled */
-	if (!on && data->ps_int)
+	if (!on && (data->ps_int || data->als_int))
 		return 0;
 
 	ret = vcnl4000_write_als_enable(data, on);
@@ -333,6 +339,7 @@ static int vcnl4200_init(struct vcnl4000_data *data)
 
 	data->rev = (ret >> 8) & 0xf;
 	data->ps_int = 0;
+	data->als_int = 0;
 
 	data->vcnl4200_al.reg = VCNL4200_AL_DATA;
 	data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
@@ -975,27 +982,45 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev,
 			       enum iio_event_info info,
 			       int *val, int *val2)
 {
-	int ret;
+	int ret = -EINVAL;
 	struct vcnl4000_data *data = iio_priv(indio_dev);
 
-	switch (dir) {
-	case IIO_EV_DIR_RISING:
-		ret = i2c_smbus_read_word_data(data->client,
-					       VCNL4040_PS_THDH_LM);
-		if (ret < 0)
-			return ret;
-		*val = ret;
-		return IIO_VAL_INT;
-	case IIO_EV_DIR_FALLING:
-		ret = i2c_smbus_read_word_data(data->client,
-					       VCNL4040_PS_THDL_LM);
-		if (ret < 0)
-			return ret;
-		*val = ret;
-		return IIO_VAL_INT;
+	switch (chan->type) {
+	case IIO_LIGHT:
+		switch (dir) {
+		case IIO_EV_DIR_RISING:
+			ret = i2c_smbus_read_word_data(data->client,
+						       VCNL4040_ALS_THDH_LM);
+			break;
+		case IIO_EV_DIR_FALLING:
+			ret = i2c_smbus_read_word_data(data->client,
+						       VCNL4040_ALS_THDL_LM);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_PROXIMITY:
+		switch (dir) {
+		case IIO_EV_DIR_RISING:
+			ret = i2c_smbus_read_word_data(data->client,
+						       VCNL4040_PS_THDH_LM);
+			break;
+		case IIO_EV_DIR_FALLING:
+			ret = i2c_smbus_read_word_data(data->client,
+						       VCNL4040_PS_THDL_LM);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
+	if (ret < 0)
+		return ret;
+	*val = ret;
+	return IIO_VAL_INT;
 }
 
 static int vcnl4040_write_event(struct iio_dev *indio_dev,
@@ -1005,25 +1030,43 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev,
 				enum iio_event_info info,
 				int val, int val2)
 {
-	int ret;
+	int ret = -EINVAL;
 	struct vcnl4000_data *data = iio_priv(indio_dev);
-
-	switch (dir) {
-	case IIO_EV_DIR_RISING:
-		ret = i2c_smbus_write_word_data(data->client,
-						VCNL4040_PS_THDH_LM, val);
-		if (ret < 0)
-			return ret;
-		return IIO_VAL_INT;
-	case IIO_EV_DIR_FALLING:
-		ret = i2c_smbus_write_word_data(data->client,
-						VCNL4040_PS_THDL_LM, val);
-		if (ret < 0)
-			return ret;
-		return IIO_VAL_INT;
+	switch (chan->type) {
+	case IIO_LIGHT:
+		switch (dir) {
+		case IIO_EV_DIR_RISING:
+			ret = i2c_smbus_write_word_data(
+				data->client, VCNL4040_ALS_THDH_LM, val);
+			break;
+		case IIO_EV_DIR_FALLING:
+			ret = i2c_smbus_write_word_data(
+				data->client, VCNL4040_ALS_THDL_LM, val);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_PROXIMITY:
+		switch (dir) {
+		case IIO_EV_DIR_RISING:
+			ret = i2c_smbus_write_word_data(
+				data->client, VCNL4040_PS_THDH_LM, val);
+			break;
+		case IIO_EV_DIR_FALLING:
+			ret = i2c_smbus_write_word_data(
+				data->client, VCNL4040_PS_THDL_LM, val);
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
+	if (ret < 0)
+		return ret;
+	return IIO_VAL_INT;
 }
 
 static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
@@ -1115,16 +1158,28 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
 {
 	int ret;
 	struct vcnl4000_data *data = iio_priv(indio_dev);
+	switch (chan->type) {
+	case IIO_LIGHT:
+		ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
+		if (ret < 0)
+			return ret;
 
-	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
-	if (ret < 0)
-		return ret;
+		data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret);
 
-	data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
+		return data->als_int;
+	case IIO_PROXIMITY:
+		ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
+		if (ret < 0)
+			return ret;
+
+		data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
 
-	return (dir == IIO_EV_DIR_RISING) ?
-		FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
-		FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
+		return (dir == IIO_EV_DIR_RISING) ?
+			FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
+			FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
+	default:
+		return -EINVAL;
+	}
 }
 
 static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
@@ -1132,29 +1187,51 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
 				       enum iio_event_type type,
 				       enum iio_event_direction dir, int state)
 {
-	int ret;
+	int ret = -EINVAL;
 	u16 val, mask;
 	struct vcnl4000_data *data = iio_priv(indio_dev);
 
 	mutex_lock(&data->vcnl4000_lock);
 
-	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
-	if (ret < 0)
-		goto out;
+	switch (chan->type) {
+	case IIO_LIGHT:
+		ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
+		if (ret < 0)
+			goto out;
 
-	if (dir == IIO_EV_DIR_RISING)
-		mask = VCNL4040_PS_IF_AWAY;
-	else
-		mask = VCNL4040_PS_IF_CLOSE;
+		mask = VCNL4040_ALS_CONF_INT_EN;
 
-	val = state ? (ret | mask) : (ret & ~mask);
+		val = state ? (ret | mask) : (ret & ~mask);
 
-	data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
-	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val);
+		data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val);
+		ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
+						val);
+		break;
+	case IIO_PROXIMITY:
+
+		ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
+		if (ret < 0)
+			goto out;
+
+		if (dir == IIO_EV_DIR_RISING)
+			mask = VCNL4040_PS_IF_AWAY;
+		else
+			mask = VCNL4040_PS_IF_CLOSE;
+
+		val = state ? (ret | mask) : (ret & ~mask);
+
+		data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
+		ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
+						val);
+		break;
+	default:
+		break;
+	}
 
 out:
 	mutex_unlock(&data->vcnl4000_lock);
-	data->chip_spec->set_power_state(data, data->ps_int != 0);
+	data->chip_spec->set_power_state(data, data->ps_int ||
+						data->als_int);
 
 	return ret;
 }
@@ -1191,6 +1268,22 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
 			       iio_get_time_ns(indio_dev));
 	}
 
+	if (ret & VCNL4040_ALS_FALLING) {
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_FALLING),
+			       iio_get_time_ns(indio_dev));
+	}
+
+	if (ret & VCNL4040_ALS_RISING) {
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_RISING),
+			       iio_get_time_ns(indio_dev));
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -1413,6 +1506,8 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
 			BIT(IIO_CHAN_INFO_SCALE) |
 			BIT(IIO_CHAN_INFO_INT_TIME),
 		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
+		.event_spec = vcnl4000_event_spec,
+		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
 	}, {
 		.type = IIO_PROXIMITY,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
                   ` (3 preceding siblings ...)
  2023-05-09 14:01 ` [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200 Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-14 17:37   ` Jonathan Cameron
  2023-05-09 14:01 ` [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200 Astrid Rost
  2023-05-09 14:01 ` [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias " Astrid Rost
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

Add read/write attribute for proximity and illumination debounce-count
and read attribute for available debounce-counts.
The debounce-count is set in the interrupt persistence flags
(PS_PERS and ALS_PERS). An interrupt will not be asserted if the raw
value is not over (or lower) than the threshold for the set
continued refresh times.
This is supported for vcnl4040 vcnl4200.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 156 ++++++++++++++++++++++++++++++++++-
 1 file changed, 152 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 68eea686b2dc..b8ce4ed6b0bb 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -84,8 +84,10 @@
 #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
 #define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
 #define VCNL4040_ALS_CONF_INT_EN	BIT(1) /* Ambient light Interrupt enable */
+#define VCNL4040_ALS_CONF_PERS	GENMASK(3, 2) /* Ambient interrupt persistence setting */
 #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
 #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
+#define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
 #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
 #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
 #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
@@ -153,6 +155,9 @@ static const int vcnl4200_als_it_times[][2] = {
 	{0, 400000},
 };
 
+static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
+static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
+
 #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
 
 enum vcnl4000_device_ids {
@@ -680,6 +685,106 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
 	return ret;
 }
 
+static ssize_t vcnl4040_read_als_debounce_count(struct vcnl4000_data *data, int *val)
+{
+	int ret;
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
+	if (ret < 0)
+		return ret;
+
+	ret = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret);
+
+	if (ret >= ARRAY_SIZE(vcnl4200_als_it_times))
+		return -EINVAL;
+
+	*val = vcnl4040_als_debounce_count[ret];
+
+	return ret;
+}
+
+static ssize_t vcnl4040_write_als_debounce_count(struct vcnl4000_data *data, int val)
+{
+	unsigned int i;
+	int ret, index = -1;
+	u16 regval;
+
+	for (i = 0; i < ARRAY_SIZE(vcnl4040_als_debounce_count); i++) {
+		if (val == vcnl4040_als_debounce_count[i]) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->vcnl4000_lock);
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
+	if (ret < 0)
+		goto out;
+
+	regval = (ret & ~VCNL4040_ALS_CONF_PERS) |
+	    FIELD_PREP(VCNL4040_ALS_CONF_PERS, index);
+	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
+					regval);
+
+out:
+	mutex_unlock(&data->vcnl4000_lock);
+	return ret;
+}
+
+static ssize_t vcnl4040_read_ps_debounce_count(struct vcnl4000_data *data, int *val)
+{
+	int ret;
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
+	if (ret < 0)
+		return ret;
+
+	ret = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret);
+
+	if (ret >= ARRAY_SIZE(vcnl4200_ps_it_times))
+		return -EINVAL;
+
+	*val = vcnl4040_ps_debounce_count[ret];
+
+	return ret;
+}
+
+static ssize_t vcnl4040_write_ps_debounce_count(struct vcnl4000_data *data, int val)
+{
+	unsigned int i;
+	int ret, index = -1;
+	u16 regval;
+
+	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_debounce_count); i++) {
+		if (val == vcnl4040_ps_debounce_count[i]) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->vcnl4000_lock);
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
+	if (ret < 0)
+		goto out;
+
+	regval = (ret & ~VCNL4040_CONF1_PS_PERS) |
+	    FIELD_PREP(VCNL4040_CONF1_PS_PERS, index);
+	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
+					regval);
+
+out:
+	mutex_unlock(&data->vcnl4000_lock);
+	return ret;
+}
+
 static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val, int *val2, long mask)
@@ -730,6 +835,21 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 		if (ret < 0)
 			return ret;
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			ret = vcnl4040_read_als_debounce_count(data, val);
+			break;
+		case IIO_PROXIMITY:
+			ret = vcnl4040_read_ps_debounce_count(data, val);
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (ret < 0)
+			return ret;
+		return IIO_VAL_INT;
+
 	default:
 		return -EINVAL;
 	}
@@ -753,6 +873,15 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
 		default:
 			return -EINVAL;
 		}
+	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			return vcnl4040_write_als_debounce_count(data, val);
+		case IIO_PROXIMITY:
+			return vcnl4040_write_ps_debounce_count(data, val);
+		default:
+			return -EINVAL;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -791,6 +920,21 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
 		}
 		*type = IIO_VAL_INT_PLUS_MICRO;
 		return IIO_AVAIL_LIST;
+	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			*vals = (int *)vcnl4040_als_debounce_count;
+			*length = ARRAY_SIZE(vcnl4040_als_debounce_count);
+			break;
+		case IIO_PROXIMITY:
+			*vals = (int *)vcnl4040_ps_debounce_count;
+			*length = ARRAY_SIZE(vcnl4040_ps_debounce_count);
+			break;
+		default:
+			return -EINVAL;
+		}
+		*type = IIO_VAL_INT;
+		return IIO_AVAIL_LIST;
 	default:
 		return -EINVAL;
 	}
@@ -1504,15 +1648,19 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
 		.type = IIO_LIGHT,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_SCALE) |
-			BIT(IIO_CHAN_INFO_INT_TIME),
-		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
+			BIT(IIO_CHAN_INFO_INT_TIME) |
+			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
+		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
 		.event_spec = vcnl4000_event_spec,
 		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
 	}, {
 		.type = IIO_PROXIMITY,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-			BIT(IIO_CHAN_INFO_INT_TIME),
-		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
+			BIT(IIO_CHAN_INFO_INT_TIME) |
+			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
+		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
 		.ext_info = vcnl4000_ext_info,
 		.event_spec = vcnl4040_event_spec,
 		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
                   ` (4 preceding siblings ...)
  2023-05-09 14:01 ` [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200 Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-14 17:41   ` Jonathan Cameron
  2023-05-09 14:01 ` [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias " Astrid Rost
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

Add the proximity multi pulse (PS_MPS) as oversampling_ratio.
One raw value is calculated out of the set amount of pulses.
Add read/write attribute for proximity oversampling-ratio and read
attribute for available oversampling-ratio.
This is supported for vcnl4040 and vcnl4200.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 86 +++++++++++++++++++++++++++++++++++-
 1 file changed, 84 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index b8ce4ed6b0bb..1fd1eaaa4620 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -60,6 +60,7 @@
 
 #define VCNL4200_AL_CONF	0x00 /* Ambient light configuration */
 #define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */
+#define VCNL4200_PS_CONF3	0x04 /* Proximity configuration */
 #define VCNL4040_PS_THDL_LM	0x06 /* Proximity threshold low */
 #define VCNL4040_PS_THDH_LM	0x07 /* Proximity threshold high */
 #define VCNL4040_ALS_THDL_LM	0x02 /* Ambient light threshold low */
@@ -89,6 +90,7 @@
 #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
 #define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
 #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
+#define VCNL4040_PS_CONF3_MPS		GENMASK(6, 5) /* Proximity multi pulse number */
 #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
 #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
 #define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
@@ -157,6 +159,7 @@ static const int vcnl4200_als_it_times[][2] = {
 
 static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
 static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
+static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
 
 #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
 
@@ -785,6 +788,56 @@ static ssize_t vcnl4040_write_ps_debounce_count(struct vcnl4000_data *data, int
 	return ret;
 }
 
+static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)
+{
+	int ret;
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
+	if (ret < 0)
+		return ret;
+
+	ret = FIELD_GET(VCNL4040_PS_CONF3_MPS, ret);
+
+	if (ret >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
+		return -EINVAL;
+
+	*val = vcnl4040_ps_oversampling_ratio[ret];
+
+	return ret;
+}
+
+static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)
+{
+	unsigned int i;
+	int ret, index = -1;
+	u16 regval;
+
+	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) {
+		if (val == vcnl4040_ps_oversampling_ratio[i]) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->vcnl4000_lock);
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
+	if (ret < 0)
+		goto out;
+
+	regval = (ret & ~VCNL4040_PS_CONF3_MPS) |
+	    FIELD_PREP(VCNL4040_PS_CONF3_MPS, index);
+	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
+					regval);
+
+out:
+	mutex_unlock(&data->vcnl4000_lock);
+	return ret;
+}
+
 static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val, int *val2, long mask)
@@ -849,6 +902,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 		if (ret < 0)
 			return ret;
 		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			ret = vcnl4040_read_ps_oversampling_ratio(data, val);
+			if (ret < 0)
+				return ret;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
 
 	default:
 		return -EINVAL;
@@ -882,6 +945,13 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
 		default:
 			return -EINVAL;
 		}
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			return vcnl4040_write_ps_oversampling_ratio(data, val);
+		default:
+			return -EINVAL;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -935,6 +1005,16 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
 		}
 		*type = IIO_VAL_INT;
 		return IIO_AVAIL_LIST;
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			*vals = (int *)vcnl4040_ps_oversampling_ratio;
+			*length = ARRAY_SIZE(vcnl4040_ps_oversampling_ratio);
+			*type = IIO_VAL_INT;
+			return IIO_AVAIL_LIST;
+		default:
+			return -EINVAL;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -1658,9 +1738,11 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
 		.type = IIO_PROXIMITY,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_INT_TIME) |
-			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
+			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
 		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
-			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
+			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
 		.ext_info = vcnl4000_ext_info,
 		.event_spec = vcnl4040_event_spec,
 		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias for 4040/4200
  2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
                   ` (5 preceding siblings ...)
  2023-05-09 14:01 ` [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200 Astrid Rost
@ 2023-05-09 14:01 ` Astrid Rost
  2023-05-14 17:44   ` Jonathan Cameron
  6 siblings, 1 reply; 17+ messages in thread
From: Astrid Rost @ 2023-05-09 14:01 UTC (permalink / raw)
  To: Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-iio, linux-kernel, kernel, Astrid Rost

The calibration bias is setting the LED current to change
the detection distance.
Add read/write attribute for proximity calibration bias and read
attribute for available values.
This is supported for vcnl4040 and vcnl4200.

Signed-off-by: Astrid Rost <astrid.rost@axis.com>
---
 drivers/iio/light/vcnl4000.c | 97 ++++++++++++++++++++++++++++++++++--
 1 file changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 1fd1eaaa4620..f0bf078dcdbe 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -91,6 +91,7 @@
 #define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
 #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
 #define VCNL4040_PS_CONF3_MPS		GENMASK(6, 5) /* Proximity multi pulse number */
+#define VCNL4040_PS_MS_LED_I		GENMASK(10, 8) /* Proximity current */
 #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
 #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
 #define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
@@ -157,6 +158,17 @@ static const int vcnl4200_als_it_times[][2] = {
 	{0, 400000},
 };
 
+static const int vcnl4040_ps_calibbias_ua[][2] = {
+	{0, 50000},
+	{0, 75000},
+	{0, 100000},
+	{0, 120000},
+	{0, 140000},
+	{0, 160000},
+	{0, 180000},
+	{0, 200000},
+};
+
 static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
 static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
 static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
@@ -838,6 +850,57 @@ static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data,
 	return ret;
 }
 
+static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2)
+{
+	int ret;
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
+	if (ret < 0)
+		return ret;
+
+	ret = FIELD_GET(VCNL4040_PS_MS_LED_I, ret);
+
+	if (ret >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))
+		return -EINVAL;
+
+	*val = vcnl4040_ps_calibbias_ua[ret][0];
+	*val2 = vcnl4040_ps_calibbias_ua[ret][1];
+
+	return ret;
+}
+
+static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val)
+{
+	unsigned int i;
+	int ret, index = -1;
+	u16 regval;
+
+	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_calibbias_ua); i++) {
+		if (val == vcnl4040_ps_calibbias_ua[i][1]) {
+			index = i;
+			break;
+		}
+	}
+
+	if (index < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->vcnl4000_lock);
+
+	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
+	if (ret < 0)
+		goto out;
+
+	regval = (ret & ~VCNL4040_PS_MS_LED_I) |
+	    FIELD_PREP(VCNL4040_PS_MS_LED_I, index);
+	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
+					regval);
+
+out:
+	mutex_unlock(&data->vcnl4000_lock);
+	return ret;
+}
+
 static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val, int *val2, long mask)
@@ -912,7 +975,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
 		default:
 			return -EINVAL;
 		}
-
+	case IIO_CHAN_INFO_CALIBBIAS:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			ret = vcnl4040_read_ps_calibbias(data, val, val2);
+			if (ret < 0)
+				return ret;
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -952,6 +1024,13 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
 		default:
 			return -EINVAL;
 		}
+	case IIO_CHAN_INFO_CALIBBIAS:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			return vcnl4040_write_ps_calibbias(data, val2);
+		default:
+			return -EINVAL;
+		}
 	default:
 		return -EINVAL;
 	}
@@ -1015,6 +1094,16 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
 		default:
 			return -EINVAL;
 		}
+	case IIO_CHAN_INFO_CALIBBIAS:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			*vals = (int *)vcnl4040_ps_calibbias_ua;
+			*length = 2 * ARRAY_SIZE(vcnl4040_ps_calibbias_ua);
+			*type = IIO_VAL_INT_PLUS_MICRO;
+			return IIO_AVAIL_LIST;
+		default:
+			return -EINVAL;
+	}
 	default:
 		return -EINVAL;
 	}
@@ -1739,10 +1828,12 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_INT_TIME) |
 			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
-			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS),
 		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
 			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
-			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS),
 		.ext_info = vcnl4000_ext_info,
 		.event_spec = vcnl4040_event_spec,
 		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200
  2023-05-09 14:01 ` [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200 Astrid Rost
@ 2023-05-13 18:57   ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-13 18:57 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:47 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> Add proximity interrupt support for vcnl4200 (similar to vcnl4040).
> Add support to configure proximity sensor interrupts and threshold
> limits. If an interrupt is detected an event will be pushed to the
> event interface.
> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
Where possible (and I think it is here) please avoid putting data as code.
That is, move the necessary register address into the
*_chip_spec structure.  That way, if another version of the chip is supported
in future we can simply add the value to the right instance of that structure.
That tends to end up more flexible than if / else / switch statements.

Thanks,

Jonathan

> ---
>  drivers/iio/light/vcnl4000.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index 56d3963d3d66..13568454baff 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -65,6 +65,7 @@
>  #define VCNL4200_PS_DATA	0x08 /* Proximity data */
>  #define VCNL4200_AL_DATA	0x09 /* Ambient light data */
>  #define VCNL4040_INT_FLAGS	0x0b /* Interrupt register */
> +#define VCNL4200_INT_FLAGS	0x0d /* Interrupt register */
>  #define VCNL4200_DEV_ID		0x0e /* Device ID, slave address and version */
>  
>  #define VCNL4040_DEV_ID		0x0c /* Device ID and version */
> @@ -1004,8 +1005,14 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
>  	struct iio_dev *indio_dev = p;
>  	struct vcnl4000_data *data = iio_priv(indio_dev);
>  	int ret;
> +	int reg;
>  
> -	ret = i2c_smbus_read_word_data(data->client, VCNL4040_INT_FLAGS);
> +	if (data->id == VCNL4200)
> +		reg = VCNL4200_INT_FLAGS;
> +	else
> +		reg = VCNL4040_INT_FLAGS;

Prefer this as
	data->chip_spec->int_reg

> +
> +	ret = i2c_smbus_read_word_data(data->client, reg);
>  	if (ret < 0)
>  		return IRQ_HANDLED;
>  
> @@ -1321,9 +1328,10 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
>  		.measure_light = vcnl4200_measure_light,
>  		.measure_proximity = vcnl4200_measure_proximity,
>  		.set_power_state = vcnl4200_set_power_state,
> -		.channels = vcnl4000_channels,
> +		.channels = vcnl4040_channels,
>  		.num_channels = ARRAY_SIZE(vcnl4000_channels),
> -		.info = &vcnl4000_info,
> +		.info = &vcnl4040_info,
> +		.irq_thread = vcnl4040_irq_thread,
>  	},
>  };
>  


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it for vcnl4200
  2023-05-09 14:01 ` [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it " Astrid Rost
@ 2023-05-14 17:24   ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-14 17:24 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:48 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> Add ps_it attributes for vcnl4200 (similar to vcnl4040).
> Add read/write attribute for proximity integration time.
> Read attribute for available proximity integration times.
> Change sampling rate depending on integration time.
> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>

Similar to previous patch, I'd prefer to move away from
code based selection of values for each type of device to data
based - with data stored in the existing chip_spec structures.

Thanks,

Jonathan

> ---
>  drivers/iio/light/vcnl4000.c | 52 +++++++++++++++++++++++++++++++-----
>  1 file changed, 45 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index 13568454baff..e14475070ac3 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -124,6 +124,15 @@ static const int vcnl4040_ps_it_times[][2] = {
>  	{0, 800},
>  };
>  
> +static const int vcnl4200_ps_it_times[][2] = {
> +	{0, 96},
> +	{0, 144},
> +	{0, 192},
> +	{0, 384},
> +	{0, 768},
> +	{0, 864},
> +};
> +
>  #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
>  
>  enum vcnl4000_device_ids {
> @@ -500,6 +509,16 @@ static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
>  static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
>  {
>  	int ret;
> +	const int(*ps_it_times)[][2];
> +	int size;
> +
> +	if (data->id == VCNL4200) {
> +		ps_it_times = &vcnl4200_ps_it_times;
> +		size = ARRAY_SIZE(vcnl4200_ps_it_times);
> +	} else {
> +		ps_it_times = &vcnl4040_ps_it_times;
> +		size = ARRAY_SIZE(vcnl4040_ps_it_times);

See below.  Same points hold (I tend to review upwards as I find it
easier to follow).

> +	}
>  
>  	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
>  	if (ret < 0)
> @@ -507,11 +526,11 @@ static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
>  
>  	ret = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret);
>  
> -	if (ret >= ARRAY_SIZE(vcnl4040_ps_it_times))
> +	if (ret >= size)
>  		return -EINVAL;
>  
> -	*val = vcnl4040_ps_it_times[ret][0];
> -	*val2 = vcnl4040_ps_it_times[ret][1];
> +	*val = (*ps_it_times)[ret][0];
> +	*val2 = (*ps_it_times)[ret][1];
>  
>  	return 0;
>  }
> @@ -521,9 +540,19 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
>  	unsigned int i;
>  	int ret, index = -1;
>  	u16 regval;
> +	const int(*ps_it_times)[][2];
> +	int size;
>  
> -	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_it_times); i++) {
> -		if (val == vcnl4040_ps_it_times[i][1]) {
> +	if (data->id == VCNL4200) {
> +		ps_it_times = &vcnl4200_ps_it_times;

As below. I'd like this to be data in chip_spec rather than code here.
That almost always ends up more flexible and compact in the long run as
support for more parts is added to a driver.

> +		size = ARRAY_SIZE(vcnl4200_ps_it_times);
> +	} else {
> +		ps_it_times = &vcnl4040_ps_it_times;
> +		size = ARRAY_SIZE(vcnl4040_ps_it_times);
> +	}
> +
> +	for (i = 0; i < size; i++) {
> +		if (val == (*ps_it_times)[i][1]) {
>  			index = i;
>  			break;
>  		}
> @@ -532,6 +561,8 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
>  	if (index < 0)
>  		return -EINVAL;
>  
> +	data->vcnl4200_ps.sampling_rate = ktime_set(0, val * 60000);
> +
>  	mutex_lock(&data->vcnl4000_lock);
>  
>  	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> @@ -619,11 +650,18 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>  			       const int **vals, int *type, int *length,
>  			       long mask)
>  {
> +	struct vcnl4000_data *data = iio_priv(indio_dev);
> +
>  	switch (mask) {
>  	case IIO_CHAN_INFO_INT_TIME:
> -		*vals = (int *)vcnl4040_ps_it_times;
> +		if (data->id == VCNL4200) {
> +			*vals = (int *)vcnl4200_ps_it_times;
> +			*length = 2 * ARRAY_SIZE(vcnl4200_ps_it_times);

As for previous, I'd much rather this was 'data' in the chip_spec structure
than code selecting it here.  That is I'd expect it to be arrange so this
part looks like.
		*vals = (int *)data->chip_spec->int_times;
		*length = 2 * data->chip_spec->num_int_times;

> +		} else {
> +			*vals = (int *)vcnl4040_ps_it_times;
> +			*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
> +		}
>  		*type = IIO_VAL_INT_PLUS_MICRO;
> -		*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
>  		return IIO_AVAIL_LIST;
>  	default:
>  		return -EINVAL;


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200
  2023-05-09 14:01 ` [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200 Astrid Rost
@ 2023-05-14 17:28   ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-14 17:28 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:49 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> Add illumination integration time for vcnl4040 and vcnl4200.
> Add read/write attribute for illumination integration time and read
> attribute for available integration times.
> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
> ---
>  drivers/iio/light/vcnl4000.c ø 147 ++++++++++++++++++++++++++++++++---
>  1 file changed, 135 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index e14475070ac3..d7445b6755fa 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -80,6 +80,7 @@
>  #define VCNL4000_SELF_TIMED_EN	BIT(0) /* start self-timed measurement */
>  
>  #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
> +#define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
>  #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
>  #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
>  #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
> @@ -133,6 +134,20 @@ static const int vcnl4200_ps_it_timesÆÅÆ2Å = æ
>  	æ0, 864å,
>  å;
>  
> +static const int vcnl4040_als_it_timesÆÅÆ2Å = æ
> +	æ0, 80000å,

Interesting.  Maybe something went wrong with encoding of this patch?
It's reading very strangely to me.

Content-Type: text/plain; charset="No"
in headers for this one vs previous which ahd
Content-Type: text/plain;

Which 'might' be the cause, I'm not sure.

Reading past the random characters I'm seeing, this has similar form
to earlier patches. I'd like all the chip differences encoded as data, not
as code.

Thanks,

Jonathan



> +	æ0, 160000å,
> +	æ0, 320000å,
> +	æ0, 640000å,
> +å;
> +
> +static const int vcnl4200_als_it_timesÆÅÆ2Å = æ
> +	æ0, 50000å,
> +	æ0, 100000å,
> +	æ0, 200000å,
> +	æ0, 400000å,
> +å;
> +
>  #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
>  
>  enum vcnl4000_device_ids æ
> @@ -334,7 +349,7 @@ static int vcnl4200_init(struct vcnl4000_data *data)
>  		data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
>  		/* Default wait time is 5ms, add 20% tolerance. */
>  		data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
> -		data->al_scale = 120000;
> +		data->al_scale = 100000;
>  		break;
>  	å
>  	mutex_init(&data->vcnl4200_al.lock);
> @@ -506,6 +521,85 @@ static int vcnl4000_set_pm_runtime_state(struct vcnl4000_data *data, bool on)
>  	return ret;
>  å
>  
> +static int vcnl4040_read_als_it(struct vcnl4000_data *data, int *val, int *val2)
> +æ
> +	int ret;
> +	const int(*als_it_times)ÆÅÆ2Å;
> +	int size;
> +
> +	if (data->id == VCNL4200) æ
> +		als_it_times = &vcnl4200_als_it_times;
> +		size = ARRAY_SIZE(vcnl4200_als_it_times);
> +	å else æ
> +		als_it_times = &vcnl4040_als_it_times;
> +		size = ARRAY_SIZE(vcnl4040_als_it_times);
> +	å
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = FIELD_GET(VCNL4040_ALS_CONF_IT, ret);
> +
> +	if (ret >= size)
> +		return -EINVAL;
> +
> +	*val = (*als_it_times)ÆretÅÆ0Å;
> +	*val2 = (*als_it_times)ÆretÅÆ1Å;
> +
> +	return 0;
> +å
> +
> +static ssize_t vcnl4040_write_als_it(struct vcnl4000_data *data, int val)
> +æ
> +	unsigned int i;
> +	int ret, index = -1;
> +	u16 regval;
> +	const int(*als_it_times)ÆÅÆ2Å;
> +	int size;
> +
> +	if (data->id == VCNL4200) æ
> +		als_it_times = &vcnl4200_als_it_times;
> +		size = ARRAY_SIZE(vcnl4200_als_it_times);
> +	å else æ
> +		als_it_times = &vcnl4040_als_it_times;
> +		size = ARRAY_SIZE(vcnl4040_als_it_times);
> +	å
> +
> +	for (i = 0; i < size; i++) æ
> +		if (val == (*als_it_times)ÆiÅÆ1Å) æ
> +			index = i;
> +			break;
> +		å
> +	å
> +
> +	if (index < 0)
> +		return -EINVAL;
> +
> +	data->vcnl4200_al.sampling_rate = ktime_set(0, val * 1200000);
> +	if (data->id == VCNL4200)
> +		/* 24000 __lux/step * 50000 __s / val  */
> +		data->al_scale = div_u64(1200000000, val);
> +	else
> +		/* 100000 __lux/step * 80000 __s / val */
> +		data->al_scale = div_u64(8000000000, val);
> +
> +	mutex_lock(&data->vcnl4000_lock);
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
> +	if (ret < 0)
> +		goto out;
> +
> +	regval = (ret & ‾VCNL4040_ALS_CONF_IT) ø
> +	    FIELD_PREP(VCNL4040_ALS_CONF_IT, index);
> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
> +					regval);
> +
> +out:
> +	mutex_unlock(&data->vcnl4000_lock);
> +	return ret;
> +å
> +
>  static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2)
>  æ
>  	int ret;
> @@ -616,9 +710,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  		*val2 = data->al_scale;
>  		return IIO_VAL_INT_PLUS_MICRO;
>  	case IIO_CHAN_INFO_INT_TIME:
> -		if (chan->type != IIO_PROXIMITY)
> +		switch (chan->type) æ
> +		case IIO_LIGHT:
> +			ret = vcnl4040_read_als_it(data, val, val2);
> +			break;
> +		case IIO_PROXIMITY:
> +			ret = vcnl4040_read_ps_it(data, val, val2);
> +			break;
> +		default:
>  			return -EINVAL;
> -		ret = vcnl4040_read_ps_it(data, val, val2);
> +		å
>  		if (ret < 0)
>  			return ret;
>  		return IIO_VAL_INT_PLUS_MICRO;
> @@ -637,9 +738,14 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
>  	case IIO_CHAN_INFO_INT_TIME:
>  		if (val != 0)
>  			return -EINVAL;
> -		if (chan->type != IIO_PROXIMITY)
> +		switch (chan->type) æ
> +		case IIO_LIGHT:
> +			return vcnl4040_write_als_it(data, val2);
> +		case IIO_PROXIMITY:
> +			return vcnl4040_write_ps_it(data, val2);
> +		default:
>  			return -EINVAL;
> -		return vcnl4040_write_ps_it(data, val2);
> +		å
>  	default:
>  		return -EINVAL;
>  	å
> @@ -654,12 +760,27 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>  
>  	switch (mask) æ
>  	case IIO_CHAN_INFO_INT_TIME:
> -		if (data->id == VCNL4200) æ
> -			*vals = (int *)vcnl4200_ps_it_times;
> -			*length = 2 * ARRAY_SIZE(vcnl4200_ps_it_times);
> -		å else æ
> -			*vals = (int *)vcnl4040_ps_it_times;
> -			*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
> +		switch (chan->type) æ
> +		case IIO_LIGHT:
> +			if (data->id == VCNL4200) æ
> +				*vals = (int *)vcnl4200_als_it_times;
> +				*length = 2 * ARRAY_SIZE(vcnl4200_als_it_times);
> +			å else æ
> +				*vals = (int *)vcnl4040_als_it_times;
> +				*length = 2 * ARRAY_SIZE(vcnl4040_als_it_times);
> +			å
> +			break;
> +		case IIO_PROXIMITY:
> +			if (data->id == VCNL4200) æ
> +				*vals = (int *)vcnl4200_ps_it_times;
> +				*length = 2 * ARRAY_SIZE(vcnl4200_ps_it_times);
> +			å else æ
> +				*vals = (int *)vcnl4040_ps_it_times;
> +				*length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times);
> +			å
> +			break;
> +		default:
> +			return -EINVAL;
>  		å
>  		*type = IIO_VAL_INT_PLUS_MICRO;
>  		return IIO_AVAIL_LIST;
> @@ -1289,7 +1410,9 @@ static const struct iio_chan_spec vcnl4040_channelsÆÅ = æ
>  	æ
>  		.type = IIO_LIGHT,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) ø
> -			BIT(IIO_CHAN_INFO_SCALE),
> +			BIT(IIO_CHAN_INFO_SCALE) ø
> +			BIT(IIO_CHAN_INFO_INT_TIME),
> +		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
>  	å, æ
>  		.type = IIO_PROXIMITY,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) ø


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200
  2023-05-09 14:01 ` [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200 Astrid Rost
@ 2023-05-14 17:31   ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-14 17:31 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:50 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> Add support to configure illumination sensor interrupts and threshold

illuminance? or Ambient light sensor?

Otherwise this looks good to me

Thanks,

Jonathan


> limits for vcnl4040 and vcnl4200. If an interrupt is detected an event
> will be pushed to the event interface.
> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
> ---
>  drivers/iio/light/vcnl4000.c | 197 ++++++++++++++++++++++++++---------
>  1 file changed, 146 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index d7445b6755fa..68eea686b2dc 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -62,6 +62,8 @@
>  #define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */
>  #define VCNL4040_PS_THDL_LM	0x06 /* Proximity threshold low */
>  #define VCNL4040_PS_THDH_LM	0x07 /* Proximity threshold high */
> +#define VCNL4040_ALS_THDL_LM	0x02 /* Ambient light threshold low */
> +#define VCNL4040_ALS_THDH_LM	0x01 /* Ambient light threshold high */
>  #define VCNL4200_PS_DATA	0x08 /* Proximity data */
>  #define VCNL4200_AL_DATA	0x09 /* Ambient light data */
>  #define VCNL4040_INT_FLAGS	0x0b /* Interrupt register */
> @@ -81,11 +83,14 @@
>  
>  #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
>  #define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
> +#define VCNL4040_ALS_CONF_INT_EN	BIT(1) /* Ambient light Interrupt enable */
>  #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
>  #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
>  #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
>  #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
>  #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
> +#define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
> +#define VCNL4040_ALS_FALLING		BIT(13) /* Ambient Light cross low threshold */
>  
>  /* Bit masks for interrupt registers. */
>  #define VCNL4010_INT_THR_SEL	BIT(0) /* Select threshold interrupt source */
> @@ -170,6 +175,7 @@ struct vcnl4000_data {
>  	int rev;
>  	int al_scale;
>  	u8 ps_int;		/* proximity interrupt mode */
> +	u8 als_int;		/* ambient light interrupt mode*/
>  	const struct vcnl4000_chip_spec *chip_spec;
>  	struct mutex vcnl4000_lock;
>  	struct vcnl4200_channel vcnl4200_al;
> @@ -288,7 +294,7 @@ static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on)
>  	int ret;
>  
>  	/* Do not power down if interrupts are enabled */
> -	if (!on && data->ps_int)
> +	if (!on && (data->ps_int || data->als_int))
>  		return 0;
>  
>  	ret = vcnl4000_write_als_enable(data, on);
> @@ -333,6 +339,7 @@ static int vcnl4200_init(struct vcnl4000_data *data)
>  
>  	data->rev = (ret >> 8) & 0xf;
>  	data->ps_int = 0;
> +	data->als_int = 0;
>  
>  	data->vcnl4200_al.reg = VCNL4200_AL_DATA;
>  	data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
> @@ -975,27 +982,45 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev,
>  			       enum iio_event_info info,
>  			       int *val, int *val2)
>  {
> -	int ret;
> +	int ret = -EINVAL;
>  	struct vcnl4000_data *data = iio_priv(indio_dev);
>  
> -	switch (dir) {
> -	case IIO_EV_DIR_RISING:
> -		ret = i2c_smbus_read_word_data(data->client,
> -					       VCNL4040_PS_THDH_LM);
> -		if (ret < 0)
> -			return ret;
> -		*val = ret;
> -		return IIO_VAL_INT;
> -	case IIO_EV_DIR_FALLING:
> -		ret = i2c_smbus_read_word_data(data->client,
> -					       VCNL4040_PS_THDL_LM);
> -		if (ret < 0)
> -			return ret;
> -		*val = ret;
> -		return IIO_VAL_INT;
> +	switch (chan->type) {
> +	case IIO_LIGHT:
> +		switch (dir) {
> +		case IIO_EV_DIR_RISING:
> +			ret = i2c_smbus_read_word_data(data->client,
> +						       VCNL4040_ALS_THDH_LM);
> +			break;
> +		case IIO_EV_DIR_FALLING:
> +			ret = i2c_smbus_read_word_data(data->client,
> +						       VCNL4040_ALS_THDL_LM);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		break;
> +	case IIO_PROXIMITY:
> +		switch (dir) {
> +		case IIO_EV_DIR_RISING:
> +			ret = i2c_smbus_read_word_data(data->client,
> +						       VCNL4040_PS_THDH_LM);
> +			break;
> +		case IIO_EV_DIR_FALLING:
> +			ret = i2c_smbus_read_word_data(data->client,
> +						       VCNL4040_PS_THDL_LM);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		break;
>  	default:
>  		return -EINVAL;
>  	}
> +	if (ret < 0)
> +		return ret;
> +	*val = ret;
> +	return IIO_VAL_INT;
>  }
>  
>  static int vcnl4040_write_event(struct iio_dev *indio_dev,
> @@ -1005,25 +1030,43 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev,
>  				enum iio_event_info info,
>  				int val, int val2)
>  {
> -	int ret;
> +	int ret = -EINVAL;
>  	struct vcnl4000_data *data = iio_priv(indio_dev);
> -
> -	switch (dir) {
> -	case IIO_EV_DIR_RISING:
> -		ret = i2c_smbus_write_word_data(data->client,
> -						VCNL4040_PS_THDH_LM, val);
> -		if (ret < 0)
> -			return ret;
> -		return IIO_VAL_INT;
> -	case IIO_EV_DIR_FALLING:
> -		ret = i2c_smbus_write_word_data(data->client,
> -						VCNL4040_PS_THDL_LM, val);
> -		if (ret < 0)
> -			return ret;
> -		return IIO_VAL_INT;
> +	switch (chan->type) {
> +	case IIO_LIGHT:
> +		switch (dir) {
> +		case IIO_EV_DIR_RISING:
> +			ret = i2c_smbus_write_word_data(
> +				data->client, VCNL4040_ALS_THDH_LM, val);
> +			break;
> +		case IIO_EV_DIR_FALLING:
> +			ret = i2c_smbus_write_word_data(
> +				data->client, VCNL4040_ALS_THDL_LM, val);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		break;
> +	case IIO_PROXIMITY:
> +		switch (dir) {
> +		case IIO_EV_DIR_RISING:
> +			ret = i2c_smbus_write_word_data(
> +				data->client, VCNL4040_PS_THDH_LM, val);
> +			break;
> +		case IIO_EV_DIR_FALLING:
> +			ret = i2c_smbus_write_word_data(
> +				data->client, VCNL4040_PS_THDL_LM, val);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		break;
>  	default:
>  		return -EINVAL;
>  	}
> +	if (ret < 0)
> +		return ret;
> +	return IIO_VAL_INT;
>  }
>  
>  static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data)
> @@ -1115,16 +1158,28 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
>  {
>  	int ret;
>  	struct vcnl4000_data *data = iio_priv(indio_dev);
> +	switch (chan->type) {
> +	case IIO_LIGHT:
> +		ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
> +		if (ret < 0)
> +			return ret;
>  
> -	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> -	if (ret < 0)
> -		return ret;
> +		data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret);
>  
> -	data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
> +		return data->als_int;
> +	case IIO_PROXIMITY:
> +		ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> +		if (ret < 0)
> +			return ret;
> +
> +		data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, ret);
>  
> -	return (dir == IIO_EV_DIR_RISING) ?
> -		FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
> -		FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
> +		return (dir == IIO_EV_DIR_RISING) ?
> +			FIELD_GET(VCNL4040_PS_IF_AWAY, ret) :
> +			FIELD_GET(VCNL4040_PS_IF_CLOSE, ret);
> +	default:
> +		return -EINVAL;
> +	}
>  }
>  
>  static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
> @@ -1132,29 +1187,51 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
>  				       enum iio_event_type type,
>  				       enum iio_event_direction dir, int state)
>  {
> -	int ret;
> +	int ret = -EINVAL;
>  	u16 val, mask;
>  	struct vcnl4000_data *data = iio_priv(indio_dev);
>  
>  	mutex_lock(&data->vcnl4000_lock);
>  
> -	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> -	if (ret < 0)
> -		goto out;
> +	switch (chan->type) {
> +	case IIO_LIGHT:
> +		ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
> +		if (ret < 0)
> +			goto out;
>  
> -	if (dir == IIO_EV_DIR_RISING)
> -		mask = VCNL4040_PS_IF_AWAY;
> -	else
> -		mask = VCNL4040_PS_IF_CLOSE;
> +		mask = VCNL4040_ALS_CONF_INT_EN;
>  
> -	val = state ? (ret | mask) : (ret & ~mask);
> +		val = state ? (ret | mask) : (ret & ~mask);
>  
> -	data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
> -	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, val);
> +		data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, val);
> +		ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
> +						val);
> +		break;
> +	case IIO_PROXIMITY:
> +
> +		ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> +		if (ret < 0)
> +			goto out;
> +
> +		if (dir == IIO_EV_DIR_RISING)
> +			mask = VCNL4040_PS_IF_AWAY;
> +		else
> +			mask = VCNL4040_PS_IF_CLOSE;
> +
> +		val = state ? (ret | mask) : (ret & ~mask);
> +
> +		data->ps_int = FIELD_GET(VCNL4040_PS_CONF2_PS_INT, val);
> +		ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
> +						val);
> +		break;
> +	default:
> +		break;
> +	}
>  
>  out:
>  	mutex_unlock(&data->vcnl4000_lock);
> -	data->chip_spec->set_power_state(data, data->ps_int != 0);
> +	data->chip_spec->set_power_state(data, data->ps_int ||
> +						data->als_int);
>  
>  	return ret;
>  }
> @@ -1191,6 +1268,22 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
>  			       iio_get_time_ns(indio_dev));
>  	}
>  
> +	if (ret & VCNL4040_ALS_FALLING) {
> +		iio_push_event(indio_dev,
> +			       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
> +						    IIO_EV_TYPE_THRESH,
> +						    IIO_EV_DIR_FALLING),
> +			       iio_get_time_ns(indio_dev));
> +	}
> +
> +	if (ret & VCNL4040_ALS_RISING) {
> +		iio_push_event(indio_dev,
> +			       IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
> +						    IIO_EV_TYPE_THRESH,
> +						    IIO_EV_DIR_RISING),
> +			       iio_get_time_ns(indio_dev));
> +	}
> +
>  	return IRQ_HANDLED;
>  }
>  
> @@ -1413,6 +1506,8 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
>  			BIT(IIO_CHAN_INFO_SCALE) |
>  			BIT(IIO_CHAN_INFO_INT_TIME),
>  		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
> +		.event_spec = vcnl4000_event_spec,
> +		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
>  	}, {
>  		.type = IIO_PROXIMITY,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200
  2023-05-09 14:01 ` [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200 Astrid Rost
@ 2023-05-14 17:37   ` Jonathan Cameron
  2023-05-15 15:00     ` Astrid Rost
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-14 17:37 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:51 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> Add read/write attribute for proximity and illumination debounce-count
> and read attribute for available debounce-counts.
> The debounce-count is set in the interrupt persistence flags
> (PS_PERS and ALS_PERS). An interrupt will not be asserted if the raw
> value is not over (or lower) than the threshold for the set
> continued refresh times.
> This is supported for vcnl4040 vcnl4200.

Why debounce count? That has previously just been used for step detection
on accelerometers and has a pretty specific definition in
See Documentation/ABI/testing/sysfs-bus-iio

"
What:		/sys/.../iio:deviceX/in_steps_debounce_count
...
		Specifies the number of steps that must occur within
		in_steps_filter_debounce_time for the pedometer to decide the
		consumer is making steps.
"

What you probably want is period, though that is defined in seconds so
you may need some unit conversions.  That is defined for events, not for
a channel so IIO_EV_INFO_PERIOD.
"
		Period of time (in seconds) for which the condition must be
		met before an event is generated. If direction is not
		specified then this period applies to both directions.
"

> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
> ---
>  drivers/iio/light/vcnl4000.c | 156 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 152 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index 68eea686b2dc..b8ce4ed6b0bb 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -84,8 +84,10 @@
>  #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
>  #define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
>  #define VCNL4040_ALS_CONF_INT_EN	BIT(1) /* Ambient light Interrupt enable */
> +#define VCNL4040_ALS_CONF_PERS	GENMASK(3, 2) /* Ambient interrupt persistence setting */
>  #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
>  #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
> +#define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
>  #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
>  #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
>  #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
> @@ -153,6 +155,9 @@ static const int vcnl4200_als_it_times[][2] = {
>  	{0, 400000},
>  };
>  
> +static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
> +static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
> +
>  #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
>  
>  enum vcnl4000_device_ids {
> @@ -680,6 +685,106 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
>  	return ret;
>  }
>  
> +static ssize_t vcnl4040_read_als_debounce_count(struct vcnl4000_data *data, int *val)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret);
> +
> +	if (ret >= ARRAY_SIZE(vcnl4200_als_it_times))
> +		return -EINVAL;
> +
> +	*val = vcnl4040_als_debounce_count[ret];
> +
> +	return ret;
> +}
> +
> +static ssize_t vcnl4040_write_als_debounce_count(struct vcnl4000_data *data, int val)
> +{
> +	unsigned int i;
> +	int ret, index = -1;
> +	u16 regval;
> +
> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_als_debounce_count); i++) {
> +		if (val == vcnl4040_als_debounce_count[i]) {
> +			index = i;
> +			break;
> +		}
> +	}
> +
> +	if (index < 0)
> +		return -EINVAL;
> +
> +	mutex_lock(&data->vcnl4000_lock);
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
> +	if (ret < 0)
> +		goto out;
> +
> +	regval = (ret & ~VCNL4040_ALS_CONF_PERS) |
> +	    FIELD_PREP(VCNL4040_ALS_CONF_PERS, index);
> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
> +					regval);
> +
> +out:
> +	mutex_unlock(&data->vcnl4000_lock);
> +	return ret;
> +}
> +
> +static ssize_t vcnl4040_read_ps_debounce_count(struct vcnl4000_data *data, int *val)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret);
> +
> +	if (ret >= ARRAY_SIZE(vcnl4200_ps_it_times))
> +		return -EINVAL;
> +
> +	*val = vcnl4040_ps_debounce_count[ret];
> +
> +	return ret;
> +}
> +
> +static ssize_t vcnl4040_write_ps_debounce_count(struct vcnl4000_data *data, int val)
> +{
> +	unsigned int i;
> +	int ret, index = -1;
> +	u16 regval;
> +
> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_debounce_count); i++) {
> +		if (val == vcnl4040_ps_debounce_count[i]) {
> +			index = i;
> +			break;
> +		}
> +	}
> +
> +	if (index < 0)
> +		return -EINVAL;
> +
> +	mutex_lock(&data->vcnl4000_lock);
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
> +	if (ret < 0)
> +		goto out;
> +
> +	regval = (ret & ~VCNL4040_CONF1_PS_PERS) |
> +	    FIELD_PREP(VCNL4040_CONF1_PS_PERS, index);
> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
> +					regval);
> +
> +out:
> +	mutex_unlock(&data->vcnl4000_lock);
> +	return ret;
> +}
> +
>  static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  				struct iio_chan_spec const *chan,
>  				int *val, int *val2, long mask)
> @@ -730,6 +835,21 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  		if (ret < 0)
>  			return ret;
>  		return IIO_VAL_INT_PLUS_MICRO;
> +	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
> +		switch (chan->type) {
> +		case IIO_LIGHT:
> +			ret = vcnl4040_read_als_debounce_count(data, val);
> +			break;
> +		case IIO_PROXIMITY:
> +			ret = vcnl4040_read_ps_debounce_count(data, val);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		if (ret < 0)
> +			return ret;
> +		return IIO_VAL_INT;
> +
>  	default:
>  		return -EINVAL;
>  	}
> @@ -753,6 +873,15 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
>  		default:
>  			return -EINVAL;
>  		}
> +	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
> +		switch (chan->type) {
> +		case IIO_LIGHT:
> +			return vcnl4040_write_als_debounce_count(data, val);
> +		case IIO_PROXIMITY:
> +			return vcnl4040_write_ps_debounce_count(data, val);
> +		default:
> +			return -EINVAL;
> +		}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -791,6 +920,21 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>  		}
>  		*type = IIO_VAL_INT_PLUS_MICRO;
>  		return IIO_AVAIL_LIST;
> +	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
> +		switch (chan->type) {
> +		case IIO_LIGHT:
> +			*vals = (int *)vcnl4040_als_debounce_count;
> +			*length = ARRAY_SIZE(vcnl4040_als_debounce_count);
> +			break;
> +		case IIO_PROXIMITY:
> +			*vals = (int *)vcnl4040_ps_debounce_count;
> +			*length = ARRAY_SIZE(vcnl4040_ps_debounce_count);
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +		*type = IIO_VAL_INT;
> +		return IIO_AVAIL_LIST;
>  	default:
>  		return -EINVAL;
>  	}
> @@ -1504,15 +1648,19 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
>  		.type = IIO_LIGHT,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>  			BIT(IIO_CHAN_INFO_SCALE) |
> -			BIT(IIO_CHAN_INFO_INT_TIME),
> -		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
> +			BIT(IIO_CHAN_INFO_INT_TIME) |
> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
> +		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>  		.event_spec = vcnl4000_event_spec,
>  		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
>  	}, {
>  		.type = IIO_PROXIMITY,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
> -			BIT(IIO_CHAN_INFO_INT_TIME),
> -		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
> +			BIT(IIO_CHAN_INFO_INT_TIME) |
> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
> +		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>  		.ext_info = vcnl4000_ext_info,
>  		.event_spec = vcnl4040_event_spec,
>  		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200
  2023-05-09 14:01 ` [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200 Astrid Rost
@ 2023-05-14 17:41   ` Jonathan Cameron
  2023-05-15 14:55     ` Astrid Rost
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-14 17:41 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:52 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> Add the proximity multi pulse (PS_MPS) as oversampling_ratio.
> One raw value is calculated out of the set amount of pulses.
> Add read/write attribute for proximity oversampling-ratio and read
> attribute for available oversampling-ratio.
> This is supported for vcnl4040 and vcnl4200.
> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
Hi Astrid,

I'm finding very little definition in for this Multi pulse setting.
Do we know if it does averaging, or some other form of outlier detection?

For oversampling we'd expect it to be averaging in ordering to improve the SNR.
I have no idea if that is what this feature is doing!

Otherwise code looks fine to me.

Thanks,

Jonathan

> ---
>  drivers/iio/light/vcnl4000.c | 86 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 84 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index b8ce4ed6b0bb..1fd1eaaa4620 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -60,6 +60,7 @@
>  
>  #define VCNL4200_AL_CONF	0x00 /* Ambient light configuration */
>  #define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */
> +#define VCNL4200_PS_CONF3	0x04 /* Proximity configuration */
>  #define VCNL4040_PS_THDL_LM	0x06 /* Proximity threshold low */
>  #define VCNL4040_PS_THDH_LM	0x07 /* Proximity threshold high */
>  #define VCNL4040_ALS_THDL_LM	0x02 /* Ambient light threshold low */
> @@ -89,6 +90,7 @@
>  #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
>  #define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
>  #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
> +#define VCNL4040_PS_CONF3_MPS		GENMASK(6, 5) /* Proximity multi pulse number */
>  #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
>  #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
>  #define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
> @@ -157,6 +159,7 @@ static const int vcnl4200_als_it_times[][2] = {
>  
>  static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
>  static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
> +static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
>  
>  #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
>  
> @@ -785,6 +788,56 @@ static ssize_t vcnl4040_write_ps_debounce_count(struct vcnl4000_data *data, int
>  	return ret;
>  }
>  
> +static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = FIELD_GET(VCNL4040_PS_CONF3_MPS, ret);
> +
> +	if (ret >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
> +		return -EINVAL;
> +
> +	*val = vcnl4040_ps_oversampling_ratio[ret];
> +
> +	return ret;
> +}
> +
> +static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)
> +{
> +	unsigned int i;
> +	int ret, index = -1;
> +	u16 regval;
> +
> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) {
> +		if (val == vcnl4040_ps_oversampling_ratio[i]) {
> +			index = i;
> +			break;
> +		}
> +	}
> +
> +	if (index < 0)
> +		return -EINVAL;
> +
> +	mutex_lock(&data->vcnl4000_lock);
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
> +	if (ret < 0)
> +		goto out;
> +
> +	regval = (ret & ~VCNL4040_PS_CONF3_MPS) |
> +	    FIELD_PREP(VCNL4040_PS_CONF3_MPS, index);
> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
> +					regval);
> +
> +out:
> +	mutex_unlock(&data->vcnl4000_lock);
> +	return ret;
> +}
> +
>  static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  				struct iio_chan_spec const *chan,
>  				int *val, int *val2, long mask)
> @@ -849,6 +902,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  		if (ret < 0)
>  			return ret;
>  		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:
> +			ret = vcnl4040_read_ps_oversampling_ratio(data, val);
> +			if (ret < 0)
> +				return ret;
> +			return IIO_VAL_INT;
> +		default:
> +			return -EINVAL;
> +		}
>  
>  	default:
>  		return -EINVAL;
> @@ -882,6 +945,13 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
>  		default:
>  			return -EINVAL;
>  		}
> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:
> +			return vcnl4040_write_ps_oversampling_ratio(data, val);
> +		default:
> +			return -EINVAL;
> +		}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -935,6 +1005,16 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>  		}
>  		*type = IIO_VAL_INT;
>  		return IIO_AVAIL_LIST;
> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:
> +			*vals = (int *)vcnl4040_ps_oversampling_ratio;
> +			*length = ARRAY_SIZE(vcnl4040_ps_oversampling_ratio);
> +			*type = IIO_VAL_INT;
> +			return IIO_AVAIL_LIST;
> +		default:
> +			return -EINVAL;
> +		}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -1658,9 +1738,11 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
>  		.type = IIO_PROXIMITY,
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>  			BIT(IIO_CHAN_INFO_INT_TIME) |
> -			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
> +			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
>  		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
> -			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
> +			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
>  		.ext_info = vcnl4000_ext_info,
>  		.event_spec = vcnl4040_event_spec,
>  		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias for 4040/4200
  2023-05-09 14:01 ` [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias " Astrid Rost
@ 2023-05-14 17:44   ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2023-05-14 17:44 UTC (permalink / raw)
  To: Astrid Rost; +Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

On Tue, 9 May 2023 16:01:53 +0200
Astrid Rost <astrid.rost@axis.com> wrote:

> The calibration bias is setting the LED current to change
> the detection distance.
> Add read/write attribute for proximity calibration bias and read
> attribute for available values.
> This is supported for vcnl4040 and vcnl4200.
Another interesting mapping onto standard ABI.
I guess it sort of ends up mapping to calibbias so I think I'm fine with this
one if other reviewers agree.

From a quick look (run out of time again today!) this looks fine to me.
Will take another look at v3.

Thanks,

Jonathan

> 
> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
> ---
>  drivers/iio/light/vcnl4000.c | 97 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 94 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
> index 1fd1eaaa4620..f0bf078dcdbe 100644
> --- a/drivers/iio/light/vcnl4000.c
> +++ b/drivers/iio/light/vcnl4000.c
> @@ -91,6 +91,7 @@
>  #define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
>  #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
>  #define VCNL4040_PS_CONF3_MPS		GENMASK(6, 5) /* Proximity multi pulse number */
> +#define VCNL4040_PS_MS_LED_I		GENMASK(10, 8) /* Proximity current */
>  #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
>  #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
>  #define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
> @@ -157,6 +158,17 @@ static const int vcnl4200_als_it_times[][2] = {
>  	{0, 400000},
>  };
>  
> +static const int vcnl4040_ps_calibbias_ua[][2] = {
> +	{0, 50000},
> +	{0, 75000},
> +	{0, 100000},
> +	{0, 120000},
> +	{0, 140000},
> +	{0, 160000},
> +	{0, 180000},
> +	{0, 200000},
> +};
> +
>  static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
>  static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
>  static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
> @@ -838,6 +850,57 @@ static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data,
>  	return ret;
>  }
>  
> +static ssize_t vcnl4040_read_ps_calibbias(struct vcnl4000_data *data, int *val, int *val2)
> +{
> +	int ret;
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = FIELD_GET(VCNL4040_PS_MS_LED_I, ret);
> +
> +	if (ret >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua))
> +		return -EINVAL;
> +
> +	*val = vcnl4040_ps_calibbias_ua[ret][0];
> +	*val2 = vcnl4040_ps_calibbias_ua[ret][1];
> +
> +	return ret;
> +}
> +
> +static ssize_t vcnl4040_write_ps_calibbias(struct vcnl4000_data *data, int val)
> +{
> +	unsigned int i;
> +	int ret, index = -1;
> +	u16 regval;
> +
> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_calibbias_ua); i++) {
> +		if (val == vcnl4040_ps_calibbias_ua[i][1]) {
> +			index = i;
> +			break;
> +		}
> +	}
> +
> +	if (index < 0)
> +		return -EINVAL;
> +
> +	mutex_lock(&data->vcnl4000_lock);
> +
> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
> +	if (ret < 0)
> +		goto out;
> +
> +	regval = (ret & ~VCNL4040_PS_MS_LED_I) |
> +	    FIELD_PREP(VCNL4040_PS_MS_LED_I, index);
> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
> +					regval);
> +
> +out:
> +	mutex_unlock(&data->vcnl4000_lock);
> +	return ret;
> +}
> +
>  static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  				struct iio_chan_spec const *chan,
>  				int *val, int *val2, long mask)
> @@ -912,7 +975,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>  		default:
>  			return -EINVAL;
>  		}
> -
> +	case IIO_CHAN_INFO_CALIBBIAS:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:
> +			ret = vcnl4040_read_ps_calibbias(data, val, val2);
> +			if (ret < 0)
> +				return ret;
> +			return IIO_VAL_INT_PLUS_MICRO;
> +		default:
> +			return -EINVAL;
> +		}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -952,6 +1024,13 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
>  		default:
>  			return -EINVAL;
>  		}
> +	case IIO_CHAN_INFO_CALIBBIAS:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:
> +			return vcnl4040_write_ps_calibbias(data, val2);
> +		default:
> +			return -EINVAL;
> +		}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -1015,6 +1094,16 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>  		default:
>  			return -EINVAL;
>  		}
> +	case IIO_CHAN_INFO_CALIBBIAS:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:
> +			*vals = (int *)vcnl4040_ps_calibbias_ua;
> +			*length = 2 * ARRAY_SIZE(vcnl4040_ps_calibbias_ua);
> +			*type = IIO_VAL_INT_PLUS_MICRO;
> +			return IIO_AVAIL_LIST;
> +		default:
> +			return -EINVAL;
> +	}
>  	default:
>  		return -EINVAL;
>  	}
> @@ -1739,10 +1828,12 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
>  		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>  			BIT(IIO_CHAN_INFO_INT_TIME) |
>  			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
> -			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
> +			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
> +			BIT(IIO_CHAN_INFO_CALIBBIAS),
>  		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
>  			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
> -			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
> +			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
> +			BIT(IIO_CHAN_INFO_CALIBBIAS),
>  		.ext_info = vcnl4000_ext_info,
>  		.event_spec = vcnl4040_event_spec,
>  		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200
  2023-05-14 17:41   ` Jonathan Cameron
@ 2023-05-15 14:55     ` Astrid Rost
  0 siblings, 0 replies; 17+ messages in thread
From: Astrid Rost @ 2023-05-15 14:55 UTC (permalink / raw)
  To: Jonathan Cameron, Astrid Rost
  Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

Hello Jonathan,

Thank you for all your comments, also on the other commits.
I started to fix them all.

Yes true,  there is not much information in the data-sheet.
According to how it behaves it calculates the average of the multiple 
pulses and the SNR is definitely much better after setting the value.
That is why we need this.

Best Regards

Astrid





On 5/14/23 19:41, Jonathan Cameron wrote:
> On Tue, 9 May 2023 16:01:52 +0200
> Astrid Rost <astrid.rost@axis.com> wrote:
> 
>> Add the proximity multi pulse (PS_MPS) as oversampling_ratio.
>> One raw value is calculated out of the set amount of pulses.
>> Add read/write attribute for proximity oversampling-ratio and read
>> attribute for available oversampling-ratio.
>> This is supported for vcnl4040 and vcnl4200.
>>
>> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
> Hi Astrid,
> 
> I'm finding very little definition in for this Multi pulse setting.
> Do we know if it does averaging, or some other form of outlier detection?
> 
> For oversampling we'd expect it to be averaging in ordering to improve the SNR.
> I have no idea if that is what this feature is doing!
> 
> Otherwise code looks fine to me.
> 
> Thanks,
> 
> Jonathan
> 
>> ---
>>   drivers/iio/light/vcnl4000.c | 86 +++++++++++++++++++++++++++++++++++-
>>   1 file changed, 84 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
>> index b8ce4ed6b0bb..1fd1eaaa4620 100644
>> --- a/drivers/iio/light/vcnl4000.c
>> +++ b/drivers/iio/light/vcnl4000.c
>> @@ -60,6 +60,7 @@
>>   
>>   #define VCNL4200_AL_CONF	0x00 /* Ambient light configuration */
>>   #define VCNL4200_PS_CONF1	0x03 /* Proximity configuration */
>> +#define VCNL4200_PS_CONF3	0x04 /* Proximity configuration */
>>   #define VCNL4040_PS_THDL_LM	0x06 /* Proximity threshold low */
>>   #define VCNL4040_PS_THDH_LM	0x07 /* Proximity threshold high */
>>   #define VCNL4040_ALS_THDL_LM	0x02 /* Ambient light threshold low */
>> @@ -89,6 +90,7 @@
>>   #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
>>   #define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
>>   #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
>> +#define VCNL4040_PS_CONF3_MPS		GENMASK(6, 5) /* Proximity multi pulse number */
>>   #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
>>   #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
>>   #define VCNL4040_ALS_RISING		BIT(12) /* Ambient Light cross high threshold */
>> @@ -157,6 +159,7 @@ static const int vcnl4200_als_it_times[][2] = {
>>   
>>   static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
>>   static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
>> +static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8};
>>   
>>   #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
>>   
>> @@ -785,6 +788,56 @@ static ssize_t vcnl4040_write_ps_debounce_count(struct vcnl4000_data *data, int
>>   	return ret;
>>   }
>>   
>> +static ssize_t vcnl4040_read_ps_oversampling_ratio(struct vcnl4000_data *data, int *val)
>> +{
>> +	int ret;
>> +
>> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = FIELD_GET(VCNL4040_PS_CONF3_MPS, ret);
>> +
>> +	if (ret >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio))
>> +		return -EINVAL;
>> +
>> +	*val = vcnl4040_ps_oversampling_ratio[ret];
>> +
>> +	return ret;
>> +}
>> +
>> +static ssize_t vcnl4040_write_ps_oversampling_ratio(struct vcnl4000_data *data, int val)
>> +{
>> +	unsigned int i;
>> +	int ret, index = -1;
>> +	u16 regval;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) {
>> +		if (val == vcnl4040_ps_oversampling_ratio[i]) {
>> +			index = i;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (index < 0)
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&data->vcnl4000_lock);
>> +
>> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
>> +	if (ret < 0)
>> +		goto out;
>> +
>> +	regval = (ret & ~VCNL4040_PS_CONF3_MPS) |
>> +	    FIELD_PREP(VCNL4040_PS_CONF3_MPS, index);
>> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
>> +					regval);
>> +
>> +out:
>> +	mutex_unlock(&data->vcnl4000_lock);
>> +	return ret;
>> +}
>> +
>>   static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>>   				struct iio_chan_spec const *chan,
>>   				int *val, int *val2, long mask)
>> @@ -849,6 +902,16 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>>   		if (ret < 0)
>>   			return ret;
>>   		return IIO_VAL_INT;
>> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
>> +		switch (chan->type) {
>> +		case IIO_PROXIMITY:
>> +			ret = vcnl4040_read_ps_oversampling_ratio(data, val);
>> +			if (ret < 0)
>> +				return ret;
>> +			return IIO_VAL_INT;
>> +		default:
>> +			return -EINVAL;
>> +		}
>>   
>>   	default:
>>   		return -EINVAL;
>> @@ -882,6 +945,13 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
>>   		default:
>>   			return -EINVAL;
>>   		}
>> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
>> +		switch (chan->type) {
>> +		case IIO_PROXIMITY:
>> +			return vcnl4040_write_ps_oversampling_ratio(data, val);
>> +		default:
>> +			return -EINVAL;
>> +		}
>>   	default:
>>   		return -EINVAL;
>>   	}
>> @@ -935,6 +1005,16 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>>   		}
>>   		*type = IIO_VAL_INT;
>>   		return IIO_AVAIL_LIST;
>> +	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
>> +		switch (chan->type) {
>> +		case IIO_PROXIMITY:
>> +			*vals = (int *)vcnl4040_ps_oversampling_ratio;
>> +			*length = ARRAY_SIZE(vcnl4040_ps_oversampling_ratio);
>> +			*type = IIO_VAL_INT;
>> +			return IIO_AVAIL_LIST;
>> +		default:
>> +			return -EINVAL;
>> +		}
>>   	default:
>>   		return -EINVAL;
>>   	}
>> @@ -1658,9 +1738,11 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
>>   		.type = IIO_PROXIMITY,
>>   		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>>   			BIT(IIO_CHAN_INFO_INT_TIME) |
>> -			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
>> +			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
>>   		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
>> -			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) |
>> +			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
>>   		.ext_info = vcnl4000_ext_info,
>>   		.event_spec = vcnl4040_event_spec,
>>   		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200
  2023-05-14 17:37   ` Jonathan Cameron
@ 2023-05-15 15:00     ` Astrid Rost
  0 siblings, 0 replies; 17+ messages in thread
From: Astrid Rost @ 2023-05-15 15:00 UTC (permalink / raw)
  To: Jonathan Cameron, Astrid Rost
  Cc: Lars-Peter Clausen, linux-iio, linux-kernel, kernel

Hello Jonathan,

Thank you!
I will use period instead, but this means it is dependent on integration 
time as well.

Maybe I should try to deliver the first four matching patches and make 
another delivery of the last three.

Astrid



On 5/14/23 19:37, Jonathan Cameron wrote:
> On Tue, 9 May 2023 16:01:51 +0200
> Astrid Rost <astrid.rost@axis.com> wrote:
> 
>> Add read/write attribute for proximity and illumination debounce-count
>> and read attribute for available debounce-counts.
>> The debounce-count is set in the interrupt persistence flags
>> (PS_PERS and ALS_PERS). An interrupt will not be asserted if the raw
>> value is not over (or lower) than the threshold for the set
>> continued refresh times.
>> This is supported for vcnl4040 vcnl4200.
> 
> Why debounce count? That has previously just been used for step detection
> on accelerometers and has a pretty specific definition in
> See Documentation/ABI/testing/sysfs-bus-iio
> 
> "
> What:		/sys/.../iio:deviceX/in_steps_debounce_count
> ...
> 		Specifies the number of steps that must occur within
> 		in_steps_filter_debounce_time for the pedometer to decide the
> 		consumer is making steps.
> "
> 
> What you probably want is period, though that is defined in seconds so
> you may need some unit conversions.  That is defined for events, not for
> a channel so IIO_EV_INFO_PERIOD.
> "
> 		Period of time (in seconds) for which the condition must be
> 		met before an event is generated. If direction is not
> 		specified then this period applies to both directions.
> "
> 
>>
>> Signed-off-by: Astrid Rost <astrid.rost@axis.com>
>> ---
>>   drivers/iio/light/vcnl4000.c | 156 ++++++++++++++++++++++++++++++++++-
>>   1 file changed, 152 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
>> index 68eea686b2dc..b8ce4ed6b0bb 100644
>> --- a/drivers/iio/light/vcnl4000.c
>> +++ b/drivers/iio/light/vcnl4000.c
>> @@ -84,8 +84,10 @@
>>   #define VCNL4040_ALS_CONF_ALS_SHUTDOWN	BIT(0)
>>   #define VCNL4040_ALS_CONF_IT		GENMASK(7, 6) /* Ambient integration time */
>>   #define VCNL4040_ALS_CONF_INT_EN	BIT(1) /* Ambient light Interrupt enable */
>> +#define VCNL4040_ALS_CONF_PERS	GENMASK(3, 2) /* Ambient interrupt persistence setting */
>>   #define VCNL4040_PS_CONF1_PS_SHUTDOWN	BIT(0)
>>   #define VCNL4040_PS_CONF2_PS_IT	GENMASK(3, 1) /* Proximity integration time */
>> +#define VCNL4040_CONF1_PS_PERS	GENMASK(5, 4) /* Proximity interrupt persistence setting */
>>   #define VCNL4040_PS_CONF2_PS_INT	GENMASK(9, 8) /* Proximity interrupt mode */
>>   #define VCNL4040_PS_IF_AWAY		BIT(8) /* Proximity event cross low threshold */
>>   #define VCNL4040_PS_IF_CLOSE		BIT(9) /* Proximity event cross high threshold */
>> @@ -153,6 +155,9 @@ static const int vcnl4200_als_it_times[][2] = {
>>   	{0, 400000},
>>   };
>>   
>> +static const int vcnl4040_als_debounce_count[] = {1, 2, 4, 8};
>> +static const int vcnl4040_ps_debounce_count[] = {1, 2, 3, 4};
>> +
>>   #define VCNL4000_SLEEP_DELAY_MS	2000 /* before we enter pm_runtime_suspend */
>>   
>>   enum vcnl4000_device_ids {
>> @@ -680,6 +685,106 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val)
>>   	return ret;
>>   }
>>   
>> +static ssize_t vcnl4040_read_als_debounce_count(struct vcnl4000_data *data, int *val)
>> +{
>> +	int ret;
>> +
>> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret);
>> +
>> +	if (ret >= ARRAY_SIZE(vcnl4200_als_it_times))
>> +		return -EINVAL;
>> +
>> +	*val = vcnl4040_als_debounce_count[ret];
>> +
>> +	return ret;
>> +}
>> +
>> +static ssize_t vcnl4040_write_als_debounce_count(struct vcnl4000_data *data, int val)
>> +{
>> +	unsigned int i;
>> +	int ret, index = -1;
>> +	u16 regval;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_als_debounce_count); i++) {
>> +		if (val == vcnl4040_als_debounce_count[i]) {
>> +			index = i;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (index < 0)
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&data->vcnl4000_lock);
>> +
>> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF);
>> +	if (ret < 0)
>> +		goto out;
>> +
>> +	regval = (ret & ~VCNL4040_ALS_CONF_PERS) |
>> +	    FIELD_PREP(VCNL4040_ALS_CONF_PERS, index);
>> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF,
>> +					regval);
>> +
>> +out:
>> +	mutex_unlock(&data->vcnl4000_lock);
>> +	return ret;
>> +}
>> +
>> +static ssize_t vcnl4040_read_ps_debounce_count(struct vcnl4000_data *data, int *val)
>> +{
>> +	int ret;
>> +
>> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret);
>> +
>> +	if (ret >= ARRAY_SIZE(vcnl4200_ps_it_times))
>> +		return -EINVAL;
>> +
>> +	*val = vcnl4040_ps_debounce_count[ret];
>> +
>> +	return ret;
>> +}
>> +
>> +static ssize_t vcnl4040_write_ps_debounce_count(struct vcnl4000_data *data, int val)
>> +{
>> +	unsigned int i;
>> +	int ret, index = -1;
>> +	u16 regval;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_debounce_count); i++) {
>> +		if (val == vcnl4040_ps_debounce_count[i]) {
>> +			index = i;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (index < 0)
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&data->vcnl4000_lock);
>> +
>> +	ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
>> +	if (ret < 0)
>> +		goto out;
>> +
>> +	regval = (ret & ~VCNL4040_CONF1_PS_PERS) |
>> +	    FIELD_PREP(VCNL4040_CONF1_PS_PERS, index);
>> +	ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
>> +					regval);
>> +
>> +out:
>> +	mutex_unlock(&data->vcnl4000_lock);
>> +	return ret;
>> +}
>> +
>>   static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>>   				struct iio_chan_spec const *chan,
>>   				int *val, int *val2, long mask)
>> @@ -730,6 +835,21 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev,
>>   		if (ret < 0)
>>   			return ret;
>>   		return IIO_VAL_INT_PLUS_MICRO;
>> +	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
>> +		switch (chan->type) {
>> +		case IIO_LIGHT:
>> +			ret = vcnl4040_read_als_debounce_count(data, val);
>> +			break;
>> +		case IIO_PROXIMITY:
>> +			ret = vcnl4040_read_ps_debounce_count(data, val);
>> +			break;
>> +		default:
>> +			return -EINVAL;
>> +		}
>> +		if (ret < 0)
>> +			return ret;
>> +		return IIO_VAL_INT;
>> +
>>   	default:
>>   		return -EINVAL;
>>   	}
>> @@ -753,6 +873,15 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev,
>>   		default:
>>   			return -EINVAL;
>>   		}
>> +	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
>> +		switch (chan->type) {
>> +		case IIO_LIGHT:
>> +			return vcnl4040_write_als_debounce_count(data, val);
>> +		case IIO_PROXIMITY:
>> +			return vcnl4040_write_ps_debounce_count(data, val);
>> +		default:
>> +			return -EINVAL;
>> +		}
>>   	default:
>>   		return -EINVAL;
>>   	}
>> @@ -791,6 +920,21 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev,
>>   		}
>>   		*type = IIO_VAL_INT_PLUS_MICRO;
>>   		return IIO_AVAIL_LIST;
>> +	case IIO_CHAN_INFO_DEBOUNCE_COUNT:
>> +		switch (chan->type) {
>> +		case IIO_LIGHT:
>> +			*vals = (int *)vcnl4040_als_debounce_count;
>> +			*length = ARRAY_SIZE(vcnl4040_als_debounce_count);
>> +			break;
>> +		case IIO_PROXIMITY:
>> +			*vals = (int *)vcnl4040_ps_debounce_count;
>> +			*length = ARRAY_SIZE(vcnl4040_ps_debounce_count);
>> +			break;
>> +		default:
>> +			return -EINVAL;
>> +		}
>> +		*type = IIO_VAL_INT;
>> +		return IIO_AVAIL_LIST;
>>   	default:
>>   		return -EINVAL;
>>   	}
>> @@ -1504,15 +1648,19 @@ static const struct iio_chan_spec vcnl4040_channels[] = {
>>   		.type = IIO_LIGHT,
>>   		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>>   			BIT(IIO_CHAN_INFO_SCALE) |
>> -			BIT(IIO_CHAN_INFO_INT_TIME),
>> -		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
>> +			BIT(IIO_CHAN_INFO_INT_TIME) |
>> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>> +		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
>> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>>   		.event_spec = vcnl4000_event_spec,
>>   		.num_event_specs = ARRAY_SIZE(vcnl4000_event_spec),
>>   	}, {
>>   		.type = IIO_PROXIMITY,
>>   		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
>> -			BIT(IIO_CHAN_INFO_INT_TIME),
>> -		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME),
>> +			BIT(IIO_CHAN_INFO_INT_TIME) |
>> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>> +		.info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) |
>> +			BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT),
>>   		.ext_info = vcnl4000_ext_info,
>>   		.event_spec = vcnl4040_event_spec,
>>   		.num_event_specs = ARRAY_SIZE(vcnl4040_event_spec),
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2023-05-15 15:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-09 14:01 [PATCH v2 0/7] iio: light: vcnl4000: Add features for vncl4040/4200 Astrid Rost
2023-05-09 14:01 ` [PATCH v2 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200 Astrid Rost
2023-05-13 18:57   ` Jonathan Cameron
2023-05-09 14:01 ` [PATCH v2 2/7] iio: light: vcnl4000: Add proximity ps_it " Astrid Rost
2023-05-14 17:24   ` Jonathan Cameron
2023-05-09 14:01 ` [PATCH v2 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200 Astrid Rost
2023-05-14 17:28   ` Jonathan Cameron
2023-05-09 14:01 ` [PATCH v2 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200 Astrid Rost
2023-05-14 17:31   ` Jonathan Cameron
2023-05-09 14:01 ` [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200 Astrid Rost
2023-05-14 17:37   ` Jonathan Cameron
2023-05-15 15:00     ` Astrid Rost
2023-05-09 14:01 ` [PATCH v2 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200 Astrid Rost
2023-05-14 17:41   ` Jonathan Cameron
2023-05-15 14:55     ` Astrid Rost
2023-05-09 14:01 ` [PATCH v2 7/7] iio: light: vcnl4000: Add calibration bias " Astrid Rost
2023-05-14 17:44   ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).