[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4a45f777-9491-23d3-f7ed-924315c4680b@gmail.com>
Date: Mon, 13 Mar 2023 15:34:31 +0200
From: Matti Vaittinen <mazziesaccount@...il.com>
To: Jonathan Cameron <jic23@...nel.org>
Cc: Matti Vaittinen <matti.vaittinen@...rohmeurope.com>,
Lars-Peter Clausen <lars@...afoo.de>,
Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
Dmitry Osipenko <dmitry.osipenko@...labora.com>,
Paul Gazzillo <paul@...zz.com>,
Shreeya Patel <shreeya.patel@...labora.com>,
Zhigang Shi <Zhigang.Shi@...eon.com>,
linux-kernel@...r.kernel.org, linux-iio@...r.kernel.org
Subject: Re: [PATCH v3 5/6] iio: light: ROHM BU27034 Ambient Light Sensor
On 3/12/23 19:39, Jonathan Cameron wrote:
> On Mon, 6 Mar 2023 11:23:50 +0200
> Matti Vaittinen <mazziesaccount@...il.com> wrote:
>
>> ROHM BU27034 is an ambient light sensor with 3 channels and 3 photo diodes
>> capable of detecting a very wide range of illuminance. Typical application
>> is adjusting LCD and backlight power of TVs and mobile phones.
>>
>> Add initial support for the ROHM BU27034 ambient light sensor.
>>
>> NOTE:
>> - Driver exposes 4 channels. One IIO_LIGHT channel providing the
>> calculated lux values based on measured data from diodes #0 and
>> #1. In addition, 3 IIO_INTENSITY channels are emitting the raw
>> register data from all diodes for more intense user-space
>> computations.
>> - Sensor has GAIN values that can be adjusted from 1x to 4096x.
>> - Sensor has adjustible measurement times of 5, 55, 100, 200 and
>> 400 mS. Driver does not support 5 mS which has special
>> limitations.
>> - Driver exposes standard 'scale' adjustment which is
>> implemented by:
>> 1) Trying to adjust only the GAIN
>> 2) If GAIN adjustment alone can't provide requested
>> scale, adjusting both the time and the gain is
>> attempted.
>> - Driver exposes writable INT_TIME property that can be used
>> for adjusting the measurement time. Time adjustment will also
>> cause the driver to try to adjust the GAIN so that the
>> overall scale is kept as close to the original as possible.
>>
>> Signed-off-by: Matti Vaittinen <mazziesaccount@...il.com>
>>
>> ---
>>
>> Please note: There are few "unfinished" discussions regarding at least:
>>
>> - PROCESSED channel scale.
>
> Hopefully the reply in the other thread covered this.
> It's not PROCESSED as you need to apply the * 1000 so just
> make it _RAW.
>
Your reply in the other thread was just fine :) I think I'll round the
result to luxes (which should be sufficient to many users if I am not
mistaken) - and provide the PROCESSED values to user-space for the sake
of the ultimate simplicity for users.
>> - Implementation details when avoiding division by zero.
>>
>> I have implemented those for this version in a way that I see the best.
>> It would have been better to wait for discussions to finish - but I will
>> be away from the computer for a week - so I wanted to send out the v3
>> with fixes so that people who are interested can do a review while I am
>> away.
>
> I'm getting behind with review anyway so a week delay on this sounds great to
> me ;) I might get to your other series as a result though don't think I'll get there today.
>
Oh, the week elapsed already ;) But don't sweat on it - this series grew
quite large so spending time on reviewing makes perfect sense. I _know_
reviewing, and especially careful reviewing, takes time. And energy.
Sometimes we lack of both, occasionally just the other :) Thanks for all
the effort you and Andy have put on this so far!
>
>> +static int bu27034_calc_mlux(struct bu27034_data *data, __le16 *res, int *val)
>> +{
>> + unsigned int gain0, gain1, meastime;
>> + unsigned int d1_d0_ratio_scaled;
>> + u16 ch0, ch1;
>> + u64 helper64;
>> + int ret;
>> +
>> + /*
>> + * We return 0 luxes if calculation fails. This should be reasonably
>> + * easy to spot from the buffers especially if raw-data channels show
>> + * valid values
>> + */
>> + *val = 0;
>> +
>> + /* Avoid div by zero. */
>> + if (!res[0])
>> + ch0 = 1;
>> + else
>> + ch0 = le16_to_cpu(res[0]);
>> +
>> + if (!res[1])
>> + ch1 = 1;
>> + else
>> + ch1 = le16_to_cpu(res[1]);
>> +
>
> As per other thread. Really don't like the check on 0 before
> the endian conversion. Sure it can be done, but it's a micro optimization that
> seems unnecessary.
Ugh... Andy pointed me the max_t(). I'll use it even though I do really
dislike that change a lot.
>
> ...
>
>> +
>> +static int bu27034_read_raw(struct iio_dev *idev,
>> + struct iio_chan_spec const *chan,
>> + int *val, int *val2, long mask)
>> +{
>> + struct bu27034_data *data = iio_priv(idev);
>> + int ret;
>> +
>> + switch (mask) {
>> + case IIO_CHAN_INFO_INT_TIME:
>> + *val = bu27034_get_int_time(data);
>> + if (*val < 0)
>> + return *val;
>> +
>> + /*
>> + * We use 50000 uS internally for all calculations and only
>> + * convert it to 55000 before returning it to the user.
>> + *
>> + * This is because the data-sheet says the time is 55 mS - but
>> + * vendor provided computations used 50 mS.
>
> No chance of a clarification? would be lovely to not do this!
Actually, since the current code uses the multiplier-field in
gts-helpers - it may be we can just use the 55000 in the tables now. I
need to check it. So perhaps we can avoid this one now! Thanks!
>
>> + */
>> + if (*val == 50000)
>> + *val = 55000;
>> +
>> + return IIO_VAL_INT;
>> +
>> + case IIO_CHAN_INFO_SCALE:
>> + return bu27034_get_scale(data, chan->channel, val, val2);
>> +
>> + case IIO_CHAN_INFO_RAW:
>> + {
>> + if (chan->type != IIO_INTENSITY)
>> + return -EINVAL;
>> +
>> + if (chan->channel < BU27034_CHAN_DATA0 ||
>> + chan->channel > BU27034_CHAN_DATA2)
>> + return -EINVAL;
>> +
>> + /* Don't mess with measurement enabling while buffering */
>> + ret = iio_device_claim_direct_mode(idev);
>> + if (ret)
>> + return ret;
>> +
>> + mutex_lock(&data->mutex);
>> + /*
>> + * Reading one channel at a time is ineffiecient but we don't
>
> spell check comments.
>
>> + * care here. Buffered version should be used if performance is
>> + * an issue.
>> + */
>> + ret = bu27034_get_single_result(data, chan->channel, val);
>> +
>> + mutex_unlock(&data->mutex);
>> + iio_device_release_direct_mode(idev);
>> +
>> + if (ret)
>> + return ret;
>> +
>> + return IIO_VAL_INT;
>> + }
>> +
>> + case IIO_CHAN_INFO_PROCESSED:
>> + if (chan->type != IIO_LIGHT)
>> + return -EINVAL;
>> +
>> + /* Don't mess with measurement enabling while buffering */
>> + ret = iio_device_claim_direct_mode(idev);
>> + if (ret)
>> + return ret;
>> +
>> + mutex_lock(&data->mutex);
>> +
>> + ret = bu27034_get_mlux(data, val);
>> +
>> + mutex_unlock(&data->mutex);
>> + iio_device_release_direct_mode(idev);
>> +
>> + if (ret)
>> + return ret;
>> +
>> + return IIO_VAL_INT;
>> +
>> + default:
>> + return -EINVAL;
>> +
>> + }
>> +
>> + return ret;
>
> I would hope you can't get here. If you can fix that so
> that the lack of return here allows the compiler to know you didn't
> intend to get here and hence complain about it.
>
Sigh. I personally still think functions should return from the end...
Well, I will revise this for v4.
>
>> +static int bu27034_probe(struct i2c_client *i2c)
>> +{
>> + struct device *dev = &i2c->dev;
>> + struct bu27034_data *data;
>> + struct regmap *regmap;
>> + struct iio_dev *idev;
>> + unsigned int part_id, reg;
>> + int ret;
>> +
>> + regmap = devm_regmap_init_i2c(i2c, &bu27034_regmap);
>> + if (IS_ERR(regmap))
>> + return dev_err_probe(dev, PTR_ERR(regmap),
>> + "Failed to initialize Regmap\n");
>> +
>> + idev = devm_iio_device_alloc(dev, sizeof(*data));
>> + if (!idev)
>> + return -ENOMEM;
>> +
>> + ret = devm_regulator_get_enable(dev, "vdd");
>> + if (ret && ret != -ENODEV)
>
> Why the special -ENODEV handling?
> You should get a stub regulator if one isn't provided by firmware.
> If you don't get a stub, or a real regulator that's a failure so we should
> return the error code and fail the probe.
I am actually not sure. Maybe my test setup didn't have the dummy
regulator assigned. I will re-check this.
The comments which I just skipped are something I more or less agree with :)
Best Regards
-- Matti
--
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland
~~ When things go utterly wrong vim users can always type :help! ~~
Powered by blists - more mailing lists