1 From 42d779016414396fe047ef41af6bc8297f3cd6a4 Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Mon, 16 Jan 2023 15:44:51 +0100
4 Subject: [PATCH] media: i2c: imx290: Initialize runtime PM before
7 Upstream commit 02852c01f654
9 Initializing the subdev before runtime PM means that no subdev
10 initialization can interact with the runtime PM framework. This can be
11 problematic when modifying controls, as the .s_ctrl() handler commonly
12 calls pm_runtime_get_if_in_use(). These code paths are not trivial,
13 making the driver fragile and possibly causing subtle bugs.
15 To make the subdev initialization more robust, initialize runtime PM
18 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
19 Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com>
20 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
21 Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
23 drivers/media/i2c/imx290.c | 59 ++++++++++++++++++++++----------------
24 1 file changed, 34 insertions(+), 25 deletions(-)
26 --- a/drivers/media/i2c/imx290.c
27 +++ b/drivers/media/i2c/imx290.c
28 @@ -581,9 +581,7 @@ static int imx290_set_ctrl(struct v4l2_c
31 * Return immediately for controls that don't need to be applied to the
32 - * device. Those controls are modified in imx290_ctrl_update(), which
33 - * is called at probe time before runtime PM is initialized, so we
34 - * can't proceed to the pm_runtime_get_if_in_use() call below.
37 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
39 @@ -1049,22 +1047,20 @@ static void imx290_subdev_cleanup(struct
43 -static int imx290_power_on(struct device *dev)
44 +static int imx290_power_on(struct imx290 *imx290)
46 - struct v4l2_subdev *sd = dev_get_drvdata(dev);
47 - struct imx290 *imx290 = to_imx290(sd);
50 ret = clk_prepare_enable(imx290->xclk);
52 - dev_err(dev, "Failed to enable clock\n");
53 + dev_err(imx290->dev, "Failed to enable clock\n");
57 ret = regulator_bulk_enable(ARRAY_SIZE(imx290->supplies),
60 - dev_err(dev, "Failed to enable regulators\n");
61 + dev_err(imx290->dev, "Failed to enable regulators\n");
62 clk_disable_unprepare(imx290->xclk);
65 @@ -1079,20 +1075,33 @@ static int imx290_power_on(struct device
69 -static int imx290_power_off(struct device *dev)
70 +static void imx290_power_off(struct imx290 *imx290)
72 - struct v4l2_subdev *sd = dev_get_drvdata(dev);
73 - struct imx290 *imx290 = to_imx290(sd);
75 clk_disable_unprepare(imx290->xclk);
76 gpiod_set_value_cansleep(imx290->rst_gpio, 1);
77 regulator_bulk_disable(ARRAY_SIZE(imx290->supplies), imx290->supplies);
80 +static int imx290_runtime_resume(struct device *dev)
82 + struct v4l2_subdev *sd = dev_get_drvdata(dev);
83 + struct imx290 *imx290 = to_imx290(sd);
85 + return imx290_power_on(imx290);
88 +static int imx290_runtime_suspend(struct device *dev)
90 + struct v4l2_subdev *sd = dev_get_drvdata(dev);
91 + struct imx290 *imx290 = to_imx290(sd);
93 + imx290_power_off(imx290);
98 static const struct dev_pm_ops imx290_pm_ops = {
99 - SET_RUNTIME_PM_OPS(imx290_power_off, imx290_power_on, NULL)
100 + SET_RUNTIME_PM_OPS(imx290_runtime_suspend, imx290_runtime_resume, NULL)
103 /* ----------------------------------------------------------------------------
104 @@ -1271,20 +1280,15 @@ static int imx290_probe(struct i2c_clien
108 - /* Initialize the V4L2 subdev. */
109 - ret = imx290_subdev_init(imx290);
114 * Enable power management. The driver supports runtime PM, but needs to
115 * work when runtime PM is disabled in the kernel. To that end, power
116 * the sensor on manually here.
118 - ret = imx290_power_on(dev);
119 + ret = imx290_power_on(imx290);
121 dev_err(dev, "Could not power on the device\n");
127 @@ -1298,6 +1302,11 @@ static int imx290_probe(struct i2c_clien
128 pm_runtime_set_autosuspend_delay(dev, 1000);
129 pm_runtime_use_autosuspend(dev);
131 + /* Initialize the V4L2 subdev. */
132 + ret = imx290_subdev_init(imx290);
137 * Finally, register the V4L2 subdev. This must be done after
138 * initializing everything as the subdev can be used immediately after
139 @@ -1306,7 +1315,7 @@ static int imx290_probe(struct i2c_clien
140 ret = v4l2_async_register_subdev(&imx290->sd);
142 dev_err(dev, "Could not register v4l2 device\n");
148 @@ -1318,12 +1327,12 @@ static int imx290_probe(struct i2c_clien
153 + imx290_subdev_cleanup(imx290);
155 pm_runtime_disable(dev);
156 pm_runtime_put_noidle(dev);
157 - imx290_power_off(dev);
159 - imx290_subdev_cleanup(imx290);
160 + imx290_power_off(imx290);
164 @@ -1341,7 +1350,7 @@ static void imx290_remove(struct i2c_cli
166 pm_runtime_disable(imx290->dev);
167 if (!pm_runtime_status_suspended(imx290->dev))
168 - imx290_power_off(imx290->dev);
169 + imx290_power_off(imx290);
170 pm_runtime_set_suspended(imx290->dev);