Re: [PATCH v2 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200

From: Astrid Rost
Date: Mon May 15 2023 - 11:00:33 EST


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@xxxxxxxx> 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@xxxxxxxx>
---
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),