Skip to content

Commit

Permalink
dw9768: Enable low-power probe on ACPI
Browse files Browse the repository at this point in the history
[ Upstream commit 5f9a089 ]

Add support for low-power probe to the driver. Also fix runtime PM API
usage in the driver.

Much of the hassle comes from different factors affecting device power
states during probe for ACPI and DT.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Fixes: 8598912 ("media: i2c: dw9768: Add DW9768 VCM driver")
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Sakari Ailus authored and gregkh committed Dec 31, 2022
1 parent 64f61e1 commit f87cd02
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions drivers/media/i2c/dw9768.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ static int dw9768_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct dw9768 *dw9768;
bool full_power;
unsigned int i;
int ret;

Expand Down Expand Up @@ -469,13 +470,23 @@ static int dw9768_probe(struct i2c_client *client)

dw9768->sd.entity.function = MEDIA_ENT_F_LENS;

/*
* Figure out whether we're going to power up the device here. Generally
* this is done if CONFIG_PM is disabled in a DT system or the device is
* to be powered on in an ACPI system. Similarly for power off in
* remove.
*/
pm_runtime_enable(dev);
if (!pm_runtime_enabled(dev)) {
full_power = (is_acpi_node(dev_fwnode(dev)) &&
acpi_dev_state_d0(dev)) ||
(is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev));
if (full_power) {
ret = dw9768_runtime_resume(dev);
if (ret < 0) {
dev_err(dev, "failed to power on: %d\n", ret);
goto err_clean_entity;
}
pm_runtime_set_active(dev);
}

ret = v4l2_async_register_subdev(&dw9768->sd);
Expand All @@ -484,14 +495,17 @@ static int dw9768_probe(struct i2c_client *client)
goto err_power_off;
}

pm_runtime_idle(dev);

return 0;

err_power_off:
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
else
if (full_power) {
dw9768_runtime_suspend(dev);
pm_runtime_set_suspended(dev);
}
err_clean_entity:
pm_runtime_disable(dev);
media_entity_cleanup(&dw9768->sd.entity);
err_free_handler:
v4l2_ctrl_handler_free(&dw9768->ctrls);
Expand All @@ -503,14 +517,17 @@ static void dw9768_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct dw9768 *dw9768 = sd_to_dw9768(sd);
struct device *dev = &client->dev;

v4l2_async_unregister_subdev(&dw9768->sd);
v4l2_ctrl_handler_free(&dw9768->ctrls);
media_entity_cleanup(&dw9768->sd.entity);
pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
dw9768_runtime_suspend(&client->dev);
pm_runtime_set_suspended(&client->dev);
if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) ||
(is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev))) {
dw9768_runtime_suspend(dev);
pm_runtime_set_suspended(dev);
}
pm_runtime_disable(dev);
}

static const struct of_device_id dw9768_of_table[] = {
Expand Down

0 comments on commit f87cd02

Please sign in to comment.