diff mbox series

[v4,05/10] iio: afe: rescale: add INT_PLUS_{MICRO,NANO} support

Message ID 20210706160942.3181474-6-liambeguin@gmail.com
State New
Headers show
Series iio: afe: add temperature rescaling support | expand

Commit Message

Liam Beguin July 6, 2021, 4:09 p.m. UTC
From: Liam Beguin <lvb@xiphos.com>

Add IIO_VAL_INT_PLUS_{NANO,MICRO} scaling support.
Scale the integer part and the decimal parts individually and keep the
original scaling type.

Signed-off-by: Liam Beguin <lvb@xiphos.com>
---
 drivers/iio/afe/iio-rescale.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Peter Rosin July 9, 2021, 4:29 p.m. UTC | #1
On 2021-07-06 18:09, Liam Beguin wrote:
> From: Liam Beguin <lvb@xiphos.com>

> 

> Add IIO_VAL_INT_PLUS_{NANO,MICRO} scaling support.

> Scale the integer part and the decimal parts individually and keep the

> original scaling type.

> 

> Signed-off-by: Liam Beguin <lvb@xiphos.com>

> ---

>  drivers/iio/afe/iio-rescale.c | 8 ++++++++

>  1 file changed, 8 insertions(+)

> 

> diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c

> index ba3bdcc69b16..1d0e24145d87 100644

> --- a/drivers/iio/afe/iio-rescale.c

> +++ b/drivers/iio/afe/iio-rescale.c

> @@ -89,7 +89,15 @@ static int rescale_read_raw(struct iio_dev *indio_dev,

>  			do_div(tmp, 1000000000LL);

>  			*val = tmp;

>  			return ret;

> +		case IIO_VAL_INT_PLUS_NANO:

> +		case IIO_VAL_INT_PLUS_MICRO:

> +			tmp = (s64)*val * rescale->numerator;

> +			*val = div_s64(tmp, rescale->denominator);

> +			tmp = (s64)*val2 * rescale->numerator;

> +			*val2 = div_s64(tmp, rescale->denominator);


Hi!

You are losing precision, and you are not mormalising after the calculation.
I think it's better to not even attempt this given that the results can be
really poor.

Cheers,
Peter

> +			return ret;

>  		default:

> +			dev_err(&indio_dev->dev, "unsupported type %d\n", ret);

>  			return -EOPNOTSUPP;

>  		}

>  	default:

>
Liam Beguin July 9, 2021, 7:30 p.m. UTC | #2
On Fri Jul 9, 2021 at 12:29 PM EDT, Peter Rosin wrote:
>

>

> On 2021-07-06 18:09, Liam Beguin wrote:

> > From: Liam Beguin <lvb@xiphos.com>

> > 

> > Add IIO_VAL_INT_PLUS_{NANO,MICRO} scaling support.

> > Scale the integer part and the decimal parts individually and keep the

> > original scaling type.

> > 

> > Signed-off-by: Liam Beguin <lvb@xiphos.com>

> > ---

> >  drivers/iio/afe/iio-rescale.c | 8 ++++++++

> >  1 file changed, 8 insertions(+)

> > 

> > diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c

> > index ba3bdcc69b16..1d0e24145d87 100644

> > --- a/drivers/iio/afe/iio-rescale.c

> > +++ b/drivers/iio/afe/iio-rescale.c

> > @@ -89,7 +89,15 @@ static int rescale_read_raw(struct iio_dev *indio_dev,

> >  			do_div(tmp, 1000000000LL);

> >  			*val = tmp;

> >  			return ret;

> > +		case IIO_VAL_INT_PLUS_NANO:

> > +		case IIO_VAL_INT_PLUS_MICRO:

> > +			tmp = (s64)*val * rescale->numerator;

> > +			*val = div_s64(tmp, rescale->denominator);

> > +			tmp = (s64)*val2 * rescale->numerator;

> > +			*val2 = div_s64(tmp, rescale->denominator);

>


Hi Peter,

> Hi!

>

> You are losing precision, and you are not mormalising after the

> calculation.


Can you elaborate a little on what you mean here?

Do you mean that I should make sure that *val2, the PLUS_{NANO,MICRO}
part, doesn't contain an integer part? And if so transfer that part back
to *val?

> I think it's better to not even attempt this given that the results can

> be

> really poor.


Unfortunatelly, I'm kinda stuck with this as some of my ADC use these
types.

Thanks,
Liam

>

> Cheers,

> Peter

>

> > +			return ret;

> >  		default:

> > +			dev_err(&indio_dev->dev, "unsupported type %d\n", ret);

> >  			return -EOPNOTSUPP;

> >  		}

> >  	default:

> >
Peter Rosin July 10, 2021, 8:14 a.m. UTC | #3
On 2021-07-09 21:30, Liam Beguin wrote:
> On Fri Jul 9, 2021 at 12:29 PM EDT, Peter Rosin wrote:

>>

>>

>> On 2021-07-06 18:09, Liam Beguin wrote:

>>> From: Liam Beguin <lvb@xiphos.com>

>>>

>>> Add IIO_VAL_INT_PLUS_{NANO,MICRO} scaling support.

>>> Scale the integer part and the decimal parts individually and keep the

>>> original scaling type.

>>>

>>> Signed-off-by: Liam Beguin <lvb@xiphos.com>

>>> ---

>>>  drivers/iio/afe/iio-rescale.c | 8 ++++++++

>>>  1 file changed, 8 insertions(+)

>>>

>>> diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c

>>> index ba3bdcc69b16..1d0e24145d87 100644

>>> --- a/drivers/iio/afe/iio-rescale.c

>>> +++ b/drivers/iio/afe/iio-rescale.c

>>> @@ -89,7 +89,15 @@ static int rescale_read_raw(struct iio_dev *indio_dev,

>>>  			do_div(tmp, 1000000000LL);

>>>  			*val = tmp;

>>>  			return ret;

>>> +		case IIO_VAL_INT_PLUS_NANO:

>>> +		case IIO_VAL_INT_PLUS_MICRO:

>>> +			tmp = (s64)*val * rescale->numerator;

>>> +			*val = div_s64(tmp, rescale->denominator);

>>> +			tmp = (s64)*val2 * rescale->numerator;

>>> +			*val2 = div_s64(tmp, rescale->denominator);

>>

> 

> Hi Peter,

> 

>> Hi!

>>

>> You are losing precision, and you are not mormalising after the

>> calculation.

> 

> Can you elaborate a little on what you mean here?

> 

> Do you mean that I should make sure that *val2, the PLUS_{NANO,MICRO}

> part, doesn't contain an integer part? And if so transfer that part back

> to *val?


Yes. On 32-bit, you will easily wrap, especially for PLUS_NANO. You'd
only need a scale factor of 10 or so and a fractional part above .5 to
hit the roof (10 * 500000000 > 2^32).

But I also mean that you are losing precision when you are scaling
the integer part and the fractional part separately. That deserves
at least a comment, but ideally it should be handled correctly.

>> I think it's better to not even attempt this given that the results can

>> be

>> really poor.

> 

> Unfortunatelly, I'm kinda stuck with this as some of my ADC use these

> types.


Ok. Crap. :-)

Cheers,
Peter
Liam Beguin July 10, 2021, 5:45 p.m. UTC | #4
On Sat Jul 10, 2021 at 4:14 AM EDT, Peter Rosin wrote:
>

>

> On 2021-07-09 21:30, Liam Beguin wrote:

> > On Fri Jul 9, 2021 at 12:29 PM EDT, Peter Rosin wrote:

> >>

> >>

> >> On 2021-07-06 18:09, Liam Beguin wrote:

> >>> From: Liam Beguin <lvb@xiphos.com>

> >>>

> >>> Add IIO_VAL_INT_PLUS_{NANO,MICRO} scaling support.

> >>> Scale the integer part and the decimal parts individually and keep the

> >>> original scaling type.

> >>>

> >>> Signed-off-by: Liam Beguin <lvb@xiphos.com>

> >>> ---

> >>>  drivers/iio/afe/iio-rescale.c | 8 ++++++++

> >>>  1 file changed, 8 insertions(+)

> >>>

> >>> diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c

> >>> index ba3bdcc69b16..1d0e24145d87 100644

> >>> --- a/drivers/iio/afe/iio-rescale.c

> >>> +++ b/drivers/iio/afe/iio-rescale.c

> >>> @@ -89,7 +89,15 @@ static int rescale_read_raw(struct iio_dev *indio_dev,

> >>>  			do_div(tmp, 1000000000LL);

> >>>  			*val = tmp;

> >>>  			return ret;

> >>> +		case IIO_VAL_INT_PLUS_NANO:

> >>> +		case IIO_VAL_INT_PLUS_MICRO:

> >>> +			tmp = (s64)*val * rescale->numerator;

> >>> +			*val = div_s64(tmp, rescale->denominator);

> >>> +			tmp = (s64)*val2 * rescale->numerator;

> >>> +			*val2 = div_s64(tmp, rescale->denominator);

> >>

> > 

> > Hi Peter,

> > 

> >> Hi!

> >>

> >> You are losing precision, and you are not mormalising after the

> >> calculation.

> > 

> > Can you elaborate a little on what you mean here?

> > 

> > Do you mean that I should make sure that *val2, the PLUS_{NANO,MICRO}

> > part, doesn't contain an integer part? And if so transfer that part back

> > to *val?


Hi Peter,

>

> Yes. On 32-bit, you will easily wrap, especially for PLUS_NANO. You'd

> only need a scale factor of 10 or so and a fractional part above .5 to

> hit the roof (10 * 500000000 > 2^32).

>


Right, That makes sense!

> But I also mean that you are losing precision when you are scaling

> the integer part and the fractional part separately. That deserves

> at least a comment, but ideally it should be handled correctly.

>


Oh got it! Apologies, How did I miss that...

All things considered, it might make sense to also implement the
test case Jonathan mentioned [1]. I'll look into it.

[1] https://lore.kernel.org/linux-devicetree/20210704173639.622371bf@jic23-huawei/

> >> I think it's better to not even attempt this given that the results can

> >> be

> >> really poor.

> > 

> > Unfortunatelly, I'm kinda stuck with this as some of my ADC use these

> > types.

>

> Ok. Crap. :-)


Can't agree more :-)

Thanks,
Liam

>

> Cheers,

> Peter
diff mbox series

Patch

diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index ba3bdcc69b16..1d0e24145d87 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -89,7 +89,15 @@  static int rescale_read_raw(struct iio_dev *indio_dev,
 			do_div(tmp, 1000000000LL);
 			*val = tmp;
 			return ret;
+		case IIO_VAL_INT_PLUS_NANO:
+		case IIO_VAL_INT_PLUS_MICRO:
+			tmp = (s64)*val * rescale->numerator;
+			*val = div_s64(tmp, rescale->denominator);
+			tmp = (s64)*val2 * rescale->numerator;
+			*val2 = div_s64(tmp, rescale->denominator);
+			return ret;
 		default:
+			dev_err(&indio_dev->dev, "unsupported type %d\n", ret);
 			return -EOPNOTSUPP;
 		}
 	default: