aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)
31 u32 v; 31 u32 v;
32 const u8 *ptr; 32 const u8 *ptr;
33 int i; 33 int i;
34 int retries = 0;
34 35
35 if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) { 36 if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
36 CX18_ERR("unable to open firmware %s\n", FWFILE); 37 CX18_ERR("unable to open firmware %s\n", FWFILE);
37 return -EINVAL; 38 return -EINVAL;
38 } 39 }
39 40
40 cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000); 41 /* The firmware load often has byte errors, so allow for several
41 cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */ 42 retries, both at byte level and at the firmware load level. */
42 43 while (retries < 5) {
43 /* Reset the Mako core (Register is undocumented.) */ 44 cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
44 cx18_av_write4(cx, 0x8100, 0x00010000); 45 cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
45 46
46 /* Put the 8051 in reset and enable firmware upload */ 47 /* Reset the Mako core (Register is undocumented.) */
47 cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000); 48 cx18_av_write4(cx, 0x8100, 0x00010000);
48 49
49 ptr = fw->data; 50 /* Put the 8051 in reset and enable firmware upload */
50 size = fw->size; 51 cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
51 52
52 for (i = 0; i < size; i++) { 53 ptr = fw->data;
53 u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16); 54 size = fw->size;
54 u32 value = 0; 55
55 int retries; 56 for (i = 0; i < size; i++) {
56 57 u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
57 for (retries = 0; retries < 5; retries++) { 58 u32 value = 0;
58 cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); 59 int retries;
59 value = cx18_av_read4(cx, CXADEC_DL_CTL); 60
60 if ((value & 0x3F00) == (dl_control & 0x3F00)) 61 for (retries = 0; retries < 5; retries++) {
62 cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
63 udelay(10);
64 value = cx18_av_read4(cx, CXADEC_DL_CTL);
65 if (value == dl_control)
66 break;
67 /* Check if we can correct the byte by changing
68 the address. We can only write the lower
69 address byte of the address. */
70 if ((value & 0x3F00) != (dl_control & 0x3F00)) {
71 retries = 5;
72 break;
73 }
74 }
75 if (retries >= 5)
61 break; 76 break;
62 } 77 }
63 if (retries >= 5) { 78 if (i == size)
64 CX18_ERR("unable to load firmware %s\n", FWFILE); 79 break;
65 release_firmware(fw); 80 retries++;
66 return -EIO; 81 }
67 } 82 if (retries >= 5) {
83 CX18_ERR("unable to load firmware %s\n", FWFILE);
84 release_firmware(fw);
85 return -EIO;
68 } 86 }
69 87
70 cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size); 88 cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);