From patchwork Wed Jul 25 15:18:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomas Novotny X-Patchwork-Id: 10544151 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 73F62A517 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 646102A4B9 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 57C332A4A8; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CBF162A4B7 for ; Wed, 25 Jul 2018 15:25:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728532AbeGYQhm (ORCPT ); Wed, 25 Jul 2018 12:37:42 -0400 Received: from hosting.pavoucek.net ([46.28.107.168]:33609 "EHLO hosting.pavoucek.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728546AbeGYQhm (ORCPT ); Wed, 25 Jul 2018 12:37:42 -0400 X-Greylist: delayed 418 seconds by postgrey-1.27 at vger.kernel.org; Wed, 25 Jul 2018 12:37:40 EDT Received: from tomas.local.tbs-biometrics.cz (unknown [176.74.132.138]) (Authenticated sender: tomas@novotny.cz) by hosting.pavoucek.net (Postfix) with ESMTPSA id 779E9103FC4; Wed, 25 Jul 2018 17:18:32 +0200 (CEST) From: Tomas Novotny To: linux-iio@vger.kernel.org Cc: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Tomas Novotny Subject: [PATCH v3 1/4] iio: vcnl4000: make the driver extendable Date: Wed, 25 Jul 2018 17:18:18 +0200 Message-Id: <20180725151821.17566-2-tomas.novotny@tbs-biometrics.com> X-Mailer: git-send-email 2.12.3 In-Reply-To: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> References: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tomas Novotny There are similar chips in the vcnl4xxx family. The initialization and communication is a bit different for members of the family, so this patch makes the driver extendable for different chips. There is no functional change. Signed-off-by: Tomas Novotny --- No change v2..v3 drivers/iio/light/vcnl4000.c | 85 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index c599a90506ad..32c0b531395f 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -26,8 +26,8 @@ #include #define VCNL4000_DRV_NAME "vcnl4000" -#define VCNL4000_ID 0x01 -#define VCNL4010_ID 0x02 /* for VCNL4020, VCNL4010 */ +#define VCNL4000_PROD_ID 0x01 +#define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */ #define VCNL4000_COMMAND 0x80 /* Command register */ #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ @@ -46,17 +46,50 @@ #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ +enum vcnl4000_device_ids { + VCNL4000, +}; + struct vcnl4000_data { struct i2c_client *client; + enum vcnl4000_device_ids id; + int rev; + int al_scale; + const struct vcnl4000_chip_spec *chip_spec; struct mutex lock; }; +struct vcnl4000_chip_spec { + const char *prod; + int (*init)(struct vcnl4000_data *data); + int (*measure_light)(struct vcnl4000_data *data, int *val); + int (*measure_proximity)(struct vcnl4000_data *data, int *val); +}; + static const struct i2c_device_id vcnl4000_id[] = { - { "vcnl4000", 0 }, + { "vcnl4000", VCNL4000 }, { } }; MODULE_DEVICE_TABLE(i2c, vcnl4000_id); +static int vcnl4000_init(struct vcnl4000_data *data) +{ + int ret, prod_id; + + ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); + if (ret < 0) + return ret; + + prod_id = ret >> 4; + if (prod_id != VCNL4010_PROD_ID && prod_id != VCNL4000_PROD_ID) + return -ENODEV; + + data->rev = ret & 0xf; + data->al_scale = 250000; + + return 0; +}; + static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, u8 rdy_mask, u8 data_reg, int *val) { @@ -103,6 +136,29 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, return ret; } +static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val) +{ + return vcnl4000_measure(data, + VCNL4000_AL_OD, VCNL4000_AL_RDY, + VCNL4000_AL_RESULT_HI, val); +} + +static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val) +{ + return vcnl4000_measure(data, + VCNL4000_PS_OD, VCNL4000_PS_RDY, + VCNL4000_PS_RESULT_HI, val); +} + +static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { + [VCNL4000] = { + .prod = "VCNL4000", + .init = vcnl4000_init, + .measure_light = vcnl4000_measure_light, + .measure_proximity = vcnl4000_measure_proximity, + }, +}; + static const struct iio_chan_spec vcnl4000_channels[] = { { .type = IIO_LIGHT, @@ -125,16 +181,12 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: switch (chan->type) { case IIO_LIGHT: - ret = vcnl4000_measure(data, - VCNL4000_AL_OD, VCNL4000_AL_RDY, - VCNL4000_AL_RESULT_HI, val); + ret = data->chip_spec->measure_light(data, val); if (ret < 0) return ret; return IIO_VAL_INT; case IIO_PROXIMITY: - ret = vcnl4000_measure(data, - VCNL4000_PS_OD, VCNL4000_PS_RDY, - VCNL4000_PS_RESULT_HI, val); + ret = data->chip_spec->measure_proximity(data, val); if (ret < 0) return ret; return IIO_VAL_INT; @@ -146,7 +198,7 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, return -EINVAL; *val = 0; - *val2 = 250000; + *val2 = data->al_scale; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -162,7 +214,7 @@ static int vcnl4000_probe(struct i2c_client *client, { struct vcnl4000_data *data; struct iio_dev *indio_dev; - int ret, prod_id; + int ret; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) @@ -171,19 +223,16 @@ static int vcnl4000_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; + data->id = id->driver_data; + data->chip_spec = &vcnl4000_chip_spec_cfg[data->id]; mutex_init(&data->lock); - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); + ret = data->chip_spec->init(data); if (ret < 0) return ret; - prod_id = ret >> 4; - if (prod_id != VCNL4010_ID && prod_id != VCNL4000_ID) - return -ENODEV; - dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n", - (prod_id == VCNL4010_ID) ? "VCNL4010/4020" : "VCNL4000", - ret & 0xf); + data->chip_spec->prod, data->rev); indio_dev->dev.parent = &client->dev; indio_dev->info = &vcnl4000_info; From patchwork Wed Jul 25 15:18:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomas Novotny X-Patchwork-Id: 10544155 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D82019093 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C550D2A3C5 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B9B332A471; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 64A212A4BC for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728579AbeGYQhm (ORCPT ); Wed, 25 Jul 2018 12:37:42 -0400 Received: from hosting.pavoucek.net ([46.28.107.168]:33614 "EHLO hosting.pavoucek.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728591AbeGYQhl (ORCPT ); Wed, 25 Jul 2018 12:37:41 -0400 Received: from tomas.local.tbs-biometrics.cz (unknown [176.74.132.138]) (Authenticated sender: tomas@novotny.cz) by hosting.pavoucek.net (Postfix) with ESMTPSA id CEA361045CB; Wed, 25 Jul 2018 17:18:33 +0200 (CEST) From: Tomas Novotny To: linux-iio@vger.kernel.org Cc: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Tomas Novotny Subject: [PATCH v3 2/4] iio: vcnl4000: add VCNL4010 and VCNL4020 device id Date: Wed, 25 Jul 2018 17:18:19 +0200 Message-Id: <20180725151821.17566-3-tomas.novotny@tbs-biometrics.com> X-Mailer: git-send-email 2.12.3 In-Reply-To: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> References: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tomas Novotny The driver already supports VCNL4010/20 devices. The currently supported features and detectable product id are the same, so add shared id for them. This is a groundwork to extend the driver by detecting incorrectly specified device id. Signed-off-by: Tomas Novotny --- Changes v2..v3: - improve commit message - add vcnl4020 device id drivers/iio/light/vcnl4000.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 32c0b531395f..980eb3b77d5f 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -48,6 +48,7 @@ enum vcnl4000_device_ids { VCNL4000, + VCNL4010, }; struct vcnl4000_data { @@ -68,6 +69,8 @@ struct vcnl4000_chip_spec { static const struct i2c_device_id vcnl4000_id[] = { { "vcnl4000", VCNL4000 }, + { "vcnl4010", VCNL4010 }, + { "vcnl4020", VCNL4010 }, { } }; MODULE_DEVICE_TABLE(i2c, vcnl4000_id); @@ -157,6 +160,12 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .measure_light = vcnl4000_measure_light, .measure_proximity = vcnl4000_measure_proximity, }, + [VCNL4010] = { + .prod = "VCNL4010/4020", + .init = vcnl4000_init, + .measure_light = vcnl4000_measure_light, + .measure_proximity = vcnl4000_measure_proximity, + }, }; static const struct iio_chan_spec vcnl4000_channels[] = { From patchwork Wed Jul 25 15:18:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomas Novotny X-Patchwork-Id: 10544153 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AFF6D1805 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9FFD92A3C5 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9449E2A443; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A5E52A4B6 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728546AbeGYQhm (ORCPT ); Wed, 25 Jul 2018 12:37:42 -0400 Received: from hosting.pavoucek.net ([46.28.107.168]:33606 "EHLO hosting.pavoucek.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728580AbeGYQhl (ORCPT ); Wed, 25 Jul 2018 12:37:41 -0400 Received: from tomas.local.tbs-biometrics.cz (unknown [176.74.132.138]) (Authenticated sender: tomas@novotny.cz) by hosting.pavoucek.net (Postfix) with ESMTPSA id 005C71056CA; Wed, 25 Jul 2018 17:18:33 +0200 (CEST) From: Tomas Novotny To: linux-iio@vger.kernel.org Cc: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Tomas Novotny Subject: [PATCH v3 3/4] iio: vcnl4000: warn on incorrectly specified device id Date: Wed, 25 Jul 2018 17:18:20 +0200 Message-Id: <20180725151821.17566-4-tomas.novotny@tbs-biometrics.com> X-Mailer: git-send-email 2.12.3 In-Reply-To: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> References: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tomas Novotny We can detect incorrectly specified device id for some chips, so warn user in that case. Signed-off-by: Tomas Novotny --- Changes v2..v3: - update warn message, vcnl4020 is now valid device id drivers/iio/light/vcnl4000.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 980eb3b77d5f..a0cd1dcbf935 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -84,8 +84,20 @@ static int vcnl4000_init(struct vcnl4000_data *data) return ret; prod_id = ret >> 4; - if (prod_id != VCNL4010_PROD_ID && prod_id != VCNL4000_PROD_ID) + switch (prod_id) { + case VCNL4000_PROD_ID: + if (data->id != VCNL4000) + dev_warn(&data->client->dev, + "wrong device id, use vcnl4000"); + break; + case VCNL4010_PROD_ID: + if (data->id != VCNL4010) + dev_warn(&data->client->dev, + "wrong device id, use vcnl4010/4020"); + break; + default: return -ENODEV; + } data->rev = ret & 0xf; data->al_scale = 250000; From patchwork Wed Jul 25 15:18:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomas Novotny X-Patchwork-Id: 10544157 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 954B79093 for ; Wed, 25 Jul 2018 15:25:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 82C592A4A5 for ; Wed, 25 Jul 2018 15:25:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7738C2A494; Wed, 25 Jul 2018 15:25:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ACB0F2A4A5 for ; Wed, 25 Jul 2018 15:25:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728528AbeGYQhm (ORCPT ); Wed, 25 Jul 2018 12:37:42 -0400 Received: from hosting.pavoucek.net ([46.28.107.168]:33605 "EHLO hosting.pavoucek.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728532AbeGYQhm (ORCPT ); Wed, 25 Jul 2018 12:37:42 -0400 Received: from tomas.local.tbs-biometrics.cz (unknown [176.74.132.138]) (Authenticated sender: tomas@novotny.cz) by hosting.pavoucek.net (Postfix) with ESMTPSA id 255801056FD; Wed, 25 Jul 2018 17:18:34 +0200 (CEST) From: Tomas Novotny To: linux-iio@vger.kernel.org Cc: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Tomas Novotny Subject: [PATCH v3 4/4] iio: vcnl4000: add support for VCNL4200 Date: Wed, 25 Jul 2018 17:18:21 +0200 Message-Id: <20180725151821.17566-5-tomas.novotny@tbs-biometrics.com> X-Mailer: git-send-email 2.12.3 In-Reply-To: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> References: <20180725151821.17566-1-tomas.novotny@tbs-biometrics.com> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tomas Novotny VCNL4200 is an integrated long distance (up to 1500mm) proximity and ambient light sensor. The support is very basic. There is no configuration of proximity and ambient light sensing yet. Only the reading of both measured values is done. The reading of ambient light and proximity values is blocking. If you request a new value too early, the driver waits for new value to be ready. Signed-off-by: Tomas Novotny --- No change v2..v3 drivers/iio/light/Kconfig | 5 +- drivers/iio/light/vcnl4000.c | 114 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 109 insertions(+), 10 deletions(-) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 074e50657366..c0344a961f54 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -430,11 +430,12 @@ config US5182D will be called us5182d. config VCNL4000 - tristate "VCNL4000/4010/4020 combined ALS and proximity sensor" + tristate "VCNL4000/4010/4020/4200 combined ALS and proximity sensor" depends on I2C help Say Y here if you want to build a driver for the Vishay VCNL4000, - VCNL4010, VCNL4020 combined ambient light and proximity sensor. + VCNL4010, VCNL4020, VCNL4200 combined ambient light and proximity + sensor. To compile this driver as a module, choose M here: the module will be called vcnl4000. diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index a0cd1dcbf935..04fd0d4b6f19 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -1,5 +1,5 @@ /* - * vcnl4000.c - Support for Vishay VCNL4000/4010/4020 combined ambient + * vcnl4000.c - Support for Vishay VCNL4000/4010/4020/4200 combined ambient * light and proximity sensor * * Copyright 2012 Peter Meerwald @@ -8,13 +8,15 @@ * the GNU General Public License. See the file COPYING in the main * directory of this archive for more details. * - * IIO driver for VCNL4000 (7-bit I2C slave address 0x13) + * IIO driver for: + * VCNL4000/10/20 (7-bit I2C slave address 0x13) + * VCNL4200 (7-bit I2C slave address 0x51) * * TODO: * allow to adjust IR current * proximity threshold and event handling * periodic ALS/proximity measurement (VCNL4010/20) - * interrupts (VCNL4010/20) + * interrupts (VCNL4010/20, VCNL4200) */ #include @@ -28,6 +30,7 @@ #define VCNL4000_DRV_NAME "vcnl4000" #define VCNL4000_PROD_ID 0x01 #define VCNL4010_PROD_ID 0x02 /* for VCNL4020, VCNL4010 */ +#define VCNL4200_PROD_ID 0x58 #define VCNL4000_COMMAND 0x80 /* Command register */ #define VCNL4000_PROD_REV 0x81 /* Product ID and Revision ID */ @@ -40,6 +43,12 @@ #define VCNL4000_PS_MEAS_FREQ 0x89 /* Proximity test signal frequency */ #define VCNL4000_PS_MOD_ADJ 0x8a /* Proximity modulator timing adjustment */ +#define VCNL4200_AL_CONF 0x00 /* Ambient light configuration */ +#define VCNL4200_PS_CONF1 0x03 /* Proximity configuration */ +#define VCNL4200_PS_DATA 0x08 /* Proximity data */ +#define VCNL4200_AL_DATA 0x09 /* Ambient light data */ +#define VCNL4200_DEV_ID 0x0e /* Device ID, slave address and version */ + /* Bit masks for COMMAND register */ #define VCNL4000_AL_RDY BIT(6) /* ALS data ready? */ #define VCNL4000_PS_RDY BIT(5) /* proximity data ready? */ @@ -49,6 +58,14 @@ enum vcnl4000_device_ids { VCNL4000, VCNL4010, + VCNL4200, +}; + +struct vcnl4200_channel { + u8 reg; + ktime_t last_measurement; + ktime_t sampling_rate; + struct mutex lock; }; struct vcnl4000_data { @@ -57,7 +74,9 @@ struct vcnl4000_data { int rev; int al_scale; const struct vcnl4000_chip_spec *chip_spec; - struct mutex lock; + struct mutex vcnl4000_lock; + struct vcnl4200_channel vcnl4200_al; + struct vcnl4200_channel vcnl4200_ps; }; struct vcnl4000_chip_spec { @@ -71,6 +90,7 @@ static const struct i2c_device_id vcnl4000_id[] = { { "vcnl4000", VCNL4000 }, { "vcnl4010", VCNL4010 }, { "vcnl4020", VCNL4010 }, + { "vcnl4200", VCNL4200 }, { } }; MODULE_DEVICE_TABLE(i2c, vcnl4000_id); @@ -101,6 +121,42 @@ static int vcnl4000_init(struct vcnl4000_data *data) data->rev = ret & 0xf; data->al_scale = 250000; + mutex_init(&data->vcnl4000_lock); + + return 0; +}; + +static int vcnl4200_init(struct vcnl4000_data *data) +{ + int ret; + + ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID); + if (ret < 0) + return ret; + + if ((ret & 0xff) != VCNL4200_PROD_ID) + return -ENODEV; + + data->rev = (ret >> 8) & 0xf; + + /* Set defaults and enable both channels */ + ret = i2c_smbus_write_byte_data(data->client, VCNL4200_AL_CONF, 0x00); + if (ret < 0) + return ret; + ret = i2c_smbus_write_byte_data(data->client, VCNL4200_PS_CONF1, 0x00); + if (ret < 0) + return ret; + + data->al_scale = 24000; + data->vcnl4200_al.reg = VCNL4200_AL_DATA; + data->vcnl4200_ps.reg = VCNL4200_PS_DATA; + /* Integration time is 50ms, but the experiments show 54ms in total. */ + data->vcnl4200_al.sampling_rate = ktime_set(0, 54000 * 1000); + data->vcnl4200_ps.sampling_rate = ktime_set(0, 4200 * 1000); + data->vcnl4200_al.last_measurement = ktime_set(0, 0); + data->vcnl4200_ps.last_measurement = ktime_set(0, 0); + mutex_init(&data->vcnl4200_al.lock); + mutex_init(&data->vcnl4200_ps.lock); return 0; }; @@ -112,7 +168,7 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, __be16 buf; int ret; - mutex_lock(&data->lock); + mutex_lock(&data->vcnl4000_lock); ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, req_mask); @@ -141,16 +197,43 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, if (ret < 0) goto fail; - mutex_unlock(&data->lock); + mutex_unlock(&data->vcnl4000_lock); *val = be16_to_cpu(buf); return 0; fail: - mutex_unlock(&data->lock); + mutex_unlock(&data->vcnl4000_lock); return ret; } +static int vcnl4200_measure(struct vcnl4000_data *data, + struct vcnl4200_channel *chan, int *val) +{ + int ret; + s64 delta; + ktime_t next_measurement; + + mutex_lock(&chan->lock); + + next_measurement = ktime_add(chan->last_measurement, + chan->sampling_rate); + delta = ktime_us_delta(next_measurement, ktime_get()); + if (delta > 0) + usleep_range(delta, delta + 500); + chan->last_measurement = ktime_get(); + + mutex_unlock(&chan->lock); + + ret = i2c_smbus_read_word_data(data->client, chan->reg); + if (ret < 0) + return ret; + + *val = ret; + + return 0; +} + static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val) { return vcnl4000_measure(data, @@ -158,6 +241,11 @@ static int vcnl4000_measure_light(struct vcnl4000_data *data, int *val) VCNL4000_AL_RESULT_HI, val); } +static int vcnl4200_measure_light(struct vcnl4000_data *data, int *val) +{ + return vcnl4200_measure(data, &data->vcnl4200_al, val); +} + static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val) { return vcnl4000_measure(data, @@ -165,6 +253,11 @@ static int vcnl4000_measure_proximity(struct vcnl4000_data *data, int *val) VCNL4000_PS_RESULT_HI, val); } +static int vcnl4200_measure_proximity(struct vcnl4000_data *data, int *val) +{ + return vcnl4200_measure(data, &data->vcnl4200_ps, val); +} + static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { [VCNL4000] = { .prod = "VCNL4000", @@ -178,6 +271,12 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = { .measure_light = vcnl4000_measure_light, .measure_proximity = vcnl4000_measure_proximity, }, + [VCNL4200] = { + .prod = "VCNL4200", + .init = vcnl4200_init, + .measure_light = vcnl4200_measure_light, + .measure_proximity = vcnl4200_measure_proximity, + }, }; static const struct iio_chan_spec vcnl4000_channels[] = { @@ -246,7 +345,6 @@ static int vcnl4000_probe(struct i2c_client *client, data->client = client; data->id = id->driver_data; data->chip_spec = &vcnl4000_chip_spec_cfg[data->id]; - mutex_init(&data->lock); ret = data->chip_spec->init(data); if (ret < 0)