]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
media: ov5640: Fix soft reset sequence and timings
authorJai Luthra <j-luthra@ti.com>
Tue, 3 Jan 2023 12:27:35 +0000 (13:27 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2023 08:33:42 +0000 (09:33 +0100)
[ Upstream commit decea0a98b7ac04536c7d659f74783e8d67a06c0 ]

Move the register-based reset out of the init_setting[] and into the
powerup_sequence function. The sensor is power cycled and reset using
the gpio pins so the soft reset is not always necessary.

This also ensures that soft reset honors the timing sequence
from the datasheet [1].

[1] https://cdn.sparkfun.com/datasheets/Sensors/LightImaging/OV5640_datasheet.pdf

Fixes: 19a81c1426c1 ("[media] add Omnivision OV5640 sensor driver")
Reported-by: Nishanth Menon <nm@ti.com>
Suggested-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Jai Luthra <j-luthra@ti.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonaboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/media/i2c/ov5640.c

index 3f6d715efa823f2ff3f00ca3ff48722f407cda95..f31b096e018f28e8ce5ce86b8d9eadb6be037f2a 100644 (file)
@@ -50,6 +50,7 @@
 #define OV5640_REG_SYS_CTRL0           0x3008
 #define OV5640_REG_SYS_CTRL0_SW_PWDN   0x42
 #define OV5640_REG_SYS_CTRL0_SW_PWUP   0x02
+#define OV5640_REG_SYS_CTRL0_SW_RST    0x82
 #define OV5640_REG_CHIP_ID             0x300a
 #define OV5640_REG_IO_MIPI_CTRL00      0x300e
 #define OV5640_REG_PAD_OUTPUT_ENABLE01 0x3017
@@ -532,7 +533,7 @@ static const struct v4l2_mbus_framefmt ov5640_default_fmt = {
 };
 
 static const struct reg_value ov5640_init_setting[] = {
-       {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
+       {0x3103, 0x11, 0, 0},
        {0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
        {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
        {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
@@ -2429,19 +2430,32 @@ static void ov5640_reset(struct ov5640_dev *sensor)
        if (!sensor->reset_gpio)
                return;
 
-       gpiod_set_value_cansleep(sensor->reset_gpio, 0);
+       if (sensor->pwdn_gpio) {
+               gpiod_set_value_cansleep(sensor->reset_gpio, 0);
 
-       /* camera power cycle */
-       ov5640_power(sensor, false);
-       usleep_range(5000, 10000);
-       ov5640_power(sensor, true);
-       usleep_range(5000, 10000);
+               /* camera power cycle */
+               ov5640_power(sensor, false);
+               usleep_range(5000, 10000);
+               ov5640_power(sensor, true);
+               usleep_range(5000, 10000);
 
-       gpiod_set_value_cansleep(sensor->reset_gpio, 1);
-       usleep_range(1000, 2000);
+               gpiod_set_value_cansleep(sensor->reset_gpio, 1);
+               usleep_range(1000, 2000);
 
-       gpiod_set_value_cansleep(sensor->reset_gpio, 0);
+               gpiod_set_value_cansleep(sensor->reset_gpio, 0);
+       } else {
+               /* software reset */
+               ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0,
+                                OV5640_REG_SYS_CTRL0_SW_RST);
+       }
        usleep_range(20000, 25000);
+
+       /*
+        * software standby: allows registers programming;
+        * exit at restore_mode() for CSI, s_stream(1) for DVP
+        */
+       ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0,
+                        OV5640_REG_SYS_CTRL0_SW_PWDN);
 }
 
 static int ov5640_set_power_on(struct ov5640_dev *sensor)