Hi Laurent, On Thu, Mar 31, 2022 at 01:33:27PM +0300, Laurent Pinchart wrote: > Hi Sakari, > > On Thu, Mar 31, 2022 at 01:08:17PM +0300, Sakari Ailus wrote: > > On Tue, Mar 29, 2022 at 11:01:31AM +0200, Jacopo Mondi wrote: > > > Implement the power up and power down routines and install them as > > > runtime_pm handler for runtime_suspend and runtime_resume operations. > > > > > > Rework the runtime_pm enablement and the chip power handling during > > > probe, as calling pm_runtime_idle() in a driver that registers no > > > idle callback is a nop. > > > > > > Signed-off-by: Jacopo Mondi <jacopo@xxxxxxxxxx> > > > --- > > > drivers/media/i2c/ov5670.c | 58 ++++++++++++++++++++++++++++++++++---- > > > 1 file changed, 52 insertions(+), 6 deletions(-) > > > > > > diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c > > > index 9e69b4008917..b63b07d8ca2f 100644 > > > --- a/drivers/media/i2c/ov5670.c > > > +++ b/drivers/media/i2c/ov5670.c > > > @@ -4,6 +4,7 @@ > > > #include <linux/acpi.h> > > > #include <linux/clk.h> > > > #include <linux/gpio/consumer.h> > > > +#include <linux/delay.h> > > > #include <linux/i2c.h> > > > #include <linux/mod_devicetable.h> > > > #include <linux/module.h> > > > @@ -2424,6 +2425,39 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable) > > > return ret; > > > } > > > > > > +static int __maybe_unused ov5670_runtime_resume(struct device *dev) > > > +{ > > > + struct i2c_client *client = to_i2c_client(dev); > > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > > + struct ov5670 *ov5670 = to_ov5670(sd); > > > + int ret; > > > + > > > + ret = regulator_bulk_enable(OV5670_NUM_SUPPLIES, ov5670->supplies); > > > + if (ret) > > > + return ret; > > > + > > > + gpiod_set_value_cansleep(ov5670->pwdn_gpio, 0); > > > + gpiod_set_value_cansleep(ov5670->reset_gpio, 0); > > > + > > > + /* 8192 * 2 clock pulses before the first SCCB transaction. */ > > > + usleep_range(1000, 1500); > > > + > > > + return 0; > > > +} > > > + > > > +static int __maybe_unused ov5670_runtime_suspend(struct device *dev) > > > +{ > > > + struct i2c_client *client = to_i2c_client(dev); > > > + struct v4l2_subdev *sd = i2c_get_clientdata(client); > > > + struct ov5670 *ov5670 = to_ov5670(sd); > > > + > > > + gpiod_set_value_cansleep(ov5670->reset_gpio, 1); > > > + gpiod_set_value_cansleep(ov5670->pwdn_gpio, 1); > > > + regulator_bulk_disable(OV5670_NUM_SUPPLIES, ov5670->supplies); > > > + > > > + return 0; > > > +} > > > + > > > static int __maybe_unused ov5670_suspend(struct device *dev) > > > { > > > struct v4l2_subdev *sd = dev_get_drvdata(dev); > > > @@ -2564,14 +2598,25 @@ static int ov5670_probe(struct i2c_client *client) > > > goto error_print; > > > } > > > > > > + pm_runtime_enable(&client->dev); > > > + > > > full_power = acpi_dev_state_d0(&client->dev); > > > if (full_power) { > > > + ret = pm_runtime_resume_and_get(&client->dev); > > > > This will power the device on, but only on OF systems. > > > > Could you instead power the device on on OF systems explicitly? That's what > > other drivers do, too. The changes would be probably more simple to > > implement, too. > > Can we fix ACPI to do something more sane instead ? :-) I don't want to > see those complicated patterns replicated in all drivers. I guess it could be changed. But it will take time. This patch does not quite represent what it takes to implement runtime PM support without ACPI. Also, sensor drivers shouldn't be somehow special when it comes to power management so depending on CONFIG_PM isn't all that nice either. Of course, removing that Kconfig option would simplify quite a few things. -- Regards, Sakari Ailus