mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v1 0/2] i2c: qcom-cci, media: ov02c10: Fix camera power cycling
@ 2026-10-22  7:14 Saikiran
  2026-10-22  7:14 ` [PATCH v1 1/2] i2c: qcom-cci: Select pinctrl states during runtime PM Saikiran
  2026-10-22  7:14 ` [PATCH v1 2/2] media: ov02c10: Fix sensor power sequencing Saikiran
  0 siblings, 2 replies; 3+ messages in thread
From: Saikiran @ 2026-10-22  7:14 UTC (permalink / raw)
  To: loic.poulain
  Cc: rfoss, andi.shyti, sakari.ailus, hansg, bod, mchehab,
	vladimir.zapolskiy, jishnu.prakash, birk.skyum, linux-i2c,
	linux-arm-msm, linux-kernel, linux-media

The OV02C10 camera on the Lenovo Yoga Slim 7x can fail to restart after
streaming stops. The CCI runtime PM callbacks gate the controller clocks
but leave the bus pins in their default state while suspended. The X1E80100
device tree already defines a CCI sleep state with pull-downs for the bus
pins, so select that state before suspending the controller and restore the
default state on resume.

The OV02C10 driver also enables the sensor supplies before MCLK and disables
MCLK before the supplies, with the required reset and startup timing. This
series fixes the power transitions without adding a regulator-off delay or
runtime autosuspend workaround.

Tested on Lenovo Yoga Slim 7x (Snapdragon X Elite): 20 consecutive Kamoso
camera open/close cycles. The sensor entered runtime-active on each open and
returned to runtime-suspended on each close. Both modified driver objects
build cleanly against the running kernel configuration.

Saikiran (2):
  i2c: qcom-cci: Select pinctrl states during runtime PM
  media: ov02c10: Fix sensor power sequencing

 drivers/i2c/busses/i2c-qcom-cci.c | 14 +++++++++++++-
 drivers/media/i2c/ov02c10.c       | 20 +++++++++++---------
 2 files changed, 24 insertions(+), 10 deletions(-)

-- 
2.56.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v1 1/2] i2c: qcom-cci: Select pinctrl states during runtime PM
  2026-10-22  7:14 [PATCH v1 0/2] i2c: qcom-cci, media: ov02c10: Fix camera power cycling Saikiran
@ 2026-10-22  7:14 ` Saikiran
  2026-10-22  7:14 ` [PATCH v1 2/2] media: ov02c10: Fix sensor power sequencing Saikiran
  1 sibling, 0 replies; 3+ messages in thread
From: Saikiran @ 2026-10-22  7:14 UTC (permalink / raw)
  To: loic.poulain
  Cc: rfoss, andi.shyti, sakari.ailus, hansg, bod, mchehab,
	vladimir.zapolskiy, jishnu.prakash, birk.skyum, linux-i2c,
	linux-arm-msm, linux-kernel, linux-media

The CCI runtime PM callbacks only gate the controller clocks, leaving the
bus pins in their default state while the controller is suspended. On the
Lenovo Yoga Slim 7x, this can back-power the camera sensor through SDA and
SCL after its supplies have been disabled, contributing to brownouts on
subsequent power cycles.

Select the sleep pinctrl state before disabling the clocks so that the
configured pull-downs can take effect. Restore the default state before
enabling the clocks on resume, and return to the sleep state if enabling
the clocks fails.

Tested-on: Lenovo Yoga Slim 7x (Snapdragon X Elite)
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
 drivers/i2c/busses/i2c-qcom-cci.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c
index 873e901a23d7..fba5f664eeaa 100644
--- a/drivers/i2c/busses/i2c-qcom-cci.c
+++ b/drivers/i2c/busses/i2c-qcom-cci.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 
 #define CCI_HW_VERSION				0x0
@@ -474,6 +475,11 @@ static void cci_disable_clocks(struct cci *cci)
 static int __maybe_unused cci_suspend_runtime(struct device *dev)
 {
 	struct cci *cci = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pinctrl_pm_select_sleep_state(dev);
+	if (ret)
+		return ret;
 
 	cci_disable_clocks(cci);
 	return 0;
@@ -484,10 +490,16 @@ static int __maybe_unused cci_resume_runtime(struct device *dev)
 	struct cci *cci = dev_get_drvdata(dev);
 	int ret;
 
-	ret = cci_enable_clocks(cci);
+	ret = pinctrl_pm_select_default_state(dev);
 	if (ret)
 		return ret;
 
+	ret = cci_enable_clocks(cci);
+	if (ret) {
+		pinctrl_pm_select_sleep_state(dev);
+		return ret;
+	}
+
 	cci_init(cci);
 	return 0;
 }
-- 
2.56.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v1 2/2] media: ov02c10: Fix sensor power sequencing
  2026-10-22  7:14 [PATCH v1 0/2] i2c: qcom-cci, media: ov02c10: Fix camera power cycling Saikiran
  2026-10-22  7:14 ` [PATCH v1 1/2] i2c: qcom-cci: Select pinctrl states during runtime PM Saikiran
@ 2026-10-22  7:14 ` Saikiran
  1 sibling, 0 replies; 3+ messages in thread
From: Saikiran @ 2026-10-22  7:14 UTC (permalink / raw)
  To: loic.poulain
  Cc: rfoss, andi.shyti, sakari.ailus, hansg, bod, mchehab,
	vladimir.zapolskiy, jishnu.prakash, birk.skyum, linux-i2c,
	linux-arm-msm, linux-kernel, linux-media

The OV02C10 driver enables MCLK before the sensor supplies and disables it
after the supplies. This can back-power the sensor through MCLK while its
supplies are off and contributes to camera brownouts on the Lenovo Yoga
Slim 7x.

Follow the power sequence used by the firmware on this platform: enable the
supplies before MCLK and disable MCLK before the supplies. Hold reset for
at least 1 ms before disabling MCLK on power-off, and wait at least 10 ms
after releasing reset on power-on to allow the sensor to start up.

Update the power-on error path to disable the supplies if enabling MCLK
fails.

Tested-on: Lenovo Yoga Slim 7x (Snapdragon X Elite)
Signed-off-by: Saikiran <bjsaikiran@gmail.com>
---
 drivers/media/i2c/ov02c10.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/media/i2c/ov02c10.c b/drivers/media/i2c/ov02c10.c
index 221cb93126ec..42aa43ea0a22 100644
--- a/drivers/media/i2c/ov02c10.c
+++ b/drivers/media/i2c/ov02c10.c
@@ -661,12 +661,13 @@ static int ov02c10_power_off(struct device *dev)
 	struct ov02c10 *ov02c10 = to_ov02c10(sd);
 
 	gpiod_set_value_cansleep(ov02c10->reset, 1);
+	usleep_range(1000, 1100);
+
+	clk_disable_unprepare(ov02c10->img_clk);
 
 	regulator_bulk_disable(ARRAY_SIZE(ov02c10_supply_names),
 			       ov02c10->supplies);
 
-	clk_disable_unprepare(ov02c10->img_clk);
-
 	return 0;
 }
 
@@ -682,23 +683,24 @@ static int ov02c10_power_on(struct device *dev)
 		usleep_range(5000, 6000);
 	}
 
-	ret = clk_prepare_enable(ov02c10->img_clk);
+	ret = regulator_bulk_enable(ARRAY_SIZE(ov02c10_supply_names),
+				    ov02c10->supplies);
 	if (ret < 0) {
-		dev_err(dev, "failed to enable imaging clock: %d", ret);
+		dev_err(dev, "failed to enable regulators: %d", ret);
 		return ret;
 	}
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(ov02c10_supply_names),
-				    ov02c10->supplies);
+	ret = clk_prepare_enable(ov02c10->img_clk);
 	if (ret < 0) {
-		dev_err(dev, "failed to enable regulators: %d", ret);
-		clk_disable_unprepare(ov02c10->img_clk);
+		dev_err(dev, "failed to enable imaging clock: %d", ret);
+		regulator_bulk_disable(ARRAY_SIZE(ov02c10_supply_names),
+				       ov02c10->supplies);
 		return ret;
 	}
 
 	if (ov02c10->reset) {
 		gpiod_set_value_cansleep(ov02c10->reset, 0);
-		usleep_range(5000, 5500);
+		usleep_range(10000, 11000);
 	}
 
 	return 0;
-- 
2.56.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-22  7:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22  7:14 [PATCH v1 0/2] i2c: qcom-cci, media: ov02c10: Fix camera power cycling Saikiran
2026-10-22  7:14 ` [PATCH v1 1/2] i2c: qcom-cci: Select pinctrl states during runtime PM Saikiran
2026-10-22  7:14 ` [PATCH v1 2/2] media: ov02c10: Fix sensor power sequencing Saikiran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®