From patchwork Tue Jun 13 13:50:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278782 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6BB9EB64D8 for ; Tue, 13 Jun 2023 13:50:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242434AbjFMNue (ORCPT ); Tue, 13 Jun 2023 09:50:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240515AbjFMNuc (ORCPT ); Tue, 13 Jun 2023 09:50:32 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C33DCD2; Tue, 13 Jun 2023 06:50:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664231; x=1718200231; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=jHoqqmlDAGebBQdgXBrwxAnMk3s8uTXBmUHeS8OYD+8=; b=hlzEi7s0KaAZ1aU0lkTifwQ64n6LD3AxwcplCd0sSTVg1rhOOH3qqUqJ PN0k7Rv/ALawalRglBBZ4FG2kyH10GKzVerYFedZkt9mrdsajS9BJIUnC qRtnoFMKaYva/6TWU+VZYKvCWxBU/mIKyvnOZVyJr0RxyYUsnlLEyN7rh WsGGLg/D2wzlKurLJ59+yP3xinr+eGYu5C0OFgClk/Y4S5jH4ib6N5zAJ cihYjmcw7uRwiAZAEPaEACJjrfkCzvnxF+EaUBUR2gHlSvvRNCIn/Nojf SXEFh3/pWHZZuKiz9V0EWB62SbLHETRRzohfMuFCYAPMXhiMmlDk0rFQi A==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 1/8] iio: light: vcnl4000: Add proximity irq for vcnl4200 Date: Tue, 13 Jun 2023 15:50:17 +0200 Message-ID: <20230613135025.2596641-2-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org 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 --- drivers/iio/light/vcnl4000.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 56d3963d3d66..55a1952672a4 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 */ @@ -164,6 +165,8 @@ struct vcnl4000_chip_spec { int (*set_power_state)(struct vcnl4000_data *data, bool on); irqreturn_t (*irq_thread)(int irq, void *priv); irqreturn_t (*trig_buffer_func)(int irq, void *priv); + + u8 int_reg; }; static const struct i2c_device_id vcnl4000_id[] = { @@ -1005,7 +1008,7 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p) struct vcnl4000_data *data = iio_priv(indio_dev); int ret; - ret = i2c_smbus_read_word_data(data->client, VCNL4040_INT_FLAGS); + ret = i2c_smbus_read_word_data(data->client, data->chip_spec->int_reg); if (ret < 0) return IRQ_HANDLED; @@ -1314,6 +1317,7 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .num_channels = ARRAY_SIZE(vcnl4040_channels), .info = &vcnl4040_info, .irq_thread = vcnl4040_irq_thread, + .int_reg = VCNL4040_INT_FLAGS, }, [VCNL4200] = { .prod = "VCNL4200", @@ -1321,9 +1325,11 @@ 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, + .int_reg = VCNL4200_INT_FLAGS, }, }; From patchwork Tue Jun 13 13:50:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278784 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72D2CEB64D9 for ; Tue, 13 Jun 2023 13:50:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242610AbjFMNuh (ORCPT ); Tue, 13 Jun 2023 09:50:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50626 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242535AbjFMNuf (ORCPT ); Tue, 13 Jun 2023 09:50:35 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57802CE; Tue, 13 Jun 2023 06:50:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664234; x=1718200234; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3aT/wugM0Tau5RsDI9NtDkOTKXjwgjYSzQdfBjJo3G8=; b=ncrlU0fcLLBhdfx7Nn5/6TMDlOb40Vqd8nsWMPEKsGTXdK258n4MrwSo lt3jMSSaZr2jSa5zpbsUMlScSG91uQ85+uZjognGaa1XqNoef1EaIKU8y 3hLhwNECvGoVARDGkTbIyuD6/rdE+wpHt6WWj6xUFPqKItdaS03802M2i bpQlf4Wimm1WTnbAm9Jx874X63Stu/tE2yP4WqHkO+R5XSLZIHLaawrLi DKqyIQtcKD+1sykLkqXo1qrAnIdQxBXZ0yfDudLoojrQZrXoac9kPDUld dDrl7ZnbASchW/Ko+vpSTAuStRUly9NnQLx+0iGxkjMKwm+qA5pXCq3FS A==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 2/8] iio: light: vcnl4000: Add proximity ps_it for vcnl4200 Date: Tue, 13 Jun 2023 15:50:18 +0200 Message-ID: <20230613135025.2596641-3-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org 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 --- drivers/iio/light/vcnl4000.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 55a1952672a4..6059d9548158 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 { @@ -167,6 +176,8 @@ struct vcnl4000_chip_spec { irqreturn_t (*trig_buffer_func)(int irq, void *priv); u8 int_reg; + const int(*ps_it_times)[][2]; + const int num_ps_it_times; }; static const struct i2c_device_id vcnl4000_id[] = { @@ -509,11 +520,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 >= data->chip_spec->num_ps_it_times) return -EINVAL; - *val = vcnl4040_ps_it_times[ret][0]; - *val2 = vcnl4040_ps_it_times[ret][1]; + *val = (*data->chip_spec->ps_it_times)[ret][0]; + *val2 = (*data->chip_spec->ps_it_times)[ret][1]; return 0; } @@ -524,8 +535,8 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val) int ret, index = -1; u16 regval; - for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_it_times); i++) { - if (val == vcnl4040_ps_it_times[i][1]) { + for (i = 0; i < data->chip_spec->num_ps_it_times; i++) { + if (val == (*data->chip_spec->ps_it_times)[i][1]) { index = i; break; } @@ -534,6 +545,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 * 60 * NSEC_PER_USEC); + mutex_lock(&data->vcnl4000_lock); ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); @@ -621,11 +634,13 @@ 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; + *vals = (int *)(*data->chip_spec->ps_it_times); *type = IIO_VAL_INT_PLUS_MICRO; - *length = 2 * ARRAY_SIZE(vcnl4040_ps_it_times); + *length = 2 * data->chip_spec->num_ps_it_times; return IIO_AVAIL_LIST; default: return -EINVAL; @@ -1318,6 +1333,8 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .info = &vcnl4040_info, .irq_thread = vcnl4040_irq_thread, .int_reg = VCNL4040_INT_FLAGS, + .ps_it_times = &vcnl4040_ps_it_times, + .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), }, [VCNL4200] = { .prod = "VCNL4200", @@ -1330,6 +1347,8 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .info = &vcnl4040_info, .irq_thread = vcnl4040_irq_thread, .int_reg = VCNL4200_INT_FLAGS, + .ps_it_times = &vcnl4200_ps_it_times, + .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times), }, }; From patchwork Tue Jun 13 13:50:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278788 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80868EB64DC for ; Tue, 13 Jun 2023 13:50:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235221AbjFMNul (ORCPT ); Tue, 13 Jun 2023 09:50:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50648 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242598AbjFMNuh (ORCPT ); Tue, 13 Jun 2023 09:50:37 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9BAD11B2; Tue, 13 Jun 2023 06:50:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664235; x=1718200235; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dR8MLCiL1MOfulFcpamRyyKR1UDqEV8kQFowQtsQaNM=; b=Lyx9+K/pN4qVGMEooTbKWlW9W6xHEAOsVXTxwLorei94JUnMRmBKirCj EbVkFQeCSlc8HPRFVjOaBqVyXhP0kopZPCIr0zP6hGJTHyr1ZxiUl9JRw KY3uTK6Yfus9wgrpBUGpxR9M623eRNxWo9Igi8El8LxrXsHYh4f9JM3I2 LFaABkGR1rXoJaua+H+FLr5/29OmWC6fSc7n3vZbMhQL1lqRhZHBZUqwF jbJoix25A6zKDyNQuBN1cC2U7YvMx2AVn4sDXdjuZCPlRZadaT1bfpry3 S49S2CVl9n6g6bx+dOlpS9IpjpTIv/TEJCTV61AnvsSxoQiWX5YVtQ9tX Q==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 3/8] iio: light: vcnl4000: Check type with switch case Date: Tue, 13 Jun 2023 15:50:19 +0200 Message-ID: <20230613135025.2596641-4-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Check IIO_PROXIMITY with switch case in order to make it easier to add further types like light. Add check for IIO_EV_INFO_VALUE for writing rising or falling events. Signed-off-by: Astrid Rost --- drivers/iio/light/vcnl4000.c | 152 +++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 52 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 6059d9548158..b2dc9ca7325f 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -600,9 +600,13 @@ 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_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; @@ -621,9 +625,12 @@ 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_PROXIMITY: + return vcnl4040_write_ps_it(data, val2); + default: return -EINVAL; - return vcnl4040_write_ps_it(data, val2); + } default: return -EINVAL; } @@ -638,9 +645,15 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_INT_TIME: - *vals = (int *)(*data->chip_spec->ps_it_times); + switch (chan->type) { + case IIO_PROXIMITY: + *vals = (int *)(*data->chip_spec->ps_it_times); + *length = 2 * data->chip_spec->num_ps_it_times; + break; + default: + return -EINVAL; + } *type = IIO_VAL_INT_PLUS_MICRO; - *length = 2 * data->chip_spec->num_ps_it_times; return IIO_AVAIL_LIST; default: return -EINVAL; @@ -836,24 +849,34 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev, int ret; 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_PROXIMITY: + switch (info) { + case IIO_EV_INFO_VALUE: + 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; + } + 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, @@ -866,22 +889,35 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev, int ret; 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_PROXIMITY: + switch (info) { + case IIO_EV_INFO_VALUE: + 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; + } + break; default: return -EINVAL; } + if (ret < 0) + return ret; + return IIO_VAL_INT; } static bool vcnl4010_is_thr_enabled(struct vcnl4000_data *data) @@ -974,15 +1010,20 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev, int ret; struct vcnl4000_data *data = iio_priv(indio_dev); - ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); - if (ret < 0) - return ret; + switch (chan->type) { + 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); + 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, @@ -990,25 +1031,32 @@ 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_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; + if (dir == IIO_EV_DIR_RISING) + mask = VCNL4040_PS_IF_AWAY; + else + mask = VCNL4040_PS_IF_CLOSE; - 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->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); From patchwork Tue Jun 13 13:50:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278783 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CEB8FEB64D7 for ; Tue, 13 Jun 2023 13:50:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242573AbjFMNuf (ORCPT ); Tue, 13 Jun 2023 09:50:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242021AbjFMNud (ORCPT ); Tue, 13 Jun 2023 09:50:33 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB31510DC; Tue, 13 Jun 2023 06:50:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664232; x=1718200232; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=A1yfNQfcbJmmOG+mu3rIMK0uri/rytmHhKhKs1H3mw0=; b=cRi97rYjj5zucpLIH9JHwNcD/acAMH8S19UguS7vf1+eG8sZFH2neSVI 3yG+i/8gCd2tHflhf919i8CR50yXskgZW6RHraAIb6QRy9HmOvJlog9wM FgFx7OHRaecyvUty0xKsiKI9EESmZNgemRlNPKA1JwbtCduTyciPVAvoh /KrV1F70/xqFMu/oU+J7cSItII8hCICdmoeB62556mCanAYFvKhLeTECq F65ICZkJD+Gl1DVC5QGmSMfuHZGISXuEkhQ/5TTX13a5ORu+Q51TT8Wr5 LP3fso73Wfka6p1q+5bZnzj2JE/1QCpnpoZ2kHSo0aPHrovwvW7oPZD9y A==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 4/8] iio: light: vcnl4000: Add als_it for vcnl4040/4200 Date: Tue, 13 Jun 2023 15:50:20 +0200 Message-ID: <20230613135025.2596641-5-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add illuminance integration time for vcnl4040 and vcnl4200. Add read/write attribute for illuminance integration time and read attribute for available integration times. Set scale and sampling rate according to the integration time. Signed-off-by: Astrid Rost --- drivers/iio/light/vcnl4000.c | 94 ++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index b2dc9ca7325f..0a96e9451ec7 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 { @@ -178,6 +193,9 @@ struct vcnl4000_chip_spec { u8 int_reg; const int(*ps_it_times)[][2]; const int num_ps_it_times; + const int(*als_it_times)[][2]; + const int num_als_it_times; + const unsigned int ulux_step; }; static const struct i2c_device_id vcnl4000_id[] = { @@ -331,16 +349,15 @@ static int vcnl4200_init(struct vcnl4000_data *data) data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000); /* Default wait time is 4.8ms, add 20% tolerance. */ data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000); - data->al_scale = 24000; break; case VCNL4040_PROD_ID: /* Default wait time is 80ms, add 20% tolerance. */ 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; break; } + data->al_scale = data->chip_spec->ulux_step; mutex_init(&data->vcnl4200_al.lock); mutex_init(&data->vcnl4200_ps.lock); @@ -510,6 +527,60 @@ 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; + + 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 >= data->chip_spec->num_als_it_times) + return -EINVAL; + + *val = (*data->chip_spec->als_it_times)[ret][0]; + *val2 = (*data->chip_spec->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; + u16 regval; + + for (i = 0; i < data->chip_spec->num_als_it_times; i++) { + if (val == (*data->chip_spec->als_it_times)[i][1]) + break; + } + + if (i == data->chip_spec->num_als_it_times) + return -EINVAL; + + data->vcnl4200_al.sampling_rate = ktime_set(0, val * 1200); + data->al_scale = div_u64(mul_u32_u32(data->chip_spec->ulux_step, + (*data->chip_spec->als_it_times)[0][1]), + val); + + mutex_lock(&data->vcnl4000_lock); + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); + if (ret < 0) + goto out_unlock; + + regval = FIELD_PREP(VCNL4040_ALS_CONF_IT, i); + regval |= (ret & ~VCNL4040_ALS_CONF_IT); + ret = i2c_smbus_write_word_data(data->client, + VCNL4200_AL_CONF, + regval); + +out_unlock: + mutex_unlock(&data->vcnl4000_lock); + return ret; +} + static int vcnl4040_read_ps_it(struct vcnl4000_data *data, int *val, int *val2) { int ret; @@ -601,6 +672,9 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_INT_TIME: 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; @@ -626,6 +700,8 @@ static int vcnl4040_write_raw(struct iio_dev *indio_dev, if (val != 0) return -EINVAL; switch (chan->type) { + case IIO_LIGHT: + return vcnl4040_write_als_it(data, val2); case IIO_PROXIMITY: return vcnl4040_write_ps_it(data, val2); default: @@ -646,6 +722,10 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { + case IIO_LIGHT: + *vals = (int *)(*data->chip_spec->als_it_times); + *length = 2 * data->chip_spec->num_als_it_times; + break; case IIO_PROXIMITY: *vals = (int *)(*data->chip_spec->ps_it_times); *length = 2 * data->chip_spec->num_ps_it_times; @@ -1310,7 +1390,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) | @@ -1383,6 +1465,9 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .int_reg = VCNL4040_INT_FLAGS, .ps_it_times = &vcnl4040_ps_it_times, .num_ps_it_times = ARRAY_SIZE(vcnl4040_ps_it_times), + .als_it_times = &vcnl4040_als_it_times, + .num_als_it_times = ARRAY_SIZE(vcnl4040_als_it_times), + .ulux_step = 100000, }, [VCNL4200] = { .prod = "VCNL4200", @@ -1397,6 +1482,9 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .int_reg = VCNL4200_INT_FLAGS, .ps_it_times = &vcnl4200_ps_it_times, .num_ps_it_times = ARRAY_SIZE(vcnl4200_ps_it_times), + .als_it_times = &vcnl4200_als_it_times, + .num_als_it_times = ARRAY_SIZE(vcnl4200_als_it_times), + .ulux_step = 24000, }, }; From patchwork Tue Jun 13 13:50:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278787 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF4E5EB64DB for ; Tue, 13 Jun 2023 13:50:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242512AbjFMNuk (ORCPT ); Tue, 13 Jun 2023 09:50:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242472AbjFMNuf (ORCPT ); Tue, 13 Jun 2023 09:50:35 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D07B810E6; Tue, 13 Jun 2023 06:50:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664233; x=1718200233; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kgNTlD4z0T4E+uI10IZA/4tKLCxHr/VPJvF4z3YcRjE=; b=C/daK4LSaA16TUEOamIex9/1nCyN57NXgopQKIYbO9bNAp3Jrg1yaCcy KwjdG18VHwYxA1DNey6kLj/sQuZ6PyXGdX4bvSjP1pHqGykuge10qQaPJ e+ISJyqezNZhvjrANHdODEePt4FipohPNcaX1kHP+VWXBxHdvj/6q1y1D ePre7pJEVbksTINBfK6oSWaXB7LXn0X2sLiOgn3a4y92QUzCIo/GDoIpW TzqHkAr4nM+va8Iq+d5wiiA/b4w67UBh800TaUqNGHC1n+8K3/doOhdlx IhjnUYYk98BfT0aE6PODVK7L8eAnOxQR0o1u88RHSsNAJoXaYVXQkY8L9 g==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 5/8] iio: light: vcnl4000: add illuminance irq vcnl4040/4200 Date: Tue, 13 Jun 2023 15:50:21 +0200 Message-ID: <20230613135025.2596641-6-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add support to configure ambient light 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 --- drivers/iio/light/vcnl4000.c | 94 +++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 0a96e9451ec7..0f4c39adc68a 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; @@ -295,7 +301,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); @@ -340,6 +346,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; @@ -930,6 +937,26 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev, struct vcnl4000_data *data = iio_priv(indio_dev); switch (chan->type) { + case IIO_LIGHT: + switch (info) { + case IIO_EV_INFO_VALUE: + 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; + default: + return -EINVAL; + } + break; case IIO_PROXIMITY: switch (info) { case IIO_EV_INFO_VALUE: @@ -970,6 +997,28 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev, struct vcnl4000_data *data = iio_priv(indio_dev); switch (chan->type) { + case IIO_LIGHT: + switch (info) { + case IIO_EV_INFO_VALUE: + 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; + default: + return -EINVAL; + } + break; case IIO_PROXIMITY: switch (info) { case IIO_EV_INFO_VALUE: @@ -1091,6 +1140,14 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev, 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; + + data->als_int = FIELD_GET(VCNL4040_ALS_CONF_INT_EN, ret); + + return data->als_int; case IIO_PROXIMITY: ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); if (ret < 0) @@ -1118,6 +1175,21 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev, mutex_lock(&data->vcnl4000_lock); switch (chan->type) { + case IIO_LIGHT: + ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); + if (ret < 0) + goto out; + + mask = VCNL4040_ALS_CONF_INT_EN; + if (state) + val = (ret | mask); + else + val = (ret & ~mask); + + 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) @@ -1140,7 +1212,7 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev, 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; } @@ -1171,6 +1243,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; } @@ -1393,6 +1481,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) | From patchwork Tue Jun 13 13:50:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278785 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43E1AEB64D8 for ; Tue, 13 Jun 2023 13:50:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240572AbjFMNui (ORCPT ); Tue, 13 Jun 2023 09:50:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50636 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242594AbjFMNuf (ORCPT ); Tue, 13 Jun 2023 09:50:35 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A89AD2; Tue, 13 Jun 2023 06:50:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664234; x=1718200234; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=y1ZK5fRvKQed3EHZU1Se0rdL7hF8b6kv6RD25LPaf2M=; b=B7j1gElqnp9N7/ABZqMqRn1nSpiyBrAlGbz9dhwcmaQNEAY8VX11veJF A9YcrUqSjlKz/6pbiKW885L5Ol4f+a8zLj0FsLV0XIgPjwOYROnreue1l rb2A22YUqCb5Z7OLx7xZrdvaJe5IHNv5tUsBdb496ITCuk6CazxkUt9pu AxKJg2RO4eAF4fyEz0Xix9AUW1zm85k1OOpDRL3LjqFywnXp3d7rm2f0n +QXZYcxAUUEyeHAUdMHr0I1GZWaYKSj6lvohj2B6pBMZv4R3Kwjob7Lh+ 05rcKBVTH58xQVDUyd6d7tWHmEJMRG5+eGCExZ0hFJiH+Tqjd88wdfVMq Q==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 6/8] iio: light: vcnl4000: Add period for vcnl4040/4200 Date: Tue, 13 Jun 2023 15:50:22 +0200 Message-ID: <20230613135025.2596641-7-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add read/write attribute for proximity and illuminance period. The period 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 amount of measurements. The time in seconds is calculated by the number of continued refreshes multiplied with the integration time. It will always pick the next lower possible value. The period changes, if the integration time is changed. Signed-off-by: Astrid Rost --- drivers/iio/light/vcnl4000.c | 161 ++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 0f4c39adc68a..435bf57eb4c8 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -84,8 +85,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 +156,9 @@ static const int vcnl4200_als_it_times[][2] = { {0, 400000}, }; +static const int vcnl4040_als_persistence[] = {1, 2, 4, 8}; +static const int vcnl4040_ps_persistence[] = {1, 2, 3, 4}; + #define VCNL4000_SLEEP_DELAY_MS 2000 /* before we enter pm_runtime_suspend */ enum vcnl4000_device_ids { @@ -641,6 +647,129 @@ static ssize_t vcnl4040_write_ps_it(struct vcnl4000_data *data, int val) return ret; } +static ssize_t vcnl4040_read_als_period(struct vcnl4000_data *data, int *val, int *val2) +{ + int ret, ret_pers, it; + int64_t val_c; + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); + if (ret < 0) + return ret; + + ret_pers = FIELD_GET(VCNL4040_ALS_CONF_PERS, ret); + if (ret_pers >= ARRAY_SIZE(vcnl4040_als_persistence)) + return -EINVAL; + + it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret); + if (it >= data->chip_spec->num_als_it_times) + return -EINVAL; + + val_c = mul_u32_u32((*data->chip_spec->als_it_times)[it][1], + vcnl4040_als_persistence[ret_pers]); + *val = div_u64_rem(val_c, MICRO, val2); + + return IIO_VAL_INT_PLUS_MICRO; +} + +static ssize_t vcnl4040_write_als_period(struct vcnl4000_data *data, int val, int val2) +{ + unsigned int i; + int ret, it; + u16 regval; + u64 val_n = mul_u32_u32(val, MICRO) + val2; + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); + if (ret < 0) + return ret; + + it = FIELD_GET(VCNL4040_ALS_CONF_IT, ret); + if (it >= data->chip_spec->num_als_it_times) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(vcnl4040_als_persistence) - 1; i++) { + if (val_n < mul_u32_u32(vcnl4040_als_persistence[i], + (*data->chip_spec->als_it_times)[it][1])) + break; + } + + mutex_lock(&data->vcnl4000_lock); + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_AL_CONF); + if (ret < 0) + goto out_unlock; + + regval = FIELD_PREP(VCNL4040_ALS_CONF_PERS, i); + regval |= (ret & ~VCNL4040_ALS_CONF_PERS); + ret = i2c_smbus_write_word_data(data->client, VCNL4200_AL_CONF, + regval); + +out_unlock: + mutex_unlock(&data->vcnl4000_lock); + return ret; +} + +static ssize_t vcnl4040_read_ps_period(struct vcnl4000_data *data, int *val, int *val2) +{ + int ret, ret_pers, it; + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); + if (ret < 0) + return ret; + + ret_pers = FIELD_GET(VCNL4040_CONF1_PS_PERS, ret); + if (ret_pers >= ARRAY_SIZE(vcnl4040_ps_persistence)) + return -EINVAL; + + it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret); + if (it >= data->chip_spec->num_ps_it_times) + return -EINVAL; + + *val = (*data->chip_spec->ps_it_times)[it][0]; + *val2 = (*data->chip_spec->ps_it_times)[it][1] * + vcnl4040_ps_persistence[ret_pers]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, int val2) +{ + int ret, it, i; + u16 regval; + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); + if (ret < 0) + return ret; + + it = FIELD_GET(VCNL4040_PS_CONF2_PS_IT, ret); + if (it >= data->chip_spec->num_ps_it_times) + return -EINVAL; + + if (val > 0) + i = ARRAY_SIZE(vcnl4040_ps_persistence) - 1; + else { + for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_persistence) - 1; i++) { + if (val2 <= vcnl4040_ps_persistence[i] * + (*data->chip_spec->ps_it_times)[it][1]) + break; + } + } + + mutex_lock(&data->vcnl4000_lock); + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1); + if (ret < 0) + goto out_unlock; + + regval = FIELD_PREP(VCNL4040_CONF1_PS_PERS, i); + regval |= (ret & ~VCNL4040_CONF1_PS_PERS); + ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1, + regval); + +out_unlock: + 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) @@ -939,6 +1068,8 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev, switch (chan->type) { case IIO_LIGHT: switch (info) { + case IIO_EV_INFO_PERIOD: + return vcnl4040_read_als_period(data, val, val2); case IIO_EV_INFO_VALUE: switch (dir) { case IIO_EV_DIR_RISING: @@ -959,6 +1090,8 @@ static int vcnl4040_read_event(struct iio_dev *indio_dev, break; case IIO_PROXIMITY: switch (info) { + case IIO_EV_INFO_PERIOD: + return vcnl4040_read_ps_period(data, val, val2); case IIO_EV_INFO_VALUE: switch (dir) { case IIO_EV_DIR_RISING: @@ -999,6 +1132,8 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev, switch (chan->type) { case IIO_LIGHT: switch (info) { + case IIO_EV_INFO_PERIOD: + return vcnl4040_write_als_period(data, val, val2); case IIO_EV_INFO_VALUE: switch (dir) { case IIO_EV_DIR_RISING: @@ -1021,6 +1156,8 @@ static int vcnl4040_write_event(struct iio_dev *indio_dev, break; case IIO_PROXIMITY: switch (info) { + case IIO_EV_INFO_PERIOD: + return vcnl4040_write_ps_period(data, val, val2); case IIO_EV_INFO_VALUE: switch (dir) { case IIO_EV_DIR_RISING: @@ -1425,6 +1562,22 @@ static const struct iio_event_spec vcnl4000_event_spec[] = { } }; +static const struct iio_event_spec vcnl4040_als_event_spec[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_PERIOD), + }, +}; + static const struct iio_event_spec vcnl4040_event_spec[] = { { .type = IIO_EV_TYPE_THRESH, @@ -1434,6 +1587,10 @@ static const struct iio_event_spec vcnl4040_event_spec[] = { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_FALLING, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_PERIOD), }, }; @@ -1481,8 +1638,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), + .event_spec = vcnl4040_als_event_spec, + .num_event_specs = ARRAY_SIZE(vcnl4040_als_event_spec), }, { .type = IIO_PROXIMITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | From patchwork Tue Jun 13 13:50:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278786 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F108BEB64D7 for ; Tue, 13 Jun 2023 13:50:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242616AbjFMNuj (ORCPT ); Tue, 13 Jun 2023 09:50:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242583AbjFMNuf (ORCPT ); Tue, 13 Jun 2023 09:50:35 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 53BCCA6; Tue, 13 Jun 2023 06:50:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664234; x=1718200234; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XyLHca4d3J9CSl8Sc9yYWb/QTbf/Yaus43MFIh/G9So=; b=eO232TExgmpJTc58IqSUPJY5evEbJMgWdbKWx/DOyE3tV/gpFDacFM/e YBnF+v/GQYo2297n29amMSGhRXuVaQWSF5gs49nEd73JwIqbgUDBEqfkQ 0hAnsmGrXJid3dEkT8Iu7LvnGt0/w7FoGoOnJqmf254ap9vwJrycwT43E sp30V5uEO6l3VcvbMzbU3FTbpuPKuMOlhewH4bf3wO05e2QYn6Uzvc5hx i0DYrvRBGqiQ3qLZP1LFnMNnh1Au248nAWeIbCswzYCgz3I19lWmkFf4P f1DOK3qONNHkzuA7If5IJmrpb/tlHwvodK0pFc9ThB33qMHfHxlOjiE5H A==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 7/8] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200 Date: Tue, 13 Jun 2023 15:50:23 +0200 Message-ID: <20230613135025.2596641-8-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add the proximity multi pulse (PS_MPS) as oversampling_ratio. Instead of one single pulse per every defined time frame, one can program2, 4, or even 8 pulses. This leads to a longer IRED on-time for each proximity measurement value, which also results in a higher detection range. 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 --- drivers/iio/light/vcnl4000.c | 83 +++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 435bf57eb4c8..ebe9b5343bb3 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -61,6 +61,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 */ @@ -90,6 +91,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 */ @@ -158,6 +160,7 @@ static const int vcnl4200_als_it_times[][2] = { static const int vcnl4040_als_persistence[] = {1, 2, 4, 8}; static const int vcnl4040_ps_persistence[] = {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 */ @@ -770,6 +773,53 @@ static ssize_t vcnl4040_write_ps_period(struct vcnl4000_data *data, int val, 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; + u16 regval; + + for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_oversampling_ratio); i++) { + if (val == vcnl4040_ps_oversampling_ratio[i]) + break; + } + + if (i >= ARRAY_SIZE(vcnl4040_ps_oversampling_ratio)) + return -EINVAL; + + mutex_lock(&data->vcnl4000_lock); + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3); + if (ret < 0) + goto out_unlock; + + regval = FIELD_PREP(VCNL4040_PS_CONF3_MPS, i); + regval |= (ret & ~VCNL4040_PS_CONF3_MPS); + ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, + regval); + +out_unlock: + 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) @@ -820,6 +870,16 @@ 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_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; } @@ -843,6 +903,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; } @@ -871,6 +938,16 @@ static int vcnl4040_read_avail(struct iio_dev *indio_dev, } *type = IIO_VAL_INT_PLUS_MICRO; 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; } @@ -1643,8 +1720,10 @@ 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), - .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME), + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), .ext_info = vcnl4000_ext_info, .event_spec = vcnl4040_event_spec, .num_event_specs = ARRAY_SIZE(vcnl4040_event_spec), From patchwork Tue Jun 13 13:50:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13278789 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04093EB64D8 for ; Tue, 13 Jun 2023 13:50:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240515AbjFMNul (ORCPT ); Tue, 13 Jun 2023 09:50:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50650 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242609AbjFMNuh (ORCPT ); Tue, 13 Jun 2023 09:50:37 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42CB310DA; Tue, 13 Jun 2023 06:50:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1686664235; x=1718200235; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MMSaPsOtCtamt1Sq6HblLoFD8AE1zNYqILjXC0xJvh0=; b=CeZXZWcIm/VCW+FhQUmMv4aqaTvVETc0ywR4ifn8ojUuedYY6MdQ8PD7 bYLtyGwDH7e4LqrRvAc15q6Z0zgqJbQ0q1et4XYQt1uLQNy28Yz84zNbf 0PM1GuORpJFWv+yEBbBulx1w2uEpchA8xmTqVF9Qk85der6BntSKuOsVG emreORUxtZXDxB9/vbMpnRJ8dRkfeFldBED1Y2O87c1A4wJPhB+j2veth mZ5L8aEMRpuzvRal/PQvaMyB33cQxUjX+u0rwv7mXjmGgOUDXkRl+ZAdS 1ILeu5l8+9fmuhFMBAIkzGfsp7YSw3053mykkP4bMbLWyJQntpLHdUIFx w==; From: Astrid Rost To: Jonathan Cameron , Lars-Peter Clausen CC: , , , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Mathieu Othacehe , Astrid Rost Subject: [PATCH v6 8/8] iio: light: vcnl4000: Add calibration bias for 4040/4200 Date: Tue, 13 Jun 2023 15:50:24 +0200 Message-ID: <20230613135025.2596641-9-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230613135025.2596641-1-astrid.rost@axis.com> References: <20230613135025.2596641-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org 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 --- drivers/iio/light/vcnl4000.c | 93 +++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index ebe9b5343bb3..d0246bcca2df 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -92,6 +92,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 */ @@ -158,6 +159,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_persistence[] = {1, 2, 4, 8}; static const int vcnl4040_ps_persistence[] = {1, 2, 3, 4}; static const int vcnl4040_ps_oversampling_ratio[] = {1, 2, 4, 8}; @@ -820,6 +832,54 @@ 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; + u16 regval; + + for (i = 0; i < ARRAY_SIZE(vcnl4040_ps_calibbias_ua); i++) { + if (val == vcnl4040_ps_calibbias_ua[i][1]) + break; + } + + if (i >= ARRAY_SIZE(vcnl4040_ps_calibbias_ua)) + return -EINVAL; + + mutex_lock(&data->vcnl4000_lock); + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3); + if (ret < 0) + goto out_unlock; + + regval = (ret & ~VCNL4040_PS_MS_LED_I); + regval |= FIELD_PREP(VCNL4040_PS_MS_LED_I, i); + ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3, + regval); + +out_unlock: + 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) @@ -880,6 +940,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; } @@ -910,6 +980,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; } @@ -948,6 +1025,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; } @@ -1721,9 +1808,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_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_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),