On Mon Jan 13, 2025 at 8:52 PM CET, Matti Vaittinen wrote: > ma 13.1.2025 klo 17.05 Javier Carrasco > (javier.carrasco.cruz@xxxxxxxxx) kirjoitti: > > > > On Mon Jan 13, 2025 at 12:56 PM CET, Matti Vaittinen wrote: > > > On 07/01/2025 22:50, Javier Carrasco wrote: > > > > The current scale is not ABI-compliant as it is just the sensor gain > > > > instead of the value that acts as a multiplier to be applied to the raw > > > > value (there is no offset). > > > > > > > > Use the iio-gts helpers to obtain the proper scale values according to > > > > the gain and integration time to match the resolution tables from the > > > > datasheet and drop dedicated variables to store the current values of > > > > the integration time, gain and resolution. When at it, use 'scale' > > > > instead of 'gain' consistently for the get/set functions to avoid > > > > misunderstandings. > > > > > > > > Fixes: 7b779f573c48 ("iio: light: add driver for veml6030 ambient light sensor") > > > > Signed-off-by: Javier Carrasco <javier.carrasco.cruz@xxxxxxxxx> > > > > > > Thanks for the patch Javier. > > > > > > And, sorry for a review which is more about questions than suggested > > > improvements. I find it hard to focus on reading code today. > > > > > > > --- > > > > drivers/iio/light/Kconfig | 1 + > > > > drivers/iio/light/veml6030.c | 499 ++++++++++++++++--------------------------- > > > > 2 files changed, 189 insertions(+), 311 deletions(-) > > > > > > > > > > I like the diffstats of this Fix! :) It's nice you found gts-helpers > > > helpful :) > > > > I wonder how painful the int. time/gain/scale issue in ALS was before > > iio-gts existed :D > > > I don't really know. I wrote the gts-helpers as soon as I wrote my > first light sensor driver :) > > > > ... > > > > > > > + > > > > +static int veml6030_process_als(struct veml6030_data *data, int raw, > > > > + int *val, int *val2) > > > > +{ > > > > + int ret, scale_int, scale_nano; > > > > + u64 tmp; > > > > + > > > > + ret = veml6030_get_scale(data, &scale_int, &scale_nano); > > > > + if (ret < 0) > > > > + return ret; > > > > + > > > > + tmp = (u64)raw * scale_nano; > > > > + *val = raw * scale_int + div_u64(tmp, NANO); > > > > + *val2 = div_u64(do_div(tmp, NANO), MILLI); > > > > > > do_div() is horrible on some platforms. Or, at least it used to be. Is > > > there really no way to go without it? We're dealing with 16bit data and > > > maximum of 512x total gain only, so maybe there was a way(?) > > > > > > Maybe a stupid question (in which case I blame mucus in my head) - could > > > you just divide the raw value by the total gain? > > > > > > > In its current form we need the 64-bit operations to handle the scale, > > and it will probably have to stay like that for the reasons I give you > > below. > > Still, I wonder if multiplying by scale really differs from dividing > by the total gain? I think the scale is inversely proportional to the > total gain, right? > I am sorry, but I am not sure if I got your point here. The scale is the multiplier to get lux from raw, and for example it's not just 1/512 for the maximum total gain, as that is not taking the intrinsic resolution of the sensor. Maybe I am misunderstanding something, but I don't see the way around raw * scale with the scale being one of the discrete values provided in the application note. I will give you a simple example, so you can tell me where my reasoning fails: raw = 100 counts scale = 2.1504 lux/count (when IT=25ms and GAIN=1/8) processed = 215.04 lux (raw * scale, ABI compliant for IIO_LIGHT) The reply to your comment below explains why we have a PROCESSED IIO_LIGHT in the first place. > > > > static irqreturn_t veml6030_event_handler(int irq, void *private) > > > > @@ -1084,6 +968,13 @@ static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev) > > > > int ret, val; > > > > struct veml6030_data *data = iio_priv(indio_dev); > > > > > > > > + ret = devm_iio_init_iio_gts(dev, 2, 150400000, > > > > > > Can you please explain the seemingly odd choice for the max scale? > > > > > > Just a quick look at the sensor spec and this driver allows me to assume > > > following: > > > > > > Maximum 'total gain' from both HWGAIN and integration time is 16 * 32 = 512. > > > > > > If we chose the 'total gain' 1x to match scale 1, then the smallest > > > scale would be 1/512 = 0.001 953 125 > > > > > > This is 1953125 NANOs. This would mean the max-scale 1X => gain 1X would > > > not cause precision loss. (Well, I'm not at my sharpest as I've caught > > > cold - but I _think_ this is true, right?) > > > > > > If I read this correctly, the only channel where the scale gets applied > > > is the INTENSITY channel, right? Hence it should be possible to chose > > > the scale as we see best. (Unless the idea of this seemingly odd scale > > > is to maintain the old intensity / scale values in order to not shake > > > userland any more - in which case this could be mentioned). > > > > > > > The scale is applied to an IIO_LIGHT channel, not to the INTENSITY, > > Isn't the IIO_LIGHT channel a PROCESSED one? I thought the scale > shouldn't be applied to it. (Driver may still apply scale internally, > but users should not see it, right? And if the driver does it only > internally, then the driver can also multiply values using (N * > scale). Well, I suppose you can as well use this "fitted MAX SCALE" - > but maybe it warrants a comment. IIO_LIGHT provides RAW and PROCESSED values, which shouldn't have happened in the first place as PROCESSED is just raw * scale, if scale had been right from the beginning. Actually, when I took over this driver, I was tempted to drop the PROCESSED value, but it was too late for that without breaking ABI. My guess is that the processed value was provided because in_illuminance_scale was not the right multiplier, only the gain. Note that in_illuminance_scale is also provided to the user, and that must comply with the ABI definitions. Thank you again, Javier Carrasco