Re: [PATCH v4 2/5] iio: ltr501: Add integration time support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jonathan,

> On 18/04/15 06:15, Kuppuswamy Sathyanarayanan wrote:
>> Added support to modify and read ALS integration time.
>>
>> Signed-off-by: Kuppuswamy Sathyanarayanan
>> <sathyanarayanan.kuppuswamy@xxxxxxxxxxxxxxx>
>
> Cool, didn't know about this regmap field stuff before.  Not exactly
> heavily
> used but looks helpful!
yes. It simplifies the bit wise manipulations and makes it more readable.
Avoids use of masks and logical operations.
>
> A few questions inline..
>
> 1) A spot where a variable name change would make it easier to follow.
Fixed it in next set.
> 2) Why are the struct reg_field not defined as const in the regmap_field
> allocators?  Here it gives the impression we are restricting ourselves to
> one instance of this chip, but in reality they seem to actually be const
> so we aren't.
There are few use cases in kernel where they allocate the reg_map fields
in an array. In these cases same reg_field can be used with few index
manipulations. Add const to allocators would restrict users in doing that.
>
> messy :(
>
>> ---
>>  drivers/iio/light/ltr501.c | 87
>> +++++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 86 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
>> index 84ee2b3..22769c8 100644
>> --- a/drivers/iio/light/ltr501.c
>> +++ b/drivers/iio/light/ltr501.c
>> @@ -28,6 +28,7 @@
>>
>>  #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */
>>  #define LTR501_PS_CONTR 0x81 /* PS operation mode */
>> +#define LTR501_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/
>>  #define LTR501_PART_ID 0x86
>>  #define LTR501_MANUFAC_ID 0x87
>>  #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */
>> @@ -49,11 +50,16 @@
>>
>>  #define LTR501_REGMAP_NAME "ltr501_regmap"
>>
>> +static int int_time_mapping[] = {100000, 50000, 200000, 400000};
>> +
>> +static struct reg_field reg_it = REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4);
> Naming could be clearer.  The reg_it here and the regmap_field below
> are different structures, but their name doesn't make this clear.
Fixed it in next set.
>
> Also, why is the above not const?  Obviously regmap doesn't take a const
> but I can't see why not... Mark?
I agree. Fixed it in next set.
>
> It is only used to initialize elements (by copying) in the regmap_field
> that allocator of which it is passed to.
>> +
>>  struct ltr501_data {
>>  	struct i2c_client *client;
>>  	struct mutex lock_als, lock_ps;
>>  	u8 als_contr, ps_contr;
>>  	struct regmap *regmap;
>> +	struct regmap_field *reg_it;
>>  };
>>
>>  static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask)
>> @@ -74,6 +80,58 @@ static int ltr501_drdy(struct ltr501_data *data, u8
>> drdy_mask)
>>  	return -EIO;
>>  }
>>
>> +static int ltr501_set_it_time(struct ltr501_data *data, int it)
>> +{
>> +	int ret, i, index = -1, status;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(int_time_mapping); i++) {
>> +		if (int_time_mapping[i] == it) {
>> +			index = i;
>> +			break;
>> +		}
>> +	}
>> +	/* Make sure integ time index is valid */
>> +	if (index < 0)
>> +		return -EINVAL;
>> +
>> +	ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	if (status & LTR501_CONTR_ALS_GAIN_MASK) {
>> +		/*
>> +		 * 200 ms and 400 ms integ time can only be
>> +		 * used in dynamic range 1
>> +		 */
>> +		if (index > 1)
>> +			return -EINVAL;
>> +	} else
>> +		/* 50 ms integ time can only be used in dynamic range 2 */
>> +		if (index == 1)
>> +			return -EINVAL;
>> +
>> +	return regmap_field_write(data->reg_it, index);
>> +}
>> +
>> +/* read int time in micro seconds */
>> +static int ltr501_read_it_time(struct ltr501_data *data, int *val, int
>> *val2)
>> +{
>> +	int ret, index;
>> +
>> +	ret = regmap_field_read(data->reg_it, &index);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* Make sure integ time index is valid */
>> +	if (index < 0 || index >= ARRAY_SIZE(int_time_mapping))
>> +		return -EINVAL;
>> +
>> +	*val2 = int_time_mapping[index];
>> +	*val = 0;
>> +
>> +	return IIO_VAL_INT_PLUS_MICRO;
>> +}
>> +
>>  static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2])
>>  {
>>  	int ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY);
>> @@ -119,7 +177,7 @@ static int ltr501_read_ps(struct ltr501_data *data)
>>  static const struct iio_chan_spec ltr501_channels[] = {
>>  	LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0),
>>  	LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR,
>> -		BIT(IIO_CHAN_INFO_SCALE)),
>> +		BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_INT_TIME)),
>>  	{
>>  		.type = IIO_PROXIMITY,
>>  		.address = LTR501_PS_DATA,
>> @@ -195,6 +253,13 @@ static int ltr501_read_raw(struct iio_dev
>> *indio_dev,
>>  		default:
>>  			return -EINVAL;
>>  		}
>> +	case IIO_CHAN_INFO_INT_TIME:
>> +		switch (chan->type) {
>> +		case IIO_INTENSITY:
>> +			return ltr501_read_it_time(data, val, val2);
>> +		default:
>> +			return -EINVAL;
>> +		}
>>  	}
>>  	return -EINVAL;
>>  }
>> @@ -245,16 +310,30 @@ static int ltr501_write_raw(struct iio_dev
>> *indio_dev,
>>  		default:
>>  			return -EINVAL;
>>  		}
>> +	case IIO_CHAN_INFO_INT_TIME:
>> +		switch (chan->type) {
>> +		case IIO_INTENSITY:
>> +			if (val != 0)
>> +				return -EINVAL;
>> +			mutex_lock(&data->lock_als);
>> +			i = ltr501_set_it_time(data, val2);
>> +			mutex_unlock(&data->lock_als);
>> +			return i;
>> +		default:
>> +			return -EINVAL;
>> +		}
>>  	}
>>  	return -EINVAL;
>>  }
>>
>>  static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125
>> 0.0625");
>>  static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005");
>> +static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4");
>>
>>  static struct attribute *ltr501_attributes[] = {
>>  	&iio_const_attr_in_proximity_scale_available.dev_attr.attr,
>>  	&iio_const_attr_in_intensity_scale_available.dev_attr.attr,
>> +	&iio_const_attr_integration_time_available.dev_attr.attr,
>>  	NULL
>>  };
>>
>> @@ -396,6 +475,12 @@ static int ltr501_probe(struct i2c_client *client,
>>  	mutex_init(&data->lock_als);
>>  	mutex_init(&data->lock_ps);
>>
>> +	data->reg_it = devm_regmap_field_alloc(&client->dev, regmap, reg_it);
>> +	if (IS_ERR(data->reg_it)) {
>> +		dev_err(&client->dev, "Integ time reg field init failed.\n");
>> +		return PTR_ERR(data->reg_it);
>> +	}
>> +
>>  	ret = regmap_read(data->regmap, LTR501_PART_ID, &partid);
>>  	if (ret < 0)
>>  		return ret;
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux