From e98ceca076bb37d42116c5395ba40d7e31ba869c Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Thu, 16 Apr 2015 22:20:57 +0300 Subject: staging: iio: light: isl29018: Remove non-standard sysfs attributes This patch removes non-standard sysfs attributes range, range_available, adc_resolution and adc_resolution_available. It also removes the corresponding show and store functions. This is in preparation for using standard IIO attributes in order to move the code out of staging. Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 94 ------------------------------------ 1 file changed, 94 deletions(-) (limited to 'drivers/staging/iio') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index a3489187aeb0..d3d0611d0cb4 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -230,87 +230,6 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, } /* Sysfs interface */ -/* range */ -static ssize_t show_range(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", chip->range); -} - -static ssize_t store_range(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - int status; - unsigned long lval; - unsigned int new_range; - - if (kstrtoul(buf, 10, &lval)) - return -EINVAL; - - if (!(lval == 1000UL || lval == 4000UL || - lval == 16000UL || lval == 64000UL)) { - dev_err(dev, "The range is not supported\n"); - return -EINVAL; - } - - mutex_lock(&chip->lock); - status = isl29018_set_range(chip, lval, &new_range); - if (status < 0) { - mutex_unlock(&chip->lock); - dev_err(dev, - "Error in setting max range with err %d\n", status); - return status; - } - chip->range = new_range; - mutex_unlock(&chip->lock); - - return count; -} - -/* resolution */ -static ssize_t show_resolution(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - - return sprintf(buf, "%u\n", chip->adc_bit); -} - -static ssize_t store_resolution(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct isl29018_chip *chip = iio_priv(indio_dev); - int status; - unsigned int val; - unsigned int new_adc_bit; - - if (kstrtouint(buf, 10, &val)) - return -EINVAL; - if (!(val == 4 || val == 8 || val == 12 || val == 16)) { - dev_err(dev, "The resolution is not supported\n"); - return -EINVAL; - } - - mutex_lock(&chip->lock); - status = isl29018_set_resolution(chip, val, &new_adc_bit); - if (status < 0) { - mutex_unlock(&chip->lock); - dev_err(dev, "Error in setting resolution\n"); - return status; - } - chip->adc_bit = new_adc_bit; - mutex_unlock(&chip->lock); - - return count; -} - /* proximity scheme */ static ssize_t show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) @@ -447,11 +366,6 @@ static const struct iio_chan_spec isl29023_channels[] = { ISL29018_IR_CHANNEL, }; -static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, show_range, store_range, 0); -static IIO_CONST_ATTR(range_available, "1000 4000 16000 64000"); -static IIO_CONST_ATTR(adc_resolution_available, "4 8 12 16"); -static IIO_DEVICE_ATTR(adc_resolution, S_IRUGO | S_IWUSR, - show_resolution, store_resolution, 0); static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, show_prox_infrared_suppression, @@ -460,19 +374,11 @@ static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) #define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) static struct attribute *isl29018_attributes[] = { - ISL29018_DEV_ATTR(range), - ISL29018_CONST_ATTR(range_available), - ISL29018_DEV_ATTR(adc_resolution), - ISL29018_CONST_ATTR(adc_resolution_available), ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), NULL }; static struct attribute *isl29023_attributes[] = { - ISL29018_DEV_ATTR(range), - ISL29018_CONST_ATTR(range_available), - ISL29018_DEV_ATTR(adc_resolution), - ISL29018_CONST_ATTR(adc_resolution_available), NULL }; -- cgit v1.2.3-59-g8ed1b From 809a591b16781cc69f1f3ff2cc9a790e3ae8ec8f Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Thu, 16 Apr 2015 22:20:58 +0300 Subject: staging: iio: light: isl29018: Rename lux_scale to calibscale This patch renames lux_scale to calibscale and lux_uscale to ucalibscale. This is done in order to avoid confusion since these parameters are used for hardware applied calibration. Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/staging/iio') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index d3d0611d0cb4..ffc3d1b2ee9a 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -71,8 +71,8 @@ struct isl29018_chip { struct regmap *regmap; struct mutex lock; int type; - unsigned int lux_scale; - unsigned int lux_uscale; + unsigned int calibscale; + unsigned int ucalibscale; unsigned int range; unsigned int adc_bit; int prox_scheme; @@ -165,12 +165,12 @@ static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) /* To support fractional scaling, separate the unshifted lux * into two calculations: int scaling and micro-scaling. - * lux_uscale ranges from 0-999999, so about 20 bits. Split + * ucalibscale ranges from 0-999999, so about 20 bits. Split * the /1,000,000 in two to reduce the risk of over/underflow. */ data_x_range = lux_data * chip->range; - lux_unshifted = data_x_range * chip->lux_scale; - lux_unshifted += data_x_range / 1000 * chip->lux_uscale / 1000; + lux_unshifted = data_x_range * chip->calibscale; + lux_unshifted += data_x_range / 1000 * chip->ucalibscale / 1000; *lux = lux_unshifted >> chip->adc_bit; return 0; @@ -277,9 +277,9 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, mutex_lock(&chip->lock); if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { - chip->lux_scale = val; + chip->calibscale = val; /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */ - chip->lux_uscale = val2; + chip->ucalibscale = val2; ret = 0; } mutex_unlock(&chip->lock); @@ -323,8 +323,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { - *val = chip->lux_scale; - *val2 = chip->lux_uscale; + *val = chip->calibscale; + *val2 = chip->ucalibscale; ret = IIO_VAL_INT_PLUS_MICRO; } break; @@ -607,8 +607,8 @@ static int isl29018_probe(struct i2c_client *client, mutex_init(&chip->lock); chip->type = dev_id; - chip->lux_scale = 1; - chip->lux_uscale = 0; + chip->calibscale = 1; + chip->ucalibscale = 0; chip->range = 1000; chip->adc_bit = 16; chip->suspended = false; -- cgit v1.2.3-59-g8ed1b From 6920ccf65d0964f7f6c6c36c551151e0fcd62327 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Thu, 16 Apr 2015 22:20:59 +0300 Subject: staging: iio: light: isl29018: Use standard sysfs attributes for scale and integration time This patch refactors the isl29018 driver code in order to use standard sysfs attributes for scale and integration time. ISL29018 light sensor uses four ranges and four ADC's resolutions which influence the calculated lux. Adc resolution is strongly connected to integration time and range should be controlled by scale. This patch introduces the usage of integration time and scale instead of adc resolution and range. Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/staging/iio/light/isl29018.c | 226 +++++++++++++++++++++++++++-------- 1 file changed, 177 insertions(+), 49 deletions(-) (limited to 'drivers/staging/iio') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index ffc3d1b2ee9a..08ca9a4172e3 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -66,6 +66,39 @@ #define ISL29035_BOUT_SHIFT 0x07 #define ISL29035_BOUT_MASK (0x01 << ISL29035_BOUT_SHIFT) +#define ISL29018_INT_TIME_AVAIL "0.090000 0.005630 0.000351 0.000021" +#define ISL29023_INT_TIME_AVAIL "0.090000 0.005600 0.000352 0.000022" +#define ISL29035_INT_TIME_AVAIL "0.105000 0.006500 0.000410 0.000025" + +static const char * const int_time_avail[] = { + ISL29018_INT_TIME_AVAIL, + ISL29023_INT_TIME_AVAIL, + ISL29035_INT_TIME_AVAIL, +}; + +enum isl29018_int_time { + ISL29018_INT_TIME_16, + ISL29018_INT_TIME_12, + ISL29018_INT_TIME_8, + ISL29018_INT_TIME_4, +}; + +static const unsigned int isl29018_int_utimes[3][4] = { + {90000, 5630, 351, 21}, + {90000, 5600, 352, 22}, + {105000, 6500, 410, 25}, +}; + +static const struct isl29018_scale { + unsigned int scale; + unsigned int uscale; +} isl29018_scales[4][4] = { + { {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} }, + { {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} }, + { {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} }, + { {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} } +}; + struct isl29018_chip { struct device *dev; struct regmap *regmap; @@ -73,51 +106,75 @@ struct isl29018_chip { int type; unsigned int calibscale; unsigned int ucalibscale; - unsigned int range; - unsigned int adc_bit; + unsigned int int_time; + struct isl29018_scale scale; int prox_scheme; bool suspended; }; -static int isl29018_set_range(struct isl29018_chip *chip, unsigned long range, - unsigned int *new_range) +static int isl29018_set_integration_time(struct isl29018_chip *chip, + unsigned int utime) { - static const unsigned long supp_ranges[] = {1000, 4000, 16000, 64000}; - int i; - - for (i = 0; i < ARRAY_SIZE(supp_ranges); ++i) { - if (range <= supp_ranges[i]) { - *new_range = (unsigned int)supp_ranges[i]; + int i, ret; + unsigned int int_time, new_int_time; + struct isl29018_scale new_scale; + + for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) { + if (utime == isl29018_int_utimes[chip->type][i]) { + new_int_time = i; + new_scale = isl29018_scales[new_int_time][0]; break; } } - if (i >= ARRAY_SIZE(supp_ranges)) + if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type])) return -EINVAL; - return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RANGE_MASK, i << COMMANDII_RANGE_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_RESOLUTION_MASK, + i << COMMANDII_RESOLUTION_SHIFT); + if (ret < 0) + return ret; + + /* keep the same range when integration time changes */ + int_time = chip->int_time; + for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) { + if (chip->scale.scale == isl29018_scales[int_time][i].scale && + chip->scale.uscale == isl29018_scales[int_time][i].uscale) { + chip->scale = isl29018_scales[new_int_time][i]; + break; + } + } + chip->int_time = new_int_time; + + return 0; } -static int isl29018_set_resolution(struct isl29018_chip *chip, - unsigned long adcbit, unsigned int *conf_adc_bit) +static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale) { - static const unsigned long supp_adcbit[] = {16, 12, 8, 4}; - int i; + int i, ret; + struct isl29018_scale new_scale; - for (i = 0; i < ARRAY_SIZE(supp_adcbit); ++i) { - if (adcbit >= supp_adcbit[i]) { - *conf_adc_bit = (unsigned int)supp_adcbit[i]; + for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) { + if (scale == isl29018_scales[chip->int_time][i].scale && + uscale == isl29018_scales[chip->int_time][i].uscale) { + new_scale = isl29018_scales[chip->int_time][i]; break; } } - if (i >= ARRAY_SIZE(supp_adcbit)) + if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time])) return -EINVAL; - return regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, - COMMANDII_RESOLUTION_MASK, - i << COMMANDII_RESOLUTION_SHIFT); + ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMANDII, + COMMANDII_RANGE_MASK, + i << COMMANDII_RANGE_SHIFT); + if (ret < 0) + return ret; + + chip->scale = new_scale; + + return 0; } static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) @@ -156,22 +213,17 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode) static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) { int lux_data; - unsigned int data_x_range, lux_unshifted; + unsigned int data_x_range; lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); if (lux_data < 0) return lux_data; - /* To support fractional scaling, separate the unshifted lux - * into two calculations: int scaling and micro-scaling. - * ucalibscale ranges from 0-999999, so about 20 bits. Split - * the /1,000,000 in two to reduce the risk of over/underflow. - */ - data_x_range = lux_data * chip->range; - lux_unshifted = data_x_range * chip->calibscale; - lux_unshifted += data_x_range / 1000 * chip->ucalibscale / 1000; - *lux = lux_unshifted >> chip->adc_bit; + data_x_range = lux_data * chip->scale.scale + + lux_data * chip->scale.uscale / 1000000; + *lux = data_x_range * chip->calibscale + + data_x_range * chip->ucalibscale / 1000000; return 0; } @@ -229,7 +281,39 @@ static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme, return 0; } -/* Sysfs interface */ +static ssize_t show_scale_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) + len += sprintf(buf + len, "%d.%06d ", + isl29018_scales[chip->int_time][i].scale, + isl29018_scales[chip->int_time][i].uscale); + + buf[len - 1] = '\n'; + + return len; +} + +static ssize_t show_int_time_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct isl29018_chip *chip = iio_priv(indio_dev); + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) + len += sprintf(buf + len, "0.%06d ", + isl29018_int_utimes[chip->type][i]); + + buf[len - 1] = '\n'; + + return len; +} + /* proximity scheme */ static ssize_t show_prox_infrared_suppression(struct device *dev, struct device_attribute *attr, char *buf) @@ -276,11 +360,28 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, int ret = -EINVAL; mutex_lock(&chip->lock); - if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { - chip->calibscale = val; - /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */ - chip->ucalibscale = val2; - ret = 0; + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + if (chan->type == IIO_LIGHT) { + chip->calibscale = val; + chip->ucalibscale = val2; + ret = 0; + } + break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT) + if (val != 0) { + mutex_unlock(&chip->lock); + return -EINVAL; + } + ret = isl29018_set_integration_time(chip, val2); + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) + ret = isl29018_set_scale(chip, val, val2); + break; + default: + break; } mutex_unlock(&chip->lock); @@ -321,6 +422,20 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, if (!ret) ret = IIO_VAL_INT; break; + case IIO_CHAN_INFO_INT_TIME: + if (chan->type == IIO_LIGHT) { + *val = 0; + *val2 = isl29018_int_utimes[chip->type][chip->int_time]; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; + case IIO_CHAN_INFO_SCALE: + if (chan->type == IIO_LIGHT) { + *val = chip->scale.scale; + *val2 = chip->scale.uscale; + ret = IIO_VAL_INT_PLUS_MICRO; + } + break; case IIO_CHAN_INFO_CALIBSCALE: if (chan->type == IIO_LIGHT) { *val = chip->calibscale; @@ -340,7 +455,9 @@ static int isl29018_read_raw(struct iio_dev *indio_dev, .indexed = 1, \ .channel = 0, \ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE), \ + BIT(IIO_CHAN_INFO_CALIBSCALE) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ } #define ISL29018_IR_CHANNEL { \ @@ -366,19 +483,27 @@ static const struct iio_chan_spec isl29023_channels[] = { ISL29018_IR_CHANNEL, }; +static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, S_IRUGO, + show_int_time_available, NULL, 0); +static IIO_DEVICE_ATTR(in_illuminance_scale_available, S_IRUGO, + show_scale_available, NULL, 0); static IIO_DEVICE_ATTR(proximity_on_chip_ambient_infrared_suppression, S_IRUGO | S_IWUSR, show_prox_infrared_suppression, store_prox_infrared_suppression, 0); #define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr) -#define ISL29018_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr) + static struct attribute *isl29018_attributes[] = { + ISL29018_DEV_ATTR(in_illuminance_scale_available), + ISL29018_DEV_ATTR(in_illuminance_integration_time_available), ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression), NULL }; static struct attribute *isl29023_attributes[] = { + ISL29018_DEV_ATTR(in_illuminance_scale_available), + ISL29018_DEV_ATTR(in_illuminance_integration_time_available), NULL }; @@ -422,8 +547,6 @@ enum { static int isl29018_chip_init(struct isl29018_chip *chip) { int status; - unsigned int new_adc_bit; - unsigned int new_range; if (chip->type == isl29035) { status = isl29035_detect(chip); @@ -472,14 +595,19 @@ static int isl29018_chip_init(struct isl29018_chip *chip) usleep_range(1000, 2000); /* per data sheet, page 10 */ /* set defaults */ - status = isl29018_set_range(chip, chip->range, &new_range); + status = isl29018_set_scale(chip, chip->scale.scale, + chip->scale.uscale); if (status < 0) { dev_err(chip->dev, "Init of isl29018 fails\n"); return status; } - status = isl29018_set_resolution(chip, chip->adc_bit, - &new_adc_bit); + status = isl29018_set_integration_time(chip, + isl29018_int_utimes[chip->type][chip->int_time]); + if (status < 0) { + dev_err(chip->dev, "Init of isl29018 fails\n"); + return status; + } return 0; } @@ -609,8 +737,8 @@ static int isl29018_probe(struct i2c_client *client, chip->type = dev_id; chip->calibscale = 1; chip->ucalibscale = 0; - chip->range = 1000; - chip->adc_bit = 16; + chip->int_time = ISL29018_INT_TIME_16; + chip->scale = isl29018_scales[chip->int_time][0]; chip->suspended = false; chip->regmap = devm_regmap_init_i2c(client, -- cgit v1.2.3-59-g8ed1b From b91617ea62af5558af598ae9ad069db96f2ab00e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 2 May 2015 12:05:05 +0100 Subject: staging:iio:light: Add some missing brackets to make sure code works as intended. Note this is not a bug due to the fact the region cannot be reached without the sanity check passing. The autobuilder reported it as missaligned code which is kind of true as well. Signed-off-by: Jonathan Cameron Cc: Roberta Dobrescu --- drivers/staging/iio/light/isl29018.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/iio') diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 08ca9a4172e3..e646c5d24004 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -369,12 +369,13 @@ static int isl29018_write_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_INT_TIME: - if (chan->type == IIO_LIGHT) + if (chan->type == IIO_LIGHT) { if (val != 0) { mutex_unlock(&chip->lock); return -EINVAL; } ret = isl29018_set_integration_time(chip, val2); + } break; case IIO_CHAN_INFO_SCALE: if (chan->type == IIO_LIGHT) -- cgit v1.2.3-59-g8ed1b