On Sat May 17 13:41:03 2025 +0200, Hans de Goede wrote: > The i2c-client's power-domain has already been powered up when probe() > gets called. So e.g. ACPI resources for regulators and clks have > already been enabled and only the GPIOs need to be set to the on state. > > Instead of calling pm_runtime_set_suspended() while the domain is > already powered up and then have detect() do a pm_runtime_get() > to set the GPIOs do the following: > > 1. Call gc0310_power_on() to only set the GPIOs > 2. Set the device's runtime-PM state to active instead of suspended > 3. Avoid the device getting suspended as soon as pm_runtime_enable() > gets called by calling pm_runtime_get() before _enable(), this means > moving the pm_runtime_get() / _put() from detect() to probe () > > This fixes power_on() not getting called when runtime-PM is not > enabled in the Kconfig and this keeps the sensor powered-up while > registering it avoiding unnecessary power cycles. > > Also modify gc0310_remove() to power-off the device if it is in > active state when gc0310_remove() runs. > > Signed-off-by: Hans de Goede <ha...@kernel.org> > Reviewed-by: Andy Shevchenko <a...@kernel.org> > Link: https://lore.kernel.org/r/20250517114106.43494-21-ha...@kernel.org > Signed-off-by: Mauro Carvalho Chehab <mchehab+hua...@kernel.org>
Patch committed. Thanks, Mauro Carvalho Chehab drivers/staging/media/atomisp/i2c/atomisp-gc0310.c | 58 +++++++++++----------- 1 file changed, 28 insertions(+), 30 deletions(-) --- diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index c4d85d65737c..173ddf41ad47 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -416,11 +416,7 @@ static int gc0310_detect(struct gc0310_device *sensor) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - ret = pm_runtime_get_sync(&client->dev); - if (ret >= 0) - ret = cci_read(sensor->regmap, GC0310_SC_CMMN_CHIP_ID_REG, - &val, NULL); - pm_runtime_put(&client->dev); + ret = cci_read(sensor->regmap, GC0310_SC_CMMN_CHIP_ID_REG, &val, NULL); if (ret < 0) { dev_err(&client->dev, "read sensor_id failed: %d\n", ret); return -ENODEV; @@ -650,13 +646,15 @@ static void gc0310_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct gc0310_device *sensor = to_gc0310_sensor(sd); - dev_dbg(&client->dev, "gc0310_remove...\n"); - v4l2_async_unregister_subdev(sd); v4l2_subdev_cleanup(sd); media_entity_cleanup(&sensor->sd.entity); v4l2_ctrl_handler_free(&sensor->ctrls.handler); pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) { + gc0310_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + } } static int gc0310_check_hwcfg(struct device *dev) @@ -744,16 +742,15 @@ static int gc0310_probe(struct i2c_client *client) if (IS_ERR(sensor->regmap)) return PTR_ERR(sensor->regmap); - pm_runtime_set_suspended(&client->dev); + gc0310_power_on(&client->dev); + + pm_runtime_set_active(&client->dev); + pm_runtime_get_noresume(&client->dev); pm_runtime_enable(&client->dev); - pm_runtime_set_autosuspend_delay(&client->dev, 1000); - pm_runtime_use_autosuspend(&client->dev); ret = gc0310_detect(sensor); - if (ret) { - gc0310_remove(client); - return ret; - } + if (ret) + goto err_power_down; sensor->sd.internal_ops = &gc0310_internal_ops; sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -761,31 +758,32 @@ static int gc0310_probe(struct i2c_client *client) sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; ret = gc0310_init_controls(sensor); - if (ret) { - gc0310_remove(client); - return ret; - } + if (ret) + goto err_power_down; ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); - if (ret) { - gc0310_remove(client); - return ret; - } + if (ret) + goto err_power_down; sensor->sd.state_lock = sensor->ctrls.handler.lock; ret = v4l2_subdev_init_finalize(&sensor->sd); - if (ret) { - gc0310_remove(client); - return ret; - } + if (ret) + goto err_power_down; ret = v4l2_async_register_subdev_sensor(&sensor->sd); - if (ret) { - gc0310_remove(client); - return ret; - } + if (ret) + goto err_power_down; + + pm_runtime_set_autosuspend_delay(&client->dev, 1000); + pm_runtime_use_autosuspend(&client->dev); + pm_runtime_put_autosuspend(&client->dev); return 0; + +err_power_down: + pm_runtime_put_noidle(&client->dev); + gc0310_remove(client); + return ret; } static DEFINE_RUNTIME_DEV_PM_OPS(gc0310_pm_ops,