summaryrefslogtreecommitdiff
path: root/drivers/media/video/cx18/cx18-av-firmware.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-06-28 15:03:02 +0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 14:15:13 +0400
commitf313da113fe083bfb1eb43377f551db4bbe702a6 (patch)
tree1123f88703a199dd879d29d9dcd94f3d1ee89592 /drivers/media/video/cx18/cx18-av-firmware.c
parentc3cb4d95ae778dbc6a4be1e74672d645fc75c8a7 (diff)
downloadlinux-f313da113fe083bfb1eb43377f551db4bbe702a6.tar.xz
V4L/DVB (8165): cx18: fix v4l-cx23418-dig.fw firmware load.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx18/cx18-av-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c70
1 files changed, 44 insertions, 26 deletions
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index a1a6af6c1c8f..ab86dc71bf8d 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -31,40 +31,58 @@ int cx18_av_loadfw(struct cx18 *cx)
u32 v;
const u8 *ptr;
int i;
+ int retries = 0;
if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
CX18_ERR("unable to open firmware %s\n", FWFILE);
return -EINVAL;
}
- cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
- cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */
-
- /* Reset the Mako core (Register is undocumented.) */
- cx18_av_write4(cx, 0x8100, 0x00010000);
-
- /* Put the 8051 in reset and enable firmware upload */
- cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
-
- ptr = fw->data;
- size = fw->size;
-
- for (i = 0; i < size; i++) {
- u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16);
- u32 value = 0;
- int retries;
-
- for (retries = 0; retries < 5; retries++) {
- cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
- value = cx18_av_read4(cx, CXADEC_DL_CTL);
- if ((value & 0x3F00) == (dl_control & 0x3F00))
+ /* The firmware load often has byte errors, so allow for several
+ retries, both at byte level and at the firmware load level. */
+ while (retries < 5) {
+ cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
+ cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
+
+ /* Reset the Mako core (Register is undocumented.) */
+ cx18_av_write4(cx, 0x8100, 0x00010000);
+
+ /* Put the 8051 in reset and enable firmware upload */
+ cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
+
+ ptr = fw->data;
+ size = fw->size;
+
+ for (i = 0; i < size; i++) {
+ u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
+ u32 value = 0;
+ int retries;
+
+ for (retries = 0; retries < 5; retries++) {
+ cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
+ udelay(10);
+ value = cx18_av_read4(cx, CXADEC_DL_CTL);
+ if (value == dl_control)
+ break;
+ /* Check if we can correct the byte by changing
+ the address. We can only write the lower
+ address byte of the address. */
+ if ((value & 0x3F00) != (dl_control & 0x3F00)) {
+ retries = 5;
+ break;
+ }
+ }
+ if (retries >= 5)
break;
}
- if (retries >= 5) {
- CX18_ERR("unable to load firmware %s\n", FWFILE);
- release_firmware(fw);
- return -EIO;
- }
+ if (i == size)
+ break;
+ retries++;
+ }
+ if (retries >= 5) {
+ CX18_ERR("unable to load firmware %s\n", FWFILE);
+ release_firmware(fw);
+ return -EIO;
}
cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);