From: Ezequiel Garcia <ezequiel@collabora.com>
To: Andrey Konovalov <andrey.konovalov@linaro.org>,
mchehab@kernel.org, robh+dt@kernel.org
Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org,
dave.stevenson@raspberrypi.com, peter.griffin@linaro.org
Subject: Re: [PATCH 2/2] media: i2c: Add driver for Sony IMX219 sensor
Date: Thu, 19 Dec 2019 12:53:38 -0300 [thread overview]
Message-ID: <a3fac083ff8ee55368ed1cd2e57aae1277fb886a.camel@collabora.com> (raw)
In-Reply-To: <a9f585c8-7033-7eb9-6db5-cb2ea2aa63b1@linaro.org>
On Thu, 2019-12-19 at 01:29 +0300, Andrey Konovalov wrote:
> Hi Ezequiel,
>
> Thank you for reviewing the patch!
>
>
[..]
> > > +/* Stop streaming */
> > > +static int imx219_stop_streaming(struct imx219 *imx219)
> > > +{
> > > + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
> > > + int ret;
> > > +
> > > + /* set stream off register */
> > > + ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
> > > + IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
> > > + if (ret)
> > > + dev_err(&client->dev, "%s failed to set stream\n", __func__);
> > > +
> > > + /*
> > > + * Return success even if it was an error, as there is nothing the
> > > + * caller can do about it.
> > > + */
> >
> > Just change this function return to void, instead?
>
> Maybe something like that (functionally the same, but probably more self-explaining):
>
> -----8<-----
> @@ -798,11 +796,7 @@ static int imx219_stop_streaming(struct imx219 *imx219)
I don't know if I'm missing something, but why can't we have:
static void imx219_stop_streaming(struct imx219 *imx219) ?
Since the return value is not used anywhere, it doesn't make sense
to return it.
> if (ret)
> dev_err(&client->dev, "%s failed to set stream\n", __func__);
>
> - /*
> - * Return success even if it was an error, as there is nothing the
> - * caller can do about it.
> - */
> - return 0;
> + return ret;
> }
>
> static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
> @@ -832,7 +826,7 @@ static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
> if (ret)
> goto err_rpm_put;
> } else {
> - imx219_stop_streaming(imx219);
> + (void)imx219_stop_streaming(imx219);
> pm_runtime_put(&client->dev);
> }
> -----8<-----
>
> ?
>
> > > + return 0;
> > > +}
> > > +
> > > +static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
> > > +{
> > > + struct imx219 *imx219 = to_imx219(sd);
> > > + struct i2c_client *client = v4l2_get_subdevdata(sd);
> > > + int ret = 0;
> > > +
> > > + mutex_lock(&imx219->mutex);
> > > + if (imx219->streaming == enable) {
> > > + mutex_unlock(&imx219->mutex);
> > > + return 0;
> > > + }
> > > +
> > > + if (enable) {
> > > + ret = pm_runtime_get_sync(&client->dev);
> > > + if (ret < 0) {
> > > + pm_runtime_put_noidle(&client->dev);
> > > + goto err_unlock;
> > > + }
> > > +
> > > + /*
> > > + * Apply default & customized values
> > > + * and then start streaming.
> > > + */
> > > + ret = imx219_start_streaming(imx219);
> > > + if (ret)
> > > + goto err_rpm_put;
> > > + } else {
> > > + imx219_stop_streaming(imx219);
> > > + pm_runtime_put(&client->dev);
> > > + }
> > > +
> > > + imx219->streaming = enable;
> > > +
> > > + /* vflip and hflip cannot change during streaming */
> > > + __v4l2_ctrl_grab(imx219->vflip, enable);
> > > + __v4l2_ctrl_grab(imx219->hflip, enable);
> > > +
> > > + mutex_unlock(&imx219->mutex);
> > > +
> > > + return ret;
> > > +
> > > +err_rpm_put:
> > > + pm_runtime_put(&client->dev);
> > > +err_unlock:
> > > + mutex_unlock(&imx219->mutex);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +/* Power/clock management functions */
> > > +static int imx219_power_on(struct device *dev)
> > > +{
> > > + struct i2c_client *client = to_i2c_client(dev);
> > > + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > > + struct imx219 *imx219 = to_imx219(sd);
> > > + int ret;
> > > +
> > > + ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES,
> > > + imx219->supplies);
> > > + if (ret) {
> > > + dev_err(&client->dev, "%s: failed to enable regulators\n",
> > > + __func__);
> > > + return ret;
> > > + }
> > > +
> > > + ret = clk_prepare_enable(imx219->xclk);
> > > + if (ret) {
> > > + dev_err(&client->dev, "%s: failed to enable clock\n",
> > > + __func__);
> > > + goto reg_off;
> > > + }
> > > +
> > > + gpiod_set_value_cansleep(imx219->xclr_gpio, 1);
> > > + msleep(IMX219_XCLR_DELAY_MS);
> > > +
> > > + return 0;
> > > +reg_off:
> > > + regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
> > > + return ret;
> > > +}
> > > +
> > > +static int imx219_power_off(struct device *dev)
> > > +{
> > > + struct i2c_client *client = to_i2c_client(dev);
> > > + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > > + struct imx219 *imx219 = to_imx219(sd);
> > > +
> > > + gpiod_set_value_cansleep(imx219->xclr_gpio, 0);
> > > + regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
> > > + clk_disable_unprepare(imx219->xclk);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int __maybe_unused imx219_suspend(struct device *dev)
> > > +{
> > > + struct i2c_client *client = to_i2c_client(dev);
> > > + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > > + struct imx219 *imx219 = to_imx219(sd);
> > > +
> > > + if (imx219->streaming)
> > > + imx219_stop_streaming(imx219);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int __maybe_unused imx219_resume(struct device *dev)
> > > +{
> > > + struct i2c_client *client = to_i2c_client(dev);
> > > + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> > > + struct imx219 *imx219 = to_imx219(sd);
> > > + int ret;
> > > +
> > > + if (imx219->streaming) {
> > > + ret = imx219_start_streaming(imx219);
> > > + if (ret)
> > > + goto error;
> > > + }
> > > +
> > > + return 0;
> > > +
> > > +error:
> > > + imx219_stop_streaming(imx219);
> > > + imx219->streaming = 0;
> > > + return ret;
> > > +}
> > > +
> > > +static int imx219_get_regulators(struct imx219 *imx219)
> > > +{
> > > + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
> > > + int i;
> > > +
> > > + for (i = 0; i < IMX219_NUM_SUPPLIES; i++)
> > > + imx219->supplies[i].supply = imx219_supply_name[i];
> > > +
> > > + return devm_regulator_bulk_get(&client->dev,
> > > + IMX219_NUM_SUPPLIES,
> > > + imx219->supplies);
> > > +}
> > > +
> > > +/* Verify chip ID */
> > > +static int imx219_identify_module(struct imx219 *imx219)
> > > +{
> > > + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
> > > + int ret;
> > > + u32 val;
> > > +
> > > + ret = imx219_power_on(imx219->dev);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID,
> > > + IMX219_REG_VALUE_16BIT, &val);
> > > + if (ret) {
> > > + dev_err(&client->dev, "failed to read chip id %x\n",
> > > + IMX219_CHIP_ID);
> > > + goto power_off;
> > > + }
> > > +
> > > + if (val != IMX219_CHIP_ID) {
> > > + dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
> > > + IMX219_CHIP_ID, val);
> > > + ret = -EIO;
> > > + }
> > > +
> >
> > I wonder if this is not a bit obscure: it's not obvious
> > from a first read that the device is left powered on successful
> > identification.
> >
> > Perhaps you can have:
> >
> > return 0;
> >
> > And then goto err_power_off on the error paths.
> > This way, it's clear that powering off is only
> > to be done on error.
>
> OK. Makes sense. Will fix in v2.
>
> > OTOH, why do we need to leave the device powered on probe?
>
> Let me try what happens if I leave powering the sensor on and off
> to dev_pm_ops. (Seems like it *should* work in theory, but maybe
> there were some hidden problems.)
> (Also I would only be able to check if the sensor works or not - can't
> do the electrical signals or power consumption measurements etc.)
>
> Anyway, leaving the sensor powered on shouldn't hurt, as the sensor
> is kept in lower power mode when it is not streaming (MIPI signals
> are passive - the indication on that is the "clock-noncontinuous"
> property in the DT bindings; also there is no code in the driver
> to change that, then the imx219 sensor must always "turn off"
> MIPI lines when it is not streaming - with the reg setting currently
> used at least).
>
Right, the sensor being in LP state is a good point. IMHO, it's
totally fine is the sensor needs to be powered. It would be
nice to have a nice comment, if only for resource tracking reasons.
Thanks,
Ezequiel
next prev parent reply other threads:[~2019-12-19 15:53 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-11 11:54 [PATCH 0/2] Add IMX219 CMOS image sensor support Andrey Konovalov
2019-12-11 11:54 ` [PATCH 1/2] dt-bindings: media: i2c: Add IMX219 CMOS sensor binding Andrey Konovalov
2019-12-19 21:00 ` Rob Herring
2019-12-11 11:54 ` [PATCH 2/2] media: i2c: Add driver for Sony IMX219 sensor Andrey Konovalov
2019-12-14 5:52 ` Ezequiel Garcia
2019-12-18 22:29 ` Andrey Konovalov
2019-12-19 15:36 ` Dave Stevenson
2019-12-20 17:15 ` Andrey Konovalov
2019-12-19 15:53 ` Ezequiel Garcia [this message]
2019-12-20 17:28 ` Andrey Konovalov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a3fac083ff8ee55368ed1cd2e57aae1277fb886a.camel@collabora.com \
--to=ezequiel@collabora.com \
--cc=andrey.konovalov@linaro.org \
--cc=dave.stevenson@raspberrypi.com \
--cc=devicetree@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=peter.griffin@linaro.org \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).