Re: [PATCH] iio: isl29018: Support fractional ALS scaling.

2012-09-08 Thread Jonathan Cameron
On 09/05/2012 08:55 PM, Bryan Freed wrote:
> 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 

add to togreg branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git

Thanks

Technically doing integer + micro values is actually pretty common
but having calibration scale is less so. Doesn't seem any harm in doing
it here, though as calibscale is of an arbitary scaling itself, if it
wasn't an abi change (which this is not) then I'd suggest just doing it
as a 1000 * the original value.

Still this does the job nicely so thanks!

Jonathan
> ---
>  drivers/staging/iio/light/isl29018.c |   17 +++--
>  1 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/staging/iio/light/isl29018.c 
> b/drivers/staging/iio/light/isl29018.c
> index 31d22f5..6ee5567 100644
> --- a/drivers/staging/iio/light/isl29018.c
> +++ b/drivers/staging/iio/light/isl29018.c
> @@ -63,6 +63,7 @@ struct isl29018_chip {
>   struct regmap   *regmap;
>   struct mutexlock;
>   unsigned intlux_scale;
> + unsigned intlux_uscale;
>   unsigned intrange;
>   unsigned intadc_bit;
>   int prox_scheme;
> @@ -145,13 +146,22 @@ 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;
>  
>   lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
>  
>   if (lux_data < 0)
>   return lux_data;
>  
> - *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit;
> + /* To support fractional scaling, separate the unshifted lux
> +  * into two calculations: int scaling and micro-scaling.
> +  * lux_uscale ranges from 0-99, 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 = lux_unshifted >> chip->adc_bit;
>  
>   return 0;
>  }
> @@ -339,6 +349,8 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
>   mutex_lock(>lock);
>   if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) {
>   chip->lux_scale = val;
> + /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */
> + chip->lux_uscale = val2;
>   ret = 0;
>   }
>   mutex_unlock(>lock);
> @@ -379,7 +391,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
>   case IIO_CHAN_INFO_CALIBSCALE:
>   if (chan->type == IIO_LIGHT) {
>   *val = chip->lux_scale;
> - ret = IIO_VAL_INT;
> + *val2 = chip->lux_uscale;
> + ret = IIO_VAL_INT_PLUS_MICRO;
>   }
>   break;
>   default:
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] iio: isl29018: Support fractional ALS scaling.

2012-09-08 Thread Jonathan Cameron
On 09/05/2012 08:55 PM, Bryan Freed wrote:
 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 bfr...@chromium.org

add to togreg branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git

Thanks

Technically doing integer + micro values is actually pretty common
but having calibration scale is less so. Doesn't seem any harm in doing
it here, though as calibscale is of an arbitary scaling itself, if it
wasn't an abi change (which this is not) then I'd suggest just doing it
as a 1000 * the original value.

Still this does the job nicely so thanks!

Jonathan
 ---
  drivers/staging/iio/light/isl29018.c |   17 +++--
  1 files changed, 15 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/staging/iio/light/isl29018.c 
 b/drivers/staging/iio/light/isl29018.c
 index 31d22f5..6ee5567 100644
 --- a/drivers/staging/iio/light/isl29018.c
 +++ b/drivers/staging/iio/light/isl29018.c
 @@ -63,6 +63,7 @@ struct isl29018_chip {
   struct regmap   *regmap;
   struct mutexlock;
   unsigned intlux_scale;
 + unsigned intlux_uscale;
   unsigned intrange;
   unsigned intadc_bit;
   int prox_scheme;
 @@ -145,13 +146,22 @@ 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;
  
   lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
  
   if (lux_data  0)
   return lux_data;
  
 - *lux = (lux_data * chip-range * chip-lux_scale)  chip-adc_bit;
 + /* To support fractional scaling, separate the unshifted lux
 +  * into two calculations: int scaling and micro-scaling.
 +  * lux_uscale ranges from 0-99, 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 = lux_unshifted  chip-adc_bit;
  
   return 0;
  }
 @@ -339,6 +349,8 @@ 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;
 + /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */
 + chip-lux_uscale = val2;
   ret = 0;
   }
   mutex_unlock(chip-lock);
 @@ -379,7 +391,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
   case IIO_CHAN_INFO_CALIBSCALE:
   if (chan-type == IIO_LIGHT) {
   *val = chip-lux_scale;
 - ret = IIO_VAL_INT;
 + *val2 = chip-lux_uscale;
 + ret = IIO_VAL_INT_PLUS_MICRO;
   }
   break;
   default:
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] iio: isl29018: Support fractional ALS scaling.

2012-09-05 Thread Bryan Freed
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 
---
 drivers/staging/iio/light/isl29018.c |   17 +++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/iio/light/isl29018.c 
b/drivers/staging/iio/light/isl29018.c
index 31d22f5..6ee5567 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -63,6 +63,7 @@ struct isl29018_chip {
struct regmap   *regmap;
struct mutexlock;
unsigned intlux_scale;
+   unsigned intlux_uscale;
unsigned intrange;
unsigned intadc_bit;
int prox_scheme;
@@ -145,13 +146,22 @@ 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;
 
lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
 
if (lux_data < 0)
return lux_data;
 
-   *lux = (lux_data * chip->range * chip->lux_scale) >> chip->adc_bit;
+   /* To support fractional scaling, separate the unshifted lux
+* into two calculations: int scaling and micro-scaling.
+* lux_uscale ranges from 0-99, 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 = lux_unshifted >> chip->adc_bit;
 
return 0;
 }
@@ -339,6 +349,8 @@ static int isl29018_write_raw(struct iio_dev *indio_dev,
mutex_lock(>lock);
if (mask == IIO_CHAN_INFO_CALIBSCALE && chan->type == IIO_LIGHT) {
chip->lux_scale = val;
+   /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */
+   chip->lux_uscale = val2;
ret = 0;
}
mutex_unlock(>lock);
@@ -379,7 +391,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_CALIBSCALE:
if (chan->type == IIO_LIGHT) {
*val = chip->lux_scale;
-   ret = IIO_VAL_INT;
+   *val2 = chip->lux_uscale;
+   ret = IIO_VAL_INT_PLUS_MICRO;
}
break;
default:
-- 
1.7.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] iio: isl29018: Support fractional ALS scaling.

2012-09-05 Thread Bryan Freed
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 bfr...@chromium.org
---
 drivers/staging/iio/light/isl29018.c |   17 +++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/iio/light/isl29018.c 
b/drivers/staging/iio/light/isl29018.c
index 31d22f5..6ee5567 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -63,6 +63,7 @@ struct isl29018_chip {
struct regmap   *regmap;
struct mutexlock;
unsigned intlux_scale;
+   unsigned intlux_uscale;
unsigned intrange;
unsigned intadc_bit;
int prox_scheme;
@@ -145,13 +146,22 @@ 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;
 
lux_data = isl29018_read_sensor_input(chip, COMMMAND1_OPMODE_ALS_ONCE);
 
if (lux_data  0)
return lux_data;
 
-   *lux = (lux_data * chip-range * chip-lux_scale)  chip-adc_bit;
+   /* To support fractional scaling, separate the unshifted lux
+* into two calculations: int scaling and micro-scaling.
+* lux_uscale ranges from 0-99, 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 = lux_unshifted  chip-adc_bit;
 
return 0;
 }
@@ -339,6 +349,8 @@ 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;
+   /* With no write_raw_get_fmt(), val2 is a MICRO fraction. */
+   chip-lux_uscale = val2;
ret = 0;
}
mutex_unlock(chip-lock);
@@ -379,7 +391,8 @@ static int isl29018_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_CALIBSCALE:
if (chan-type == IIO_LIGHT) {
*val = chip-lux_scale;
-   ret = IIO_VAL_INT;
+   *val2 = chip-lux_uscale;
+   ret = IIO_VAL_INT_PLUS_MICRO;
}
break;
default:
-- 
1.7.7.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/