* [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 an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.