Skip to content

Commit 2b82169

Browse files
Jacopo Mondimchehab
authored andcommitted
media: i2c: rdacm21: Power up OV10640 before OV490
The current RDACM21 initialization routine powers up the OV10640 image sensor after the OV490 ISP. The ISP is programmed with a firmware loaded from an embedded serial flash that (most probably) tries to interact and program also the image sensor connected to the ISP. As described in commit "media: i2c: rdacm21: Fix OV10640 powerup" the image sensor powerdown signal is kept high by an internal pull up resistor and occasionally fails to startup correctly if the powerdown line is not asserted explicitly. Failures in the OV10640 startup causes the OV490 firmware to fail to boot correctly resulting in the camera module initialization to fail consequentially. Fix this by powering up the OV10640 image sensor before testing the OV490 firmware boot completion, by splitting the ov10640_initialize() function in an ov10640_power_up() one and an ov10640_check_id() one. Also make sure the OV10640 identification procedure gives enough time to the image sensor to resume after the programming phase performed by the OV490 firmware by repeating the ID read procedure. This commit fixes a sporadic start-up error triggered by a failure to detect the OV490 firmware boot completion: rdacm21 8-0054: Timeout waiting for firmware boot [hverkuil: fixed two typos in commit log] Fixes: a59f853 ("media: i2c: Add driver for RDACM21 camera module") Signed-off-by: Jacopo Mondi <[email protected]> Reviewed-by: Laurent Pinchart <[email protected]> Reviewed-by: Kieran Bingham <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent ff75332 commit 2b82169

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

drivers/media/i2c/rdacm21.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#define OV490_ISP_VSIZE_LOW 0x80820062
7070
#define OV490_ISP_VSIZE_HIGH 0x80820063
7171

72+
#define OV10640_PID_TIMEOUT 20
7273
#define OV10640_ID_HIGH 0xa6
7374
#define OV10640_CHIP_ID 0x300a
7475
#define OV10640_PIXEL_RATE 55000000
@@ -329,10 +330,8 @@ static const struct v4l2_subdev_ops rdacm21_subdev_ops = {
329330
.pad = &rdacm21_subdev_pad_ops,
330331
};
331332

332-
static int ov10640_initialize(struct rdacm21_device *dev)
333+
static void ov10640_power_up(struct rdacm21_device *dev)
333334
{
334-
u8 val;
335-
336335
/* Enable GPIO0#0 (reset) and GPIO1#0 (pwdn) as output lines. */
337336
ov490_write_reg(dev, OV490_GPIO_SEL0, OV490_GPIO0);
338337
ov490_write_reg(dev, OV490_GPIO_SEL1, OV490_SPWDN0);
@@ -347,18 +346,35 @@ static int ov10640_initialize(struct rdacm21_device *dev)
347346
usleep_range(1500, 3000);
348347
ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_GPIO0);
349348
usleep_range(3000, 5000);
349+
}
350350

351-
/* Read OV10640 ID to test communications. */
352-
ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR, OV490_SCCB_SLAVE_READ);
353-
ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH, OV10640_CHIP_ID >> 8);
354-
ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW, OV10640_CHIP_ID & 0xff);
355-
356-
/* Trigger SCCB slave transaction and give it some time to complete. */
357-
ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
358-
usleep_range(1000, 1500);
351+
static int ov10640_check_id(struct rdacm21_device *dev)
352+
{
353+
unsigned int i;
354+
u8 val;
359355

360-
ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
361-
if (val != OV10640_ID_HIGH) {
356+
/* Read OV10640 ID to test communications. */
357+
for (i = 0; i < OV10640_PID_TIMEOUT; ++i) {
358+
ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR,
359+
OV490_SCCB_SLAVE_READ);
360+
ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH,
361+
OV10640_CHIP_ID >> 8);
362+
ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW,
363+
OV10640_CHIP_ID & 0xff);
364+
365+
/*
366+
* Trigger SCCB slave transaction and give it some time
367+
* to complete.
368+
*/
369+
ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
370+
usleep_range(1000, 1500);
371+
372+
ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
373+
if (val == OV10640_ID_HIGH)
374+
break;
375+
usleep_range(1000, 1500);
376+
}
377+
if (i == OV10640_PID_TIMEOUT) {
362378
dev_err(dev->dev, "OV10640 ID mismatch: (0x%02x)\n", val);
363379
return -ENODEV;
364380
}
@@ -374,6 +390,8 @@ static int ov490_initialize(struct rdacm21_device *dev)
374390
unsigned int i;
375391
int ret;
376392

393+
ov10640_power_up(dev);
394+
377395
/*
378396
* Read OV490 Id to test communications. Give it up to 40msec to
379397
* exit from reset.
@@ -411,7 +429,7 @@ static int ov490_initialize(struct rdacm21_device *dev)
411429
return -ENODEV;
412430
}
413431

414-
ret = ov10640_initialize(dev);
432+
ret = ov10640_check_id(dev);
415433
if (ret)
416434
return ret;
417435

0 commit comments

Comments
 (0)