From patchwork Mon May 8 07:09: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: 13234148 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 3B6BCC77B75 for ; Mon, 8 May 2023 07:10:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233287AbjEHHKQ (ORCPT ); Mon, 8 May 2023 03:10:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52296 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233428AbjEHHJ5 (ORCPT ); Mon, 8 May 2023 03:09:57 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 262601AEF4; Mon, 8 May 2023 00:09:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529781; x=1715065781; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2V+NUhnYRzHcs/qPV372ooVdqlg/MRqyc6ldidCg9bY=; b=DIZct6ncsTbjR4096+pVaYccmSB9epzRem86o3mB2lJTEHhNWiK4dJQL r42DLb/tRgRntj/24e/cR8/gP95JuKyzZWW4Y0HmiriAwkjX27iX+IFvd WnLe9nCeGrWLuhZbJFN2whTcj3yIDDdK5jQbH7X9cdMIWZcIgG3rpw+aJ eyNa2HH00SN9yQ73z6bbnWwRHiy7Ei5asQcpMX1753qbkvbCAaVDKh/JJ jU0XV54SdkVo4hH5BfN2bpZYIcXPb/vfIoCeyt/ONx5uETqZSmCcUAEpy +FeVA8OUSavXWtz22oEChsrns8yFFNShsGk0sTmcVi9SC4FQg9yAvZsqb g==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 1/7] iio: light: vcnl4000: Add proximity irq for vcnl4200 Date: Mon, 8 May 2023 09:09:19 +0200 Message-ID: <20230508070925.2123265-2-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-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 | 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, }, }; From patchwork Mon May 8 07:09: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: 13234149 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 AC8BFC7EE2A for ; Mon, 8 May 2023 07:10:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233311AbjEHHKS (ORCPT ); Mon, 8 May 2023 03:10:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51994 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233450AbjEHHJ7 (ORCPT ); Mon, 8 May 2023 03:09:59 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 925831E9A2; Mon, 8 May 2023 00:09:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529781; x=1715065781; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HyeQ1SkxMIsCZ+1+CHtohT95Afv+FFaCviNOkxFUrnA=; b=eMs2+QQHDJhPUJvKf+2rsrBURqZVOM6MGZUn1jSoCw6So2wt2O9QSyz0 mg9NZh/vFID3hNuSUK5nZwQ8rXJgpbGceSb9M61AMl9BMfLA4KTI6JF9P PgntJBhHaaO5DEf+Mphs7b0nC4VqDu5T3WqSJrfk+Nw1tf7n2DgIgBSTs u9u4E25iPLDRohOtYAeBuDYIpG8ZA+7+Tg9/Trhxm/5+vtD3C+y9ZPkDt FrrJFkI9EMraN4yf9RcShTN3idfE/xqjytFFjbblCNyiPAsA5SPc7yeYq eOvl3p2sUBCDCzpi0H/dmkKtktjZ0ph6xd+PftQ+rSusKlEyfRUX8yaai g==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 2/7] iio: light: vcnl4000: Add proximity ps_it for vcnl4200 Date: Mon, 8 May 2023 09:09:20 +0200 Message-ID: <20230508070925.2123265-3-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-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 | 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; From patchwork Mon May 8 07:09: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: 13234150 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 06B6AC77B7F for ; Mon, 8 May 2023 07:10:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233299AbjEHHKR (ORCPT ); Mon, 8 May 2023 03:10:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51978 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233445AbjEHHJ7 (ORCPT ); Mon, 8 May 2023 03:09:59 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8360E1A10E; Mon, 8 May 2023 00:09:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529781; x=1715065781; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+ZIMG+VC7U/b5stae5MoVgLWcjpmm9w30NPXlGFnKrA=; b=TJ2lX0HrfhqV9WG8hpjkCttYA5HLAYs5nRCtQ+ics0ZAL8+5qLbSq0LB MeE4Zk+chuaw3I6JX5+QdY1zKTd9HBRL0KyIzsvBu9OWyj9DeHA8DLxrf 6Hn8Sr8Z7yiQsY801tPyLC3lKyw50DAqcC9b89k+4qucbMyOxWabg7yYK NylhDwoflp7NQhL20O2YAkqN51fB3b8zGe4XPpnrQL/3hZz74aXnbvFlX 63jTlNmlvwkn/IAhpsFaqxCnoSUttNr2XGU9MVWH0oz/gWu0vjkCKOCqT 7uc0l9kr/CuHqbgTfQtz0YSJF/cgbut3LAnI/WQmcuHgzxtm5oyn5J49h Q==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 3/7] iio: light: vcnl4000: Add als_it for vcnl4040/4200 Date: Mon, 8 May 2023 09:09:21 +0200 Message-ID: <20230508070925.2123265-4-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-1-astrid.rost@axis.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org 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 --- drivers/iio/light/vcnl4000.c | 140 ++++++++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 11 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index e14475070ac3..65b42da9ffa8 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 { @@ -506,6 +521,80 @@ 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); + data->al_scale = 12000000000 / 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 +705,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 +733,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 +755,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 +1405,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) | From patchwork Mon May 8 07:09: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: 13234152 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 049E7C77B7F for ; Mon, 8 May 2023 07:10:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232313AbjEHHKf (ORCPT ); Mon, 8 May 2023 03:10:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233133AbjEHHKM (ORCPT ); Mon, 8 May 2023 03:10:12 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE3D21A125; Mon, 8 May 2023 00:09:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529799; x=1715065799; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=80pu4EpUcOwahaOLqMkhKI5s6ZQ6MufNxzrKA+syQWM=; b=m4PzmFOu8O9PS8UNdqK/Te+JI8eH7dzBn2mTiKPZcTWcXP4v7IbcoI22 li3FZjZwVCex1dhH/WVuj0sQTioGCx1sC9QAEWXi7rmKNnXTye+W/JbXF yUeMdrtw8MD6Hk+gjQ9NXefc7oR5BVaGXokIY4yAS/bVdOB24YY6cdTlQ qxbiLxHWJeDHEU1ZUQOr2eLiIJD1l1mnC5HBLpbp0NsRvO+plWtwtu+PH dLHPyd+jUOi6Tyl2qR5Ssc7Jvi66B7iQ0sKVkjUUTtg9i7ACOEJA79ORr Ab1Q5Vjzg2PF6IdAlmXrkX+GCah0qOlWF8MX79zzgxBRX3rViOq1QqyG0 g==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 4/7] iio: light: vcnl4000: add illumination irq vcnl4040/4200 Date: Mon, 8 May 2023 09:09:22 +0200 Message-ID: <20230508070925.2123265-5-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-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 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 --- 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 65b42da9ffa8..ae06a697fbff 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; @@ -970,27 +977,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, @@ -1000,25 +1025,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) @@ -1110,16 +1153,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, @@ -1127,29 +1182,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; } @@ -1186,6 +1263,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; } @@ -1408,6 +1501,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 Mon May 8 07:09: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: 13234151 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 69955C77B75 for ; Mon, 8 May 2023 07:10:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233110AbjEHHKf (ORCPT ); Mon, 8 May 2023 03:10:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51740 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233137AbjEHHKM (ORCPT ); Mon, 8 May 2023 03:10:12 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FE601A130; Mon, 8 May 2023 00:09:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529800; x=1715065800; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hZ7xUmwwGYnij1OoqnwNTbOyyoPTefkk7jA9Vn+5Wq8=; b=GG0B1i6GMo+tgbs7SPlqMu9+X0TsVNZrPElFT2uEu75Xo5ZSLxZrNJFr VnPNFUkOp9XnG/UDIdLLHHVUIIYunCcCRHyL/pI1pMnhz6kvXBi+3ZB4n n2pSt+m4iNKAYKfiZW+eoUwVnBkZeuQrW8mS+CCHasx1pB2YulMWWiOW2 Ygdtfj5QP5/eFnNX49j/dBqqvrwAA4DnEqlO3m7tT0RE4NCQ3/nq4/Mqd VEzlUi3rhpFOC4WmTYg349TgRL/ft4GLnfBFR6HBh/UoI59EjagATaoJl zInu955jcvQwVlC3fiuWrzvUR7a8+y1Y6bseqXMV6TE8zU6KhS5g0Wc3c w==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 5/7] iio: light: vcnl4000: Add debounce count for vcnl4040/4200 Date: Mon, 8 May 2023 09:09:23 +0200 Message-ID: <20230508070925.2123265-6-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-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 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 --- 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 ae06a697fbff..5c6359d1e0ba 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 { @@ -675,6 +680,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) @@ -725,6 +830,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; } @@ -748,6 +868,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; } @@ -786,6 +915,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; } @@ -1499,15 +1643,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), From patchwork Mon May 8 07:09: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: 13234154 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 47518C77B75 for ; Mon, 8 May 2023 07:10:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233409AbjEHHKi (ORCPT ); Mon, 8 May 2023 03:10:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53238 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233165AbjEHHKM (ORCPT ); Mon, 8 May 2023 03:10:12 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 937EB1A1C0; Mon, 8 May 2023 00:09:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529800; x=1715065800; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iNjjcLcTLmyGjFy8ODPKZmYimQ0QXkyn/MgBpnKyLig=; b=azNicJCqPdQ2rcwlKHeHN3w9rZTXJndpjqF1hO4SpojY1CIXGpZLIWtZ wpKHV7QbAuWXLEmcqDCgD2IFUcRxovyIXmB8/kmX7PlohQR4N52IgSnZD rE3v320TxZHz2iUoNmzyeIBDgkunrNh0lxxYjF7QeATFDPqLPcaM8BCvX h5TGy2QaaFMkacCz3LyIzHoCOg7Kwc8AcdFQz1JSuPinO+g1et2i53F0O Qhu/4iuyp8OfeBazr6NYrRjZVmWbf+7P33nYycD7ihgRk5DgNwGZpOu2o A7V5pg8cyqjApGD2zd2CuGLmcbaazIzwwEdbmI0GTiy5VtJn+D1hlVM4m Q==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 6/7] iio: light: vcnl4000: Add oversampling_ratio for 4040/4200 Date: Mon, 8 May 2023 09:09:24 +0200 Message-ID: <20230508070925.2123265-7-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-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. 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 --- 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 5c6359d1e0ba..ab70c6fd5520 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 */ @@ -780,6 +783,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) @@ -844,6 +897,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; @@ -877,6 +940,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; } @@ -930,6 +1000,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; } @@ -1653,9 +1733,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), From patchwork Mon May 8 07:09:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Astrid Rost X-Patchwork-Id: 13234153 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 E5D44C7EE24 for ; Mon, 8 May 2023 07:10:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233404AbjEHHKg (ORCPT ); Mon, 8 May 2023 03:10:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233155AbjEHHKM (ORCPT ); Mon, 8 May 2023 03:10:12 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 743E41A134; Mon, 8 May 2023 00:09:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1683529800; x=1715065800; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=W/xWbKcRNiw8Sn6/6Bh66R38/GASDSgCB4EIlMrvDZ0=; b=hTOSQTeQRv+QbPxMBHWJN/vMcrKjgAcxuLFW1tfDxciDgqFpYveCaY62 WMY33Q2EvaLJfijdp8v3EVQivhqtkWERER4CBxZm13BcwQAAVcGhh0kxH qgFw4fv6adGrOfDwsElTSu6EuIRGdS7CElhEyMEFKdf/nNwF9GrIXB4B/ dBP+YTWK6xhavw+7uRrXlNsZqbwN5NeVajRsvW+MVjJV7pKht76dnH1XN rUCOZB6S2M7kNACFbVxzrKIwVZwDMLp5JvmOLfNFyupfKieEmlW9Wl+4x DhO35gj6EZn3SI1LEz+57+sNBJZ5LFAgnlOtIEiStsswuZEoAkjOD07ZN w==; From: Astrid Rost To: Jonathan Cameron CC: , Astrid Rost , Astrid Rost , Lars-Peter Clausen , , Subject: [PATCH v1 7/7] iio: light: vcnl4000: Add calibration bias for 4040/4200 Date: Mon, 8 May 2023 09:09:25 +0200 Message-ID: <20230508070925.2123265-8-astrid.rost@axis.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230508070925.2123265-1-astrid.rost@axis.com> References: <20230508070925.2123265-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 | 97 ++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index ab70c6fd5520..cd5eae692dbf 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}; @@ -833,6 +845,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) @@ -907,7 +970,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; } @@ -947,6 +1019,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; } @@ -1010,6 +1089,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; } @@ -1734,10 +1823,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),