Re: [PATCH] iio: bmg160: add callbacks for the filter frequency

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

 



On 01/05/16 21:02, Jonathan Cameron wrote:
> On 26/04/16 22:36, Srinivas Pandruvada wrote:
>> On Tue, 2016-04-26 at 22:15 +0100, Jonathan Cameron wrote:
>>>
>>> On 26 April 2016 21:25:22 BST, Srinivas Pandruvada <srinivas.pandruva
>>> da@xxxxxxxxxxxxxxx> wrote:
>>>>
>>>> On Mon, 2016-04-25 at 20:31 +0100, Jonathan Cameron wrote:
>>>>>
>>>>> On 21/04/16 11:49, Steffen Trumtrar wrote:
>>>>>>
>>>>>>
>>>>>> The filter frequency and sample rate have a fixed relationship.
>>>>>> Only the filter frequency is unique, however.
>>>>>> Currently the driver ignores the filter settings for 32 Hz and
>>>>>> 64 Hz.
>>>>>>
>>>>>> This patch adds the necessary callbacks to be able to configure
>>>>>> and read the filter setting from sysfs.
>>>>>>
>>>>>> Signed-off-by: Steffen Trumtrar <s.trumtrar@xxxxxxxxxxxxxx>
>>>>> cc'd Srinivas as it's his driver...  Looks superficially fine to
>>>>> me.
>>>>>
>>>>> Jonathan
>>>>>>
>>>>>>
>>>>>> ---
>>>>>>
>>>>>> Changing the sample rate will result in using the first match
>>>>>> and therefore selecting the filter accordingly. Is this a
>>>>>> misuse
>>>>>> of the ABI and should be handled differently or is this okay?
>>>>>>
>>>> This is the reason they were omitted. Now you can't uniquely set
>>>> 100Hz
>>>> sampling frequency. Depending on filter it will have different
>>>> results.
>>>>
>>>> I think this needs some ABI level changes, where you display
>>>> available
>>>> and allow to specify both ODR and Filter to uniquely select.
>>> Unfortunately the moment the ABI allows for combined elements it
>>> becomes a
>>>  nightmare for complexity. In some devices a single parameter change
>>> can
>>>  change everything else. There are no simple rules unfortunately. 
>>>
>>> The way we avoid this being a problem is that we very deliberately
>>> allow any ABI element
>>> to be able to result in a change in any other.  This includes
>>> changing the
>>>  available values list as here. It might be slightly nicer to jump to
>>> the nearest
>>>  available option though.
>>>
>>> An alternative would be to have an interface to fake such changes
>>> then
>>> apply them atomically if possible. 
>>> That level of complexity just does seem warranted here and would
>>> still need userspace to check valid ranges as it
>>>  pretends to change the state. Hence no real gain....
>>>
>> I think we should add some documentation for this driver about this.
>> They should rather change filer rather than sampling freq to have
>> unique setting.
> whilst that would get around the problem, people are going to be expecting
> to have explicit control of sampling frequency if they see it is variable for
> the part...
> 
> Tricky unfortunately.
So Srinivas, I'm in favour of the patch as it stands.  Have I convinced you?

Jonathan
> 
> Jonathan
>>
>> Thanks,
>> Srinivas
>>
>>> Jonathan
>>>>
>>>>
>>>> Thanks,
>>>> Srinivas
>>>>
>>>>
>>>>>
>>>>>>
>>>>>>  drivers/iio/gyro/bmg160_core.c | 105
>>>>>> ++++++++++++++++++++++++++++++++++++-----
>>>>>>  1 file changed, 93 insertions(+), 12 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/iio/gyro/bmg160_core.c
>>>>>> b/drivers/iio/gyro/bmg160_core.c
>>>>>> index bbce3b09ac45..ea0243eb393a 100644
>>>>>> --- a/drivers/iio/gyro/bmg160_core.c
>>>>>> +++ b/drivers/iio/gyro/bmg160_core.c
>>>>>> @@ -52,6 +52,7 @@
>>>>>>  #define BMG160_REG_PMU_BW		0x10
>>>>>>  #define BMG160_NO_FILTER		0
>>>>>>  #define BMG160_DEF_BW			100
>>>>>> +#define BMG160_REG_PMU_BW_RES		BIT(7)
>>>>>>  
>>>>>>  #define BMG160_REG_INT_MAP_0		0x17
>>>>>>  #define BMG160_INT_MAP_0_BIT_ANY	BIT(1)
>>>>>> @@ -103,7 +104,6 @@ struct bmg160_data {
>>>>>>  	struct iio_trigger *motion_trig;
>>>>>>  	struct mutex mutex;
>>>>>>  	s16 buffer[8];
>>>>>> -	u8 bw_bits;
>>>>>>  	u32 dps_range;
>>>>>>  	int ev_enable_state;
>>>>>>  	int slope_thres;
>>>>>> @@ -119,13 +119,16 @@ enum bmg160_axis {
>>>>>>  };
>>>>>>  
>>>>>>  static const struct {
>>>>>> -	int val;
>>>>>> +	int odr;
>>>>>> +	int filter;
>>>>>>  	int bw_bits;
>>>>>> -} bmg160_samp_freq_table[] = { {100, 0x07},
>>>>>> -			       {200, 0x06},
>>>>>> -			       {400, 0x03},
>>>>>> -			       {1000, 0x02},
>>>>>> -			       {2000, 0x01} };
>>>>>> +} bmg160_samp_freq_table[] = { {100, 32, 0x07},
>>>>>> +			       {200, 64, 0x06},
>>>>>> +			       {100, 12, 0x05},
>>>>>> +			       {200, 23, 0x04},
>>>>>> +			       {400, 47, 0x03},
>>>>>> +			       {1000, 116, 0x02},
>>>>>> +			       {2000, 230, 0x01} };
>>>>>>  
>>>>>>  static const struct {
>>>>>>  	int scale;
>>>>>> @@ -154,7 +157,7 @@ static int bmg160_convert_freq_to_bit(int
>>>>>> val)
>>>>>>  	int i;
>>>>>>  
>>>>>>  	for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table);
>>>>>> ++i) {
>>>>>> -		if (bmg160_samp_freq_table[i].val == val)
>>>>>> +		if (bmg160_samp_freq_table[i].odr == val)
>>>>>>  			return
>>>>>> bmg160_samp_freq_table[i].bw_bits;
>>>>>>  	}
>>>>>>  
>>>>>> @@ -176,7 +179,51 @@ static int bmg160_set_bw(struct
>>>>>> bmg160_data
>>>>>> *data, int val)
>>>>>>  		return ret;
>>>>>>  	}
>>>>>>  
>>>>>> -	data->bw_bits = bw_bits;
>>>>>> +	return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int bmg160_get_filter(struct bmg160_data *data, int
>>>>>> *val)
>>>>>> +{
>>>>>> +	int ret;
>>>>>> +	int i;
>>>>>> +	unsigned int bw_bits;
>>>>>> +
>>>>>> +	ret = regmap_read(data->regmap, BMG160_REG_PMU_BW,
>>>>>> &bw_bits);
>>>>>> +	if (ret < 0) {
>>>>>> +		dev_err(data->dev, "Error reading
>>>>>> reg_pmu_bw\n");
>>>>>> +		return ret;
>>>>>> +	}
>>>>>> +
>>>>>> +	/* Ignore the readonly reserved bit. */
>>>>>> +	bw_bits &= ~BMG160_REG_PMU_BW_RES;
>>>>>> +
>>>>>> +	for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table);
>>>>>> ++i) {
>>>>>> +		if (bmg160_samp_freq_table[i].bw_bits ==
>>>>>> bw_bits)
>>>>>> +			break;
>>>>>> +	}
>>>>>> +
>>>>>> +	*val = bmg160_samp_freq_table[i].filter;
>>>>>> +
>>>>>> +	return ret ? ret : IIO_VAL_INT;
>>>>>> +}
>>>>>> +
>>>>>> +
>>>>>> +static int bmg160_set_filter(struct bmg160_data *data, int
>>>>>> val)
>>>>>> +{
>>>>>> +	int ret;
>>>>>> +	int i;
>>>>>> +
>>>>>> +	for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table);
>>>>>> ++i) {
>>>>>> +		if (bmg160_samp_freq_table[i].filter == val)
>>>>>> +			break;
>>>>>> +	}
>>>>>> +
>>>>>> +	ret = regmap_write(data->regmap, BMG160_REG_PMU_BW,
>>>>>> +			   bmg160_samp_freq_table[i].bw_bits);
>>>>>> +	if (ret < 0) {
>>>>>> +		dev_err(data->dev, "Error writing
>>>>>> reg_pmu_bw\n");
>>>>>> +		return ret;
>>>>>> +	}
>>>>>>  
>>>>>>  	return 0;
>>>>>>  }
>>>>>> @@ -388,10 +435,21 @@ static int
>>>>>> bmg160_setup_new_data_interrupt(struct bmg160_data *data,
>>>>>>  static int bmg160_get_bw(struct bmg160_data *data, int *val)
>>>>>>  {
>>>>>>  	int i;
>>>>>> +	unsigned int bw_bits;
>>>>>> +	int ret;
>>>>>> +
>>>>>> +	ret = regmap_read(data->regmap, BMG160_REG_PMU_BW,
>>>>>> &bw_bits);
>>>>>> +	if (ret < 0) {
>>>>>> +		dev_err(data->dev, "Error reading
>>>>>> reg_pmu_bw\n");
>>>>>> +		return ret;
>>>>>> +	}
>>>>>> +
>>>>>> +	/* Ignore the readonly reserved bit. */
>>>>>> +	bw_bits &= ~BMG160_REG_PMU_BW_RES;
>>>>>>  
>>>>>>  	for (i = 0; i < ARRAY_SIZE(bmg160_samp_freq_table);
>>>>>> ++i) {
>>>>>> -		if (bmg160_samp_freq_table[i].bw_bits == data-
>>>>>>>
>>>>>>> bw_bits) {
>>>>>> -			*val = bmg160_samp_freq_table[i].val;
>>>>>> +		if (bmg160_samp_freq_table[i].bw_bits ==
>>>>>> bw_bits)
>>>>>> {
>>>>>> +			*val = bmg160_samp_freq_table[i].odr;
>>>>>>  			return IIO_VAL_INT;
>>>>>>  		}
>>>>>>  	}
>>>>>> @@ -506,6 +564,8 @@ static int bmg160_read_raw(struct iio_dev
>>>>>> *indio_dev,
>>>>>>  			return IIO_VAL_INT;
>>>>>>  		} else
>>>>>>  			return -EINVAL;
>>>>>> +	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
>>>>>> +		return bmg160_get_filter(data, val);
>>>>>>  	case IIO_CHAN_INFO_SCALE:
>>>>>>  		*val = 0;
>>>>>>  		switch (chan->type) {
>>>>>> @@ -570,6 +630,26 @@ static int bmg160_write_raw(struct iio_dev
>>>>>> *indio_dev,
>>>>>>  		ret = bmg160_set_power_state(data, false);
>>>>>>  		mutex_unlock(&data->mutex);
>>>>>>  		return ret;
>>>>>> +	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
>>>>>> +		if (val2)
>>>>>> +			return -EINVAL;
>>>>>> +
>>>>>> +		mutex_lock(&data->mutex);
>>>>>> +		ret = bmg160_set_power_state(data, true);
>>>>>> +		if (ret < 0) {
>>>>>> +			bmg160_set_power_state(data, false);
>>>>>> +			mutex_unlock(&data->mutex);
>>>>>> +			return ret;
>>>>>> +		}
>>>>>> +		ret = bmg160_set_filter(data, val);
>>>>>> +		if (ret < 0) {
>>>>>> +			bmg160_set_power_state(data, false);
>>>>>> +			mutex_unlock(&data->mutex);
>>>>>> +			return ret;
>>>>>> +		}
>>>>>> +		ret = bmg160_set_power_state(data, false);
>>>>>> +		mutex_unlock(&data->mutex);
>>>>>> +		return ret;
>>>>>>  	case IIO_CHAN_INFO_SCALE:
>>>>>>  		if (val)
>>>>>>  			return -EINVAL;
>>>>>> @@ -727,7 +807,8 @@ static const struct iio_event_spec
>>>>>> bmg160_event
>>>>>> = {
>>>>>>  	.channel2 = IIO_MOD_##_axis,				
>>>>>> 	\
>>>>>>  	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		
>>>>>> 	\
>>>>>>  	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
>>>>>> 	
>>>>>> 	\
>>>>>> -				    BIT(IIO_CHAN_INFO_SAMP_FRE
>>>>>> Q),	
>>>>>> \
>>>>>> +		BIT(IIO_CHAN_INFO_SAMP_FREQ) |			
>>>>>> 	\
>>>>>> +		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENC
>>>>>> Y),	
>>>>>> \
>>>>>>  	.scan_index = AXIS_##_axis,				
>>>>>> 	\
>>>>>>  	.scan_type = {						
>>>>>> 	\
>>>>>>  		.sign = 's',					
>>>>>> 	\
>>>>>>
> 
> --
> 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