diff mbox series

[47/57] media: atomisp: ov2680: Add runtime-pm support

Message ID 20230123125205.622152-48-hdegoede@redhat.com (mailing list archive)
State New, archived
Headers show
Series media: atomisp: Big power-management changes + lots of fixes | expand

Commit Message

Hans de Goede Jan. 23, 2023, 12:51 p.m. UTC
Add runtime-pm support. This is a preparation patch for letting
ACPI deal with the regulators and clocks instead of the DIY code
in atomisp_gmin_platform.c.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../media/atomisp/i2c/atomisp-ov2680.c        | 57 ++++++++++++-------
 drivers/staging/media/atomisp/i2c/ov2680.h    |  1 -
 2 files changed, 36 insertions(+), 22 deletions(-)

Comments

Andy Shevchenko Jan. 24, 2023, 10:53 a.m. UTC | #1
On Mon, Jan 23, 2023 at 01:51:55PM +0100, Hans de Goede wrote:
> Add runtime-pm support. This is a preparation patch for letting
> ACPI deal with the regulators and clocks instead of the DIY code
> in atomisp_gmin_platform.c.

Good one!
Reviewed-by: Andy Shevchenko <andy@kernel.org>

> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  .../media/atomisp/i2c/atomisp-ov2680.c        | 57 ++++++++++++-------
>  drivers/staging/media/atomisp/i2c/ov2680.h    |  1 -
>  2 files changed, 36 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
> index 2a8c4508cc66..881340d7466f 100644
> --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
> +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
> @@ -19,6 +19,7 @@
>  #include <linux/device.h>
>  #include <linux/i2c.h>
>  #include <linux/module.h>
> +#include <linux/pm_runtime.h>
>  #include <linux/types.h>
>  #include <media/ovxxxx_16bit_addr_reg_helpers.h>
>  #include <media/v4l2-device.h>
> @@ -138,7 +139,8 @@ static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
>  	struct ov2680_device *sensor = to_ov2680_sensor(sd);
>  	int ret;
>  
> -	if (!sensor->power_on) {
> +	/* Only apply changes to the controls if the device is powered up */
> +	if (!pm_runtime_get_if_in_use(sensor->sd.dev)) {
>  		ov2680_set_bayer_order(sensor, &sensor->mode.fmt);
>  		return 0;
>  	}
> @@ -162,6 +164,8 @@ static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
>  	default:
>  		ret = -EINVAL;
>  	}
> +
> +	pm_runtime_put(sensor->sd.dev);
>  	return ret;
>  }
>  
> @@ -244,9 +248,6 @@ static int power_up(struct v4l2_subdev *sd)
>  		return -ENODEV;
>  	}
>  
> -	if (dev->power_on)
> -		return 0; /* Already on */
> -
>  	/* power control */
>  	ret = power_ctrl(sd, 1);
>  	if (ret)
> @@ -275,7 +276,6 @@ static int power_up(struct v4l2_subdev *sd)
>  	if (ret)
>  		goto fail_init_registers;
>  
> -	dev->power_on = true;
>  	return 0;
>  
>  fail_init_registers:
> @@ -301,9 +301,6 @@ static int power_down(struct v4l2_subdev *sd)
>  		return -ENODEV;
>  	}
>  
> -	if (!dev->power_on)
> -		return 0; /* Already off */
> -
>  	ret = dev->platform_data->flisclk_ctrl(sd, 0);
>  	if (ret)
>  		dev_err(&client->dev, "flisclk failed\n");
> @@ -323,7 +320,6 @@ static int power_down(struct v4l2_subdev *sd)
>  		return ret;
>  	}
>  
> -	dev->power_on = false;
>  	return 0;
>  }
>  
> @@ -562,8 +558,8 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
>  	}
>  
>  	if (enable) {
> -		ret = power_up(sd);
> -		if (ret)
> +		ret = pm_runtime_get_sync(sensor->sd.dev);
> +		if (ret < 0)
>  			goto error_unlock;
>  
>  		ret = ov2680_set_mode(sensor);
> @@ -580,7 +576,7 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
>  			goto error_power_down;
>  	} else {
>  		ovxxxx_write_reg8(client, OV2680_SW_STREAM, OV2680_STOP_STREAMING);
> -		power_down(sd);
> +		pm_runtime_put(sensor->sd.dev);
>  	}
>  
>  	sensor->is_streaming = enable;
> @@ -591,7 +587,7 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
>  	return 0;
>  
>  error_power_down:
> -	power_down(sd);
> +	pm_runtime_put(sensor->sd.dev);
>  error_unlock:
>  	mutex_unlock(&sensor->input_lock);
>  	return ret;
> @@ -612,8 +608,8 @@ static int ov2680_s_config(struct v4l2_subdev *sd,
>  
>  	mutex_lock(&dev->input_lock);
>  
> -	ret = power_up(sd);
> -	if (ret) {
> +	ret = pm_runtime_get_sync(&client->dev);
> +	if (ret < 0) {
>  		dev_err(&client->dev, "ov2680 power-up err.\n");
>  		goto fail_power_on;
>  	}
> @@ -630,11 +626,7 @@ static int ov2680_s_config(struct v4l2_subdev *sd,
>  	}
>  
>  	/* turn off sensor, after probed */
> -	ret = power_down(sd);
> -	if (ret) {
> -		dev_err(&client->dev, "ov2680 power-off err.\n");
> -		goto fail_csi_cfg;
> -	}
> +	pm_runtime_put(&client->dev);
>  	mutex_unlock(&dev->input_lock);
>  
>  	return 0;
> @@ -642,7 +634,7 @@ static int ov2680_s_config(struct v4l2_subdev *sd,
>  fail_csi_cfg:
>  	dev->platform_data->csi_cfg(sd, 0);
>  fail_power_on:
> -	power_down(sd);
> +	pm_runtime_put(&client->dev);
>  	dev_err(&client->dev, "sensor power-gating failed\n");
>  	mutex_unlock(&dev->input_lock);
>  	return ret;
> @@ -787,6 +779,7 @@ static void ov2680_remove(struct i2c_client *client)
>  	v4l2_device_unregister_subdev(sd);
>  	media_entity_cleanup(&dev->sd.entity);
>  	v4l2_ctrl_handler_free(&dev->ctrls.handler);
> +	pm_runtime_disable(&client->dev);
>  	kfree(dev);
>  }
>  
> @@ -813,6 +806,11 @@ static int ov2680_probe(struct i2c_client *client)
>  		goto out_free;
>  	}
>  
> +	pm_runtime_set_suspended(&client->dev);
> +	pm_runtime_enable(&client->dev);
> +	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
> +	pm_runtime_use_autosuspend(&client->dev);
> +
>  	ret = ov2680_s_config(&dev->sd, client->irq, pdata);
>  	if (ret)
>  		goto out_free;
> @@ -849,6 +847,22 @@ static int ov2680_probe(struct i2c_client *client)
>  	return ret;
>  }
>  
> +static int ov2680_suspend(struct device *dev)
> +{
> +	struct v4l2_subdev *sd = dev_get_drvdata(dev);
> +
> +	return power_down(sd);
> +}
> +
> +static int ov2680_resume(struct device *dev)
> +{
> +	struct v4l2_subdev *sd = dev_get_drvdata(dev);
> +
> +	return power_up(sd);
> +}
> +
> +static DEFINE_RUNTIME_DEV_PM_OPS(ov2680_pm_ops, ov2680_suspend, ov2680_resume, NULL);
> +
>  static const struct acpi_device_id ov2680_acpi_match[] = {
>  	{"XXOV2680"},
>  	{"OVTI2680"},
> @@ -859,6 +873,7 @@ MODULE_DEVICE_TABLE(acpi, ov2680_acpi_match);
>  static struct i2c_driver ov2680_driver = {
>  	.driver = {
>  		.name = "ov2680",
> +		.pm = pm_sleep_ptr(&ov2680_pm_ops),
>  		.acpi_match_table = ov2680_acpi_match,
>  	},
>  	.probe_new = ov2680_probe,
> diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h
> index f0641dd611c3..58593da50f6f 100644
> --- a/drivers/staging/media/atomisp/i2c/ov2680.h
> +++ b/drivers/staging/media/atomisp/i2c/ov2680.h
> @@ -120,7 +120,6 @@ struct ov2680_device {
>  	struct mutex input_lock;
>  	struct i2c_client *client;
>  	struct camera_sensor_platform_data *platform_data;
> -	bool power_on;
>  	bool is_streaming;
>  
>  	struct ov2680_mode {
> -- 
> 2.39.0
>
diff mbox series

Patch

diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
index 2a8c4508cc66..881340d7466f 100644
--- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
+++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c
@@ -19,6 +19,7 @@ 
 #include <linux/device.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/types.h>
 #include <media/ovxxxx_16bit_addr_reg_helpers.h>
 #include <media/v4l2-device.h>
@@ -138,7 +139,8 @@  static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
 	struct ov2680_device *sensor = to_ov2680_sensor(sd);
 	int ret;
 
-	if (!sensor->power_on) {
+	/* Only apply changes to the controls if the device is powered up */
+	if (!pm_runtime_get_if_in_use(sensor->sd.dev)) {
 		ov2680_set_bayer_order(sensor, &sensor->mode.fmt);
 		return 0;
 	}
@@ -162,6 +164,8 @@  static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
 	default:
 		ret = -EINVAL;
 	}
+
+	pm_runtime_put(sensor->sd.dev);
 	return ret;
 }
 
@@ -244,9 +248,6 @@  static int power_up(struct v4l2_subdev *sd)
 		return -ENODEV;
 	}
 
-	if (dev->power_on)
-		return 0; /* Already on */
-
 	/* power control */
 	ret = power_ctrl(sd, 1);
 	if (ret)
@@ -275,7 +276,6 @@  static int power_up(struct v4l2_subdev *sd)
 	if (ret)
 		goto fail_init_registers;
 
-	dev->power_on = true;
 	return 0;
 
 fail_init_registers:
@@ -301,9 +301,6 @@  static int power_down(struct v4l2_subdev *sd)
 		return -ENODEV;
 	}
 
-	if (!dev->power_on)
-		return 0; /* Already off */
-
 	ret = dev->platform_data->flisclk_ctrl(sd, 0);
 	if (ret)
 		dev_err(&client->dev, "flisclk failed\n");
@@ -323,7 +320,6 @@  static int power_down(struct v4l2_subdev *sd)
 		return ret;
 	}
 
-	dev->power_on = false;
 	return 0;
 }
 
@@ -562,8 +558,8 @@  static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
 	}
 
 	if (enable) {
-		ret = power_up(sd);
-		if (ret)
+		ret = pm_runtime_get_sync(sensor->sd.dev);
+		if (ret < 0)
 			goto error_unlock;
 
 		ret = ov2680_set_mode(sensor);
@@ -580,7 +576,7 @@  static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
 			goto error_power_down;
 	} else {
 		ovxxxx_write_reg8(client, OV2680_SW_STREAM, OV2680_STOP_STREAMING);
-		power_down(sd);
+		pm_runtime_put(sensor->sd.dev);
 	}
 
 	sensor->is_streaming = enable;
@@ -591,7 +587,7 @@  static int ov2680_s_stream(struct v4l2_subdev *sd, int enable)
 	return 0;
 
 error_power_down:
-	power_down(sd);
+	pm_runtime_put(sensor->sd.dev);
 error_unlock:
 	mutex_unlock(&sensor->input_lock);
 	return ret;
@@ -612,8 +608,8 @@  static int ov2680_s_config(struct v4l2_subdev *sd,
 
 	mutex_lock(&dev->input_lock);
 
-	ret = power_up(sd);
-	if (ret) {
+	ret = pm_runtime_get_sync(&client->dev);
+	if (ret < 0) {
 		dev_err(&client->dev, "ov2680 power-up err.\n");
 		goto fail_power_on;
 	}
@@ -630,11 +626,7 @@  static int ov2680_s_config(struct v4l2_subdev *sd,
 	}
 
 	/* turn off sensor, after probed */
-	ret = power_down(sd);
-	if (ret) {
-		dev_err(&client->dev, "ov2680 power-off err.\n");
-		goto fail_csi_cfg;
-	}
+	pm_runtime_put(&client->dev);
 	mutex_unlock(&dev->input_lock);
 
 	return 0;
@@ -642,7 +634,7 @@  static int ov2680_s_config(struct v4l2_subdev *sd,
 fail_csi_cfg:
 	dev->platform_data->csi_cfg(sd, 0);
 fail_power_on:
-	power_down(sd);
+	pm_runtime_put(&client->dev);
 	dev_err(&client->dev, "sensor power-gating failed\n");
 	mutex_unlock(&dev->input_lock);
 	return ret;
@@ -787,6 +779,7 @@  static void ov2680_remove(struct i2c_client *client)
 	v4l2_device_unregister_subdev(sd);
 	media_entity_cleanup(&dev->sd.entity);
 	v4l2_ctrl_handler_free(&dev->ctrls.handler);
+	pm_runtime_disable(&client->dev);
 	kfree(dev);
 }
 
@@ -813,6 +806,11 @@  static int ov2680_probe(struct i2c_client *client)
 		goto out_free;
 	}
 
+	pm_runtime_set_suspended(&client->dev);
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+	pm_runtime_use_autosuspend(&client->dev);
+
 	ret = ov2680_s_config(&dev->sd, client->irq, pdata);
 	if (ret)
 		goto out_free;
@@ -849,6 +847,22 @@  static int ov2680_probe(struct i2c_client *client)
 	return ret;
 }
 
+static int ov2680_suspend(struct device *dev)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+
+	return power_down(sd);
+}
+
+static int ov2680_resume(struct device *dev)
+{
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+
+	return power_up(sd);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(ov2680_pm_ops, ov2680_suspend, ov2680_resume, NULL);
+
 static const struct acpi_device_id ov2680_acpi_match[] = {
 	{"XXOV2680"},
 	{"OVTI2680"},
@@ -859,6 +873,7 @@  MODULE_DEVICE_TABLE(acpi, ov2680_acpi_match);
 static struct i2c_driver ov2680_driver = {
 	.driver = {
 		.name = "ov2680",
+		.pm = pm_sleep_ptr(&ov2680_pm_ops),
 		.acpi_match_table = ov2680_acpi_match,
 	},
 	.probe_new = ov2680_probe,
diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h
index f0641dd611c3..58593da50f6f 100644
--- a/drivers/staging/media/atomisp/i2c/ov2680.h
+++ b/drivers/staging/media/atomisp/i2c/ov2680.h
@@ -120,7 +120,6 @@  struct ov2680_device {
 	struct mutex input_lock;
 	struct i2c_client *client;
 	struct camera_sensor_platform_data *platform_data;
-	bool power_on;
 	bool is_streaming;
 
 	struct ov2680_mode {