[PATCH v1 2/2] media: ov02c10: Fix sensor power sequencing
From: Saikiran
Date: Thu Oct 22 2026 - 03:18:48 EST
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@xxxxxxxxx>
---
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