aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/iio/light/isl29018.c
diff options
context:
space:
mode:
authorBryan Freed <bfreed@chromium.org>2012-09-05 15:55:00 -0400
committerJonathan Cameron <jic23@kernel.org>2012-09-08 05:25:10 -0400
commit932323b74e2535dbb6a1b245dfa1aa8cd2bbd8e2 (patch)
treedd7fda9f5b49de9d7c5260b44b63af1c86348eef /drivers/staging/iio/light/isl29018.c
parent7b123c85bbb3fadbd02b82d77d5aee0c399b0e06 (diff)
iio: isl29018: Support fractional ALS scaling.
The Industrial IO framework supports scaling ADC values by fractions, but most drivers default to using whole numbers. This change turns on fractional scaling in the isl29018 driver. Signed-off-by: Bryan Freed <bfreed@chromium.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/staging/iio/light/isl29018.c')
-rw-r--r--drivers/staging/iio/light/isl29018.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index 31d22f5591c..6ee5567d981 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -63,6 +63,7 @@ struct isl29018_chip {
63 struct regmap *regmap; 63 struct regmap *regmap;
64 struct mutex lock; 64 struct mutex lock;
65 unsigned int lux_scale; 65 unsigned int lux_scale;
66 unsigned int lux_uscale;
66 unsigned int range; 67 unsigned int range;
67 unsigned int adc_bit; 68 unsigned int adc_bit;
68 int prox_scheme; 69 int prox_scheme;
@@ -145,13 +146,22 @@ static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
145static int isl29018_read_lux(struct isl29018_chip *chip, int *lux) 146static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
146{ 147{
147 int lux_data; 148 int lux_data;
149 unsigned int data_x_range, lux_unshifted;
148 150
149 lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE); 151 lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
150 152
151 if (lux_data < 0) 153 if (lux_data < 0)
152 return lux_data; 154 return lux_data;
153 155
154 *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit; 156 /* To support fractional scaling, separate the unshifted lux
157 * into two calculations: int scaling and micro-scaling.
158 * lux_uscale ranges from 0-999999, so about 20 bits. Split
159 * the /1,000,000 in two to reduce the risk of over/underflow.
160 */
161 data_x_range = lux_data * chip->range;
162 lux_unshifted = data_x_range * chip->lux_scale;
163 lux_unshifted += data_x_range / 1000 * chip->lux_uscale / 1000;
164 *lux = lux_unshifted >> chip->adc_bit;
155 165
156 return 0; 166 return 0;
157} 167}
@@ -339,6 +349,8 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
339 mutex_lock(&chip->lock); 349 mutex_lock(&chip->lock);
340 if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) { 350 if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) {
341 chip->lux_scale = val; 351 chip->lux_scale = val;
352 /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */
353 chip->lux_uscale = val2;
342 ret = 0; 354 ret = 0;
343 } 355 }
344 mutex_unlock(&chip->lock); 356 mutex_unlock(&chip->lock);
@@ -379,7 +391,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
379 case IIO_CHAN_INFO_CALIBSCALE: 391 case IIO_CHAN_INFO_CALIBSCALE:
380 if (chan->type == IIO_LIGHT) { 392 if (chan->type == IIO_LIGHT) {
381 *val = chip->lux_scale; 393 *val = chip->lux_scale;
382 ret = IIO_VAL_INT; 394 *val2 = chip->lux_uscale;
395 ret = IIO_VAL_INT_PLUS_MICRO;
383 } 396 }
384 break; 397 break;
385 default: 398 default: