Re: [PATCH v3 1/2] staging: iio: isl29028: correct proximity sleep times
From: Jonathan Cameron
Date: Wed Apr 26 2017 - 01:30:34 EST
On 25/04/17 02:34, Brian Masney wrote:
> The sysfs attribute in_proximity_sampling_frequency_available currently
> shows the values 1 3 5 10 13 20 83 100. These values are supposed to
> correspond to the sleep values 800 400 200 100 75 50 12.5 0 (all in ms).
> When passing in a sampling frequency of 3, it actually uses a sleep
> time of 200ms instead of the expected 400ms value. This patch changes
> the value shown by this sysfs attribute to use fixed-point numbers so
> that the correct sampling frequency is shown to the user. This patch
> also changes the code that updates the proximity sampling frequency to
> only allow values that are shown in the _available sysfs attribute.
>
> The original code showed the value 83 that corresponds to the sleep
> time 12 ms. The data sheet actually lists 12.5 ms as the sleep time,
> so the proximity frequency was updated to 80.
>
> Signed-off-by: Brian Masney <masneyb@xxxxxxxxxxxxx>
Applied to the togreg branch of iio.git and pushed out as testing for the
autobuilders to play with it.
Thanks,
Jonathan
> ---
> drivers/staging/iio/light/isl29028.c | 70 +++++++++++++++++++++++++-----------
> 1 file changed, 50 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
> index 5375e7a..aeb5082 100644
> --- a/drivers/staging/iio/light/isl29028.c
> +++ b/drivers/staging/iio/light/isl29028.c
> @@ -64,8 +64,25 @@
>
> #define ISL29028_POWER_OFF_DELAY_MS 2000
>
> -static const unsigned int isl29028_prox_sleep_time[] = {800, 400, 200, 100, 75,
> - 50, 12, 0};
> +struct isl29028_prox_data {
> + int sampling_int;
> + int sampling_fract;
> + int sleep_time;
> +};
> +
> +static const struct isl29028_prox_data isl29028_prox_data[] = {
> + { 1, 250000, 800 },
> + { 2, 500000, 400 },
> + { 5, 0, 200 },
> + { 10, 0, 100 },
> + { 13, 300000, 75 },
> + { 20, 0, 50 },
> + { 80, 0, 13 }, /*
> + * Note: Data sheet lists 12.5 ms sleep time.
> + * Round up a half millisecond for msleep().
> + */
> + { 100, 0, 0 }
> +};
>
> enum isl29028_als_ir_mode {
> ISL29028_MODE_NONE = 0,
> @@ -76,32 +93,37 @@ enum isl29028_als_ir_mode {
> struct isl29028_chip {
> struct mutex lock;
> struct regmap *regmap;
> - unsigned int prox_sampling;
> + int prox_sampling_int;
> + int prox_sampling_frac;
> bool enable_prox;
> int lux_scale;
> enum isl29028_als_ir_mode als_ir_mode;
> };
>
> -static int isl29028_find_prox_sleep_time_index(int sampling)
> +static int isl29028_find_prox_sleep_index(int sampling_int, int sampling_fract)
> {
> - unsigned int period = DIV_ROUND_UP(1000, sampling);
> int i;
>
> - for (i = 0; i < ARRAY_SIZE(isl29028_prox_sleep_time); ++i) {
> - if (period >= isl29028_prox_sleep_time[i])
> - break;
> + for (i = 0; i < ARRAY_SIZE(isl29028_prox_data); ++i) {
> + if (isl29028_prox_data[i].sampling_int == sampling_int &&
> + isl29028_prox_data[i].sampling_fract == sampling_fract)
> + return i;
> }
>
> - return i;
> + return -EINVAL;
> }
>
> static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
> - unsigned int sampling)
> + int sampling_int, int sampling_fract)
> {
> struct device *dev = regmap_get_device(chip->regmap);
> int sleep_index, ret;
>
> - sleep_index = isl29028_find_prox_sleep_time_index(sampling);
> + sleep_index = isl29028_find_prox_sleep_index(sampling_int,
> + sampling_fract);
> + if (sleep_index < 0)
> + return sleep_index;
> +
> ret = regmap_update_bits(chip->regmap, ISL29028_REG_CONFIGURE,
> ISL29028_CONF_PROX_SLP_MASK,
> sleep_index << ISL29028_CONF_PROX_SLP_SH);
> @@ -112,16 +134,18 @@ static int isl29028_set_proxim_sampling(struct isl29028_chip *chip,
> return ret;
> }
>
> - chip->prox_sampling = sampling;
> + chip->prox_sampling_int = sampling_int;
> + chip->prox_sampling_frac = sampling_fract;
>
> return ret;
> }
>
> static int isl29028_enable_proximity(struct isl29028_chip *chip)
> {
> - int sleep_index, ret;
> + int prox_index, ret;
>
> - ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
> + ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling_int,
> + chip->prox_sampling_frac);
> if (ret < 0)
> return ret;
>
> @@ -132,8 +156,12 @@ static int isl29028_enable_proximity(struct isl29028_chip *chip)
> return ret;
>
> /* Wait for conversion to be complete for first sample */
> - sleep_index = isl29028_find_prox_sleep_time_index(chip->prox_sampling);
> - msleep(isl29028_prox_sleep_time[sleep_index]);
> + prox_index = isl29028_find_prox_sleep_index(chip->prox_sampling_int,
> + chip->prox_sampling_frac);
> + if (prox_index < 0)
> + return prox_index;
> +
> + msleep(isl29028_prox_data[prox_index].sleep_time);
>
> return 0;
> }
> @@ -361,7 +389,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
> break;
> }
>
> - ret = isl29028_set_proxim_sampling(chip, val);
> + ret = isl29028_set_proxim_sampling(chip, val, val2);
> break;
> case IIO_LIGHT:
> if (mask != IIO_CHAN_INFO_SCALE) {
> @@ -439,7 +467,8 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
> if (chan->type != IIO_PROXIMITY)
> break;
>
> - *val = chip->prox_sampling;
> + *val = chip->prox_sampling_int;
> + *val2 = chip->prox_sampling_frac;
> ret = IIO_VAL_INT;
> break;
> case IIO_CHAN_INFO_SCALE:
> @@ -472,7 +501,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
> }
>
> static IIO_CONST_ATTR(in_proximity_sampling_frequency_available,
> - "1 3 5 10 13 20 83 100");
> + "1.25 2.5 5 10 13.3 20 80 100");
> static IIO_CONST_ATTR(in_illuminance_scale_available, "125 2000");
>
> #define ISL29028_CONST_ATTR(name) (&iio_const_attr_##name.dev_attr.attr)
> @@ -571,7 +600,8 @@ static int isl29028_probe(struct i2c_client *client,
> }
>
> chip->enable_prox = false;
> - chip->prox_sampling = 20;
> + chip->prox_sampling_int = 20;
> + chip->prox_sampling_frac = 0;
> chip->lux_scale = 2000;
>
> ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
>