Re: [PATCH 2/2] iio: light: veml6030: fix scale to conform to ABI

From: Matti Vaittinen
Date: Mon Jan 13 2025 - 06:56:38 EST


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 :)

...

+
+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?

+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+

...

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).

+ veml6030_gain_sel, ARRAY_SIZE(veml6030_gain_sel),
+ veml6030_it_sel, ARRAY_SIZE(veml6030_it_sel),
+ &data->gts);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init iio gts\n");
+
ret = veml6030_als_shut_down(data);
if (ret)
return dev_err_probe(dev, ret, "can't shutdown als\n");
@@ -1119,11 +1010,6 @@ static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev)
return dev_err_probe(dev, ret,
"can't clear als interrupt status\n");
- /* Cache currently active measurement parameters */
- data->cur_gain = 3;
- data->cur_resolution = 5376;
- data->cur_integration_time = 3;
-
return ret;
}

Yours,
-- Matti