1 From 28725443a44ba4ed854195cd2916a0ae59c4259f Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Mon, 16 Jan 2023 15:44:50 +0100
4 Subject: [PATCH] media: i2c: imx290: Use runtime PM autosuspend
6 Upstream commit a8c3e0c1bf1e
8 Use runtime PM autosuspend to avoid powering off the sensor during fast
9 stop-reconfigure-restart cycles. This also fixes runtime PM handling in
10 the probe function that didn't suspend the device, effectively leaving
13 While at it, improve documentation of power management in probe() and
16 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
17 Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>
18 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
19 Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
21 drivers/media/i2c/imx290.c | 58 +++++++++++++++++++++++++++++---------
22 1 file changed, 45 insertions(+), 13 deletions(-)
24 --- a/drivers/media/i2c/imx290.c
25 +++ b/drivers/media/i2c/imx290.c
26 @@ -626,7 +626,8 @@ static int imx290_set_ctrl(struct v4l2_c
30 - pm_runtime_put(imx290->dev);
31 + pm_runtime_mark_last_busy(imx290->dev);
32 + pm_runtime_put_autosuspend(imx290->dev);
36 @@ -827,12 +828,13 @@ static int imx290_set_stream(struct v4l2
37 ret = imx290_start_streaming(imx290, state);
39 dev_err(imx290->dev, "Start stream failed\n");
40 - pm_runtime_put(imx290->dev);
41 + pm_runtime_put_sync(imx290->dev);
45 imx290_stop_streaming(imx290);
46 - pm_runtime_put(imx290->dev);
47 + pm_runtime_mark_last_busy(imx290->dev);
48 + pm_runtime_put_autosuspend(imx290->dev);
52 @@ -1269,33 +1271,59 @@ static int imx290_probe(struct i2c_clien
56 - /* Initialize and register subdev. */
57 + /* Initialize the V4L2 subdev. */
58 ret = imx290_subdev_init(imx290);
62 - ret = v4l2_async_register_subdev(&imx290->sd);
64 - dev_err(dev, "Could not register v4l2 device\n");
68 - /* Power on the device to match runtime PM state below */
70 + * Enable power management. The driver supports runtime PM, but needs to
71 + * work when runtime PM is disabled in the kernel. To that end, power
72 + * the sensor on manually here.
74 ret = imx290_power_on(dev);
76 dev_err(dev, "Could not power on the device\n");
81 + * Enable runtime PM with autosuspend. As the device has been powered
82 + * manually, mark it as active, and increase the usage count without
83 + * resuming the device.
85 pm_runtime_set_active(dev);
86 + pm_runtime_get_noresume(dev);
87 pm_runtime_enable(dev);
88 - pm_runtime_idle(dev);
89 + pm_runtime_set_autosuspend_delay(dev, 1000);
90 + pm_runtime_use_autosuspend(dev);
93 + * Finally, register the V4L2 subdev. This must be done after
94 + * initializing everything as the subdev can be used immediately after
97 + ret = v4l2_async_register_subdev(&imx290->sd);
99 + dev_err(dev, "Could not register v4l2 device\n");
104 + * Decrease the PM usage count. The device will get suspended after the
105 + * autosuspend delay, turning the power off.
107 + pm_runtime_mark_last_busy(dev);
108 + pm_runtime_put_autosuspend(dev);
113 + pm_runtime_disable(dev);
114 + pm_runtime_put_noidle(dev);
115 + imx290_power_off(dev);
117 imx290_subdev_cleanup(imx290);
122 @@ -1307,6 +1335,10 @@ static void imx290_remove(struct i2c_cli
123 v4l2_async_unregister_subdev(sd);
124 imx290_subdev_cleanup(imx290);
127 + * Disable runtime PM. In case runtime PM is disabled in the kernel,
128 + * make sure to turn power off manually.
130 pm_runtime_disable(imx290->dev);
131 if (!pm_runtime_status_suspended(imx290->dev))
132 imx290_power_off(imx290->dev);