* [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support @ 2016-07-25 10:57 Pratik Prajapati 2016-07-25 10:57 ` [PATCH v2 2/2] staging: iio: vcnl4000: Replace i2c api's with regmap Pratik Prajapati 2016-08-21 15:16 ` [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support Jonathan Cameron 0 siblings, 2 replies; 4+ messages in thread From: Pratik Prajapati @ 2016-07-25 10:57 UTC (permalink / raw) To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler Cc: linux-iio, linux-kernel, Pratik Prajapati Signed-off-by: Pratik Prajapati <pratik.prajapati12@gmail.com> --- Changes v1 -> v2: - documented current_led files in ABI - masked value while writing to led register - added blank line before last return - removed redundant return Documentation/ABI/testing/sysfs-bus-iio | 13 ++++++ drivers/iio/light/vcnl4000.c | 77 ++++++++++++++++++++++++++++++--- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index fee35c0..7129be6 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1579,3 +1579,16 @@ Contact: linux-iio@vger.kernel.org Description: Raw (unscaled no offset etc.) electric conductivity reading that can be processed to siemens per meter. + +What: /sys/bus/iio/devices/iio:deviceX/in_current_led_raw +KernelVersion: 4.8 +Contact: linux-iio@vger.kernel.org +Description: + This controls the current to an IR LED. + +What: /sys/bus/iio/devices/iio:deviceX/in_current_led_scale +KernelVersion: 4.8 +Contact: linux-iio@vger.kernel.org +Description: + Specifies the conversion factor from the standard unit + to device specific unit. diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index 360b6e9..dcf7a6f 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -3,6 +3,7 @@ * light and proximity sensor * * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net> + * Copyright (C) 2016 Pratik Prajapati <pratik.prajapati12@gmail.com> * * This file is subject to the terms and conditions of version 2 of * the GNU General Public License. See the file COPYING in the main @@ -11,7 +12,6 @@ * IIO driver for VCNL4000 (7-bit I2C slave address 0x13) * * TODO: - * allow to adjust IR current * proximity threshold and event handling * periodic ALS/proximity measurement (VCNL4010/20) * interrupts (VCNL4010/20) @@ -46,6 +46,10 @@ #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ +/* Bit mask for LED_CURRENT register */ +#define VCNL4000_LED_CURRENT_MASK 0x3F +#define VCNL4000_LED_CURRENT_MAX 20 + struct vcnl4000_data { struct i2c_client *client; struct mutex lock; @@ -111,9 +115,43 @@ static const struct iio_chan_spec vcnl4000_channels[] = { }, { .type = IIO_PROXIMITY, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - } + }, { + .type = IIO_CURRENT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .extend_name = "led", + .output = 1, + .scan_index = -1, + }, }; +static int vcnl4000_write_led_current_raw(struct vcnl4000_data *data, int val) +{ + int ret; + + if (val < 0 || val > VCNL4000_LED_CURRENT_MAX) + return -ERANGE; + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_LED_CURRENT, + VCNL4000_LED_CURRENT_MASK & val); + mutex_unlock(&data->lock); + + return ret; +} + +static int vcnl4000_read_led_current_raw(struct vcnl4000_data *data) +{ + int ret; + + mutex_lock(&data->lock); + ret = i2c_smbus_read_byte_data(data->client, VCNL4000_LED_CURRENT); + mutex_unlock(&data->lock); + if (ret < 0) + return ret; + + return ret &= VCNL4000_LED_CURRENT_MASK; +} + static int vcnl4000_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -138,23 +176,50 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; return IIO_VAL_INT; + case IIO_CURRENT: + ret = vcnl4000_read_led_current_raw(data); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; default: return -EINVAL; } + case IIO_CHAN_INFO_SCALE: - if (chan->type != IIO_LIGHT) + switch (chan->type) { + case IIO_LIGHT: + *val = 0; + *val2 = 250000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CURRENT: + /* Output register is in 10s of milliamps */ + *val = 10; + return IIO_VAL_INT; + default: return -EINVAL; + } - *val = 0; - *val2 = 250000; - return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } } +static int vcnl4000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct vcnl4000_data *data = iio_priv(indio_dev); + + if (mask == IIO_CHAN_INFO_RAW && chan->type == IIO_CURRENT) + return vcnl4000_write_led_current_raw(data, val); + + return -EINVAL; +} + static const struct iio_info vcnl4000_info = { .read_raw = vcnl4000_read_raw, + .write_raw = vcnl4000_write_raw, .driver_module = THIS_MODULE, }; -- 2.6.2 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] staging: iio: vcnl4000: Replace i2c api's with regmap 2016-07-25 10:57 [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support Pratik Prajapati @ 2016-07-25 10:57 ` Pratik Prajapati 2016-08-21 15:21 ` Jonathan Cameron 2016-08-21 15:16 ` [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support Jonathan Cameron 1 sibling, 1 reply; 4+ messages in thread From: Pratik Prajapati @ 2016-07-25 10:57 UTC (permalink / raw) To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler Cc: linux-iio, linux-kernel, Pratik Prajapati Signed-off-by: Pratik Prajapati <pratik.prajapati12@gmail.com> --- Changes v1 -> v2 - added error msgs for led current's read and write functions drivers/iio/light/vcnl4000.c | 99 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 86 insertions(+), 13 deletions(-) diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index dcf7a6f..9a79022 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -21,6 +21,7 @@ #include <linux/i2c.h> #include <linux/err.h> #include <linux/delay.h> +#include <linux/regmap.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -53,6 +54,7 @@ struct vcnl4000_data { struct i2c_client *client; struct mutex lock; + struct regmap *regmap; }; static const struct i2c_device_id vcnl4000_id[] = { @@ -67,20 +69,20 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, int tries = 20; __be16 buf; int ret; + unsigned int regval; mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, - req_mask); + ret = regmap_write(data->regmap, VCNL4000_COMMAND, req_mask); if (ret < 0) goto fail; /* wait for data to become ready */ while (tries--) { - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); + ret = regmap_read(data->regmap, VCNL4000_COMMAND, ®val); if (ret < 0) goto fail; - if (ret & rdy_mask) + if (regval & rdy_mask) break; msleep(20); /* measurement takes up to 100 ms */ } @@ -92,8 +94,8 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, goto fail; } - ret = i2c_smbus_read_i2c_block_data(data->client, - data_reg, sizeof(buf), (u8 *) &buf); + ret = regmap_bulk_read(data->regmap, data_reg, (u8 *) &buf, + sizeof(buf)); if (ret < 0) goto fail; @@ -127,29 +129,38 @@ static const struct iio_chan_spec vcnl4000_channels[] = { static int vcnl4000_write_led_current_raw(struct vcnl4000_data *data, int val) { + struct device *dev = regmap_get_device(data->regmap); int ret; if (val < 0 || val > VCNL4000_LED_CURRENT_MAX) return -ERANGE; + mutex_lock(&data->lock); - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_LED_CURRENT, - VCNL4000_LED_CURRENT_MASK & val); + ret = regmap_write_bits(data->regmap, VCNL4000_LED_CURRENT, + VCNL4000_LED_CURRENT_MASK, val); mutex_unlock(&data->lock); + if (ret < 0) + dev_err(dev, "Failed to write to LED current register: %d", + ret); return ret; } static int vcnl4000_read_led_current_raw(struct vcnl4000_data *data) { + struct device *dev = regmap_get_device(data->regmap); + unsigned int regval; int ret; mutex_lock(&data->lock); - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_LED_CURRENT); + ret = regmap_read(data->regmap, VCNL4000_LED_CURRENT, ®val); mutex_unlock(&data->lock); - if (ret < 0) + if (ret < 0) { + dev_err(dev, "Failed to read LED current register: %d", ret); return ret; + } - return ret &= VCNL4000_LED_CURRENT_MASK; + return regval &= VCNL4000_LED_CURRENT_MASK; } static int vcnl4000_read_raw(struct iio_dev *indio_dev, @@ -223,27 +234,89 @@ static const struct iio_info vcnl4000_info = { .driver_module = THIS_MODULE, }; +static bool vcnl4000_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case VCNL4000_COMMAND: + case VCNL4000_PROD_REV: + case VCNL4000_LED_CURRENT: + case VCNL4000_AL_PARAM: + case VCNL4000_AL_RESULT_HI: + case VCNL4000_AL_RESULT_LO: + case VCNL4000_PS_RESULT_HI: + case VCNL4000_PS_RESULT_LO: + case VCNL4000_PS_MEAS_FREQ: + case VCNL4000_PS_MOD_ADJ: + return true; + default: + return false; + } +} + +static bool vcnl4000_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case VCNL4000_COMMAND: + case VCNL4000_LED_CURRENT: + case VCNL4000_AL_PARAM: + case VCNL4000_PS_MEAS_FREQ: + case VCNL4000_PS_MOD_ADJ: + return true; + default: + return false; + } +} + +static bool vcnl4000_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case VCNL4000_COMMAND: + case VCNL4000_AL_RESULT_HI: + case VCNL4000_AL_RESULT_LO: + case VCNL4000_PS_RESULT_HI: + case VCNL4000_PS_RESULT_LO: + return true; + default: + return false; + } +} + +static const struct regmap_config vcnl4000_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = VCNL4000_PS_MOD_ADJ, + .readable_reg = vcnl4000_readable_reg, + .writeable_reg = vcnl4000_writeable_reg, + .volatile_reg = vcnl4000_volatile_reg, +}; + static int vcnl4000_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct vcnl4000_data *data; struct iio_dev *indio_dev; int ret, prod_id; + unsigned int regval; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); + data->regmap = devm_regmap_init_i2c(client, &vcnl4000_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(&client->dev, "regmap_init failed!\n"); + return PTR_ERR(data->regmap); + } i2c_set_clientdata(client, indio_dev); data->client = client; mutex_init(&data->lock); - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); + ret = regmap_read(data->regmap, VCNL4000_PROD_REV, ®val); if (ret < 0) return ret; - prod_id = ret >> 4; + prod_id = regval >> 4; if (prod_id != VCNL4010_ID && prod_id != VCNL4000_ID) return -ENODEV; -- 2.6.2 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 2/2] staging: iio: vcnl4000: Replace i2c api's with regmap 2016-07-25 10:57 ` [PATCH v2 2/2] staging: iio: vcnl4000: Replace i2c api's with regmap Pratik Prajapati @ 2016-08-21 15:21 ` Jonathan Cameron 0 siblings, 0 replies; 4+ messages in thread From: Jonathan Cameron @ 2016-08-21 15:21 UTC (permalink / raw) To: Pratik Prajapati, Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler Cc: linux-iio, linux-kernel On 25/07/16 11:57, Pratik Prajapati wrote: > Signed-off-by: Pratik Prajapati <pratik.prajapati12@gmail.com> Why? I.e. Why replace it with regmap. I kind of assumed this was to add spi support on a dual bus chip, but it doesn't look like vcnl4000 has an spi version... I wouldn't have minded if the driver had originally been written to use regmap, but it seems a fair bit of churn if there are no advantages. Caching? Anyhow, description should include the answer to 'Why?' Jonathan > --- > Changes v1 -> v2 > - added error msgs for led current's read and write functions > > drivers/iio/light/vcnl4000.c | 99 ++++++++++++++++++++++++++++++++++++++------ > 1 file changed, 86 insertions(+), 13 deletions(-) > > diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c > index dcf7a6f..9a79022 100644 > --- a/drivers/iio/light/vcnl4000.c > +++ b/drivers/iio/light/vcnl4000.c > @@ -21,6 +21,7 @@ > #include <linux/i2c.h> > #include <linux/err.h> > #include <linux/delay.h> > +#include <linux/regmap.h> > > #include <linux/iio/iio.h> > #include <linux/iio/sysfs.h> > @@ -53,6 +54,7 @@ > struct vcnl4000_data { > struct i2c_client *client; > struct mutex lock; > + struct regmap *regmap; > }; > > static const struct i2c_device_id vcnl4000_id[] = { > @@ -67,20 +69,20 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, > int tries = 20; > __be16 buf; > int ret; > + unsigned int regval; > > mutex_lock(&data->lock); > > - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, > - req_mask); > + ret = regmap_write(data->regmap, VCNL4000_COMMAND, req_mask); > if (ret < 0) > goto fail; > > /* wait for data to become ready */ > while (tries--) { > - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_COMMAND); > + ret = regmap_read(data->regmap, VCNL4000_COMMAND, ®val); > if (ret < 0) > goto fail; > - if (ret & rdy_mask) > + if (regval & rdy_mask) > break; > msleep(20); /* measurement takes up to 100 ms */ > } > @@ -92,8 +94,8 @@ static int vcnl4000_measure(struct vcnl4000_data *data, u8 req_mask, > goto fail; > } > > - ret = i2c_smbus_read_i2c_block_data(data->client, > - data_reg, sizeof(buf), (u8 *) &buf); > + ret = regmap_bulk_read(data->regmap, data_reg, (u8 *) &buf, > + sizeof(buf)); > if (ret < 0) > goto fail; > > @@ -127,29 +129,38 @@ static const struct iio_chan_spec vcnl4000_channels[] = { > > static int vcnl4000_write_led_current_raw(struct vcnl4000_data *data, int val) > { > + struct device *dev = regmap_get_device(data->regmap); > int ret; > > if (val < 0 || val > VCNL4000_LED_CURRENT_MAX) > return -ERANGE; > + > mutex_lock(&data->lock); > - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_LED_CURRENT, > - VCNL4000_LED_CURRENT_MASK & val); > + ret = regmap_write_bits(data->regmap, VCNL4000_LED_CURRENT, > + VCNL4000_LED_CURRENT_MASK, val); > mutex_unlock(&data->lock); > + if (ret < 0) > + dev_err(dev, "Failed to write to LED current register: %d", > + ret); > > return ret; > } > > static int vcnl4000_read_led_current_raw(struct vcnl4000_data *data) > { > + struct device *dev = regmap_get_device(data->regmap); > + unsigned int regval; > int ret; > > mutex_lock(&data->lock); > - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_LED_CURRENT); > + ret = regmap_read(data->regmap, VCNL4000_LED_CURRENT, ®val); > mutex_unlock(&data->lock); > - if (ret < 0) > + if (ret < 0) { > + dev_err(dev, "Failed to read LED current register: %d", ret); > return ret; > + } > > - return ret &= VCNL4000_LED_CURRENT_MASK; > + return regval &= VCNL4000_LED_CURRENT_MASK; > } > > static int vcnl4000_read_raw(struct iio_dev *indio_dev, > @@ -223,27 +234,89 @@ static const struct iio_info vcnl4000_info = { > .driver_module = THIS_MODULE, > }; > > +static bool vcnl4000_readable_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case VCNL4000_COMMAND: > + case VCNL4000_PROD_REV: > + case VCNL4000_LED_CURRENT: > + case VCNL4000_AL_PARAM: > + case VCNL4000_AL_RESULT_HI: > + case VCNL4000_AL_RESULT_LO: > + case VCNL4000_PS_RESULT_HI: > + case VCNL4000_PS_RESULT_LO: > + case VCNL4000_PS_MEAS_FREQ: > + case VCNL4000_PS_MOD_ADJ: > + return true; > + default: > + return false; > + } > +} > + > +static bool vcnl4000_writeable_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case VCNL4000_COMMAND: > + case VCNL4000_LED_CURRENT: > + case VCNL4000_AL_PARAM: > + case VCNL4000_PS_MEAS_FREQ: > + case VCNL4000_PS_MOD_ADJ: > + return true; > + default: > + return false; > + } > +} > + > +static bool vcnl4000_volatile_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case VCNL4000_COMMAND: > + case VCNL4000_AL_RESULT_HI: > + case VCNL4000_AL_RESULT_LO: > + case VCNL4000_PS_RESULT_HI: > + case VCNL4000_PS_RESULT_LO: > + return true; > + default: > + return false; > + } > +} > + > +static const struct regmap_config vcnl4000_regmap_config = { > + .reg_bits = 8, > + .val_bits = 8, > + .max_register = VCNL4000_PS_MOD_ADJ, > + .readable_reg = vcnl4000_readable_reg, > + .writeable_reg = vcnl4000_writeable_reg, > + .volatile_reg = vcnl4000_volatile_reg, > +}; > + > static int vcnl4000_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > struct vcnl4000_data *data; > struct iio_dev *indio_dev; > int ret, prod_id; > + unsigned int regval; > > indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); > if (!indio_dev) > return -ENOMEM; > > data = iio_priv(indio_dev); > + data->regmap = devm_regmap_init_i2c(client, &vcnl4000_regmap_config); > + if (IS_ERR(data->regmap)) { > + dev_err(&client->dev, "regmap_init failed!\n"); > + return PTR_ERR(data->regmap); > + } > i2c_set_clientdata(client, indio_dev); > data->client = client; > mutex_init(&data->lock); > > - ret = i2c_smbus_read_byte_data(data->client, VCNL4000_PROD_REV); > + ret = regmap_read(data->regmap, VCNL4000_PROD_REV, ®val); > if (ret < 0) > return ret; > > - prod_id = ret >> 4; > + prod_id = regval >> 4; > if (prod_id != VCNL4010_ID && prod_id != VCNL4000_ID) > return -ENODEV; > > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support 2016-07-25 10:57 [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support Pratik Prajapati 2016-07-25 10:57 ` [PATCH v2 2/2] staging: iio: vcnl4000: Replace i2c api's with regmap Pratik Prajapati @ 2016-08-21 15:16 ` Jonathan Cameron 1 sibling, 0 replies; 4+ messages in thread From: Jonathan Cameron @ 2016-08-21 15:16 UTC (permalink / raw) To: Pratik Prajapati, Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler Cc: linux-iio, linux-kernel On 25/07/16 11:57, Pratik Prajapati wrote: > Signed-off-by: Pratik Prajapati <pratik.prajapati12@gmail.com> Sorry it took me so long to get to this. Wading back through my emails post holiday still. Small issue in the documentation. Jonathan > --- > Changes v1 -> v2: > - documented current_led files in ABI > - masked value while writing to led register > - added blank line before last return > - removed redundant return > > Documentation/ABI/testing/sysfs-bus-iio | 13 ++++++ > drivers/iio/light/vcnl4000.c | 77 ++++++++++++++++++++++++++++++--- > 2 files changed, 84 insertions(+), 6 deletions(-) > > diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio > index fee35c0..7129be6 100644 > --- a/Documentation/ABI/testing/sysfs-bus-iio > +++ b/Documentation/ABI/testing/sysfs-bus-iio > @@ -1579,3 +1579,16 @@ Contact: linux-iio@vger.kernel.org > Description: > Raw (unscaled no offset etc.) electric conductivity reading that > can be processed to siemens per meter. > + > +What: /sys/bus/iio/devices/iio:deviceX/in_current_led_raw > +KernelVersion: 4.8 > +Contact: linux-iio@vger.kernel.org > +Description: > + This controls the current to an IR LED. It's controlling an output is it not? Rather than monitoring the current through the LED. Should be out_current_led_raw Actually I think the issue is only in the docs as it looks right in the code. > + > +What: /sys/bus/iio/devices/iio:deviceX/in_current_led_scale > +KernelVersion: 4.8 > +Contact: linux-iio@vger.kernel.org > +Description: > + Specifies the conversion factor from the standard unit > + to device specific unit. out_ again. > diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c > index 360b6e9..dcf7a6f 100644 > --- a/drivers/iio/light/vcnl4000.c > +++ b/drivers/iio/light/vcnl4000.c > @@ -3,6 +3,7 @@ > * light and proximity sensor > * > * Copyright 2012 Peter Meerwald <pmeerw@pmeerw.net> > + * Copyright (C) 2016 Pratik Prajapati <pratik.prajapati12@gmail.com> > * > * This file is subject to the terms and conditions of version 2 of > * the GNU General Public License. See the file COPYING in the main > @@ -11,7 +12,6 @@ > * IIO driver for VCNL4000 (7-bit I2C slave address 0x13) > * > * TODO: > - * allow to adjust IR current > * proximity threshold and event handling > * periodic ALS/proximity measurement (VCNL4010/20) > * interrupts (VCNL4010/20) > @@ -46,6 +46,10 @@ > #define VCNL4000_AL_OD BIT(4) /* start on-demand ALS measurement */ > #define VCNL4000_PS_OD BIT(3) /* start on-demand proximity measurement */ > > +/* Bit mask for LED_CURRENT register */ > +#define VCNL4000_LED_CURRENT_MASK 0x3F > +#define VCNL4000_LED_CURRENT_MAX 20 > + > struct vcnl4000_data { > struct i2c_client *client; > struct mutex lock; > @@ -111,9 +115,43 @@ static const struct iio_chan_spec vcnl4000_channels[] = { > }, { > .type = IIO_PROXIMITY, > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), > - } > + }, { > + .type = IIO_CURRENT, > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | > + BIT(IIO_CHAN_INFO_SCALE), > + .extend_name = "led", > + .output = 1, > + .scan_index = -1, > + }, > }; > > +static int vcnl4000_write_led_current_raw(struct vcnl4000_data *data, int val) > +{ > + int ret; > + > + if (val < 0 || val > VCNL4000_LED_CURRENT_MAX) > + return -ERANGE; > + mutex_lock(&data->lock); > + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_LED_CURRENT, > + VCNL4000_LED_CURRENT_MASK & val); > + mutex_unlock(&data->lock); > + > + return ret; > +} > + > +static int vcnl4000_read_led_current_raw(struct vcnl4000_data *data) > +{ > + int ret; > + > + mutex_lock(&data->lock); > + ret = i2c_smbus_read_byte_data(data->client, VCNL4000_LED_CURRENT); > + mutex_unlock(&data->lock); > + if (ret < 0) > + return ret; > + > + return ret &= VCNL4000_LED_CURRENT_MASK; > +} > + > static int vcnl4000_read_raw(struct iio_dev *indio_dev, > struct iio_chan_spec const *chan, > int *val, int *val2, long mask) > @@ -138,23 +176,50 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, > if (ret < 0) > return ret; > return IIO_VAL_INT; > + case IIO_CURRENT: > + ret = vcnl4000_read_led_current_raw(data); > + if (ret < 0) > + return ret; > + *val = ret; > + return IIO_VAL_INT; > default: > return -EINVAL; > } > + > case IIO_CHAN_INFO_SCALE: > - if (chan->type != IIO_LIGHT) > + switch (chan->type) { > + case IIO_LIGHT: > + *val = 0; > + *val2 = 250000; > + return IIO_VAL_INT_PLUS_MICRO; > + case IIO_CURRENT: > + /* Output register is in 10s of milliamps */ > + *val = 10; > + return IIO_VAL_INT; > + default: > return -EINVAL; > + } > > - *val = 0; > - *val2 = 250000; > - return IIO_VAL_INT_PLUS_MICRO; > default: > return -EINVAL; > } > } > > +static int vcnl4000_write_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int val, int val2, long mask) > +{ > + struct vcnl4000_data *data = iio_priv(indio_dev); > + > + if (mask == IIO_CHAN_INFO_RAW && chan->type == IIO_CURRENT) > + return vcnl4000_write_led_current_raw(data, val); > + > + return -EINVAL; > +} > + > static const struct iio_info vcnl4000_info = { > .read_raw = vcnl4000_read_raw, > + .write_raw = vcnl4000_write_raw, > .driver_module = THIS_MODULE, > }; > > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2016-08-21 15:21 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-07-25 10:57 [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support Pratik Prajapati 2016-07-25 10:57 ` [PATCH v2 2/2] staging: iio: vcnl4000: Replace i2c api's with regmap Pratik Prajapati 2016-08-21 15:21 ` Jonathan Cameron 2016-08-21 15:16 ` [PATCH v2 1/2] staging: iio: vcnl4000: Add IR current adjust support Jonathan Cameron
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).