aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-av-firmware.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2009-04-26 16:02:25 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-06-16 17:20:45 -0400
commit1bd8e15ac31f7f3d9f1ace70660330ba0055c69c (patch)
treebfef2a08bc311f44645e3deebcbabf06fb5c7846 /drivers/media/video/cx18/cx18-av-firmware.c
parent0c6292522968427d4f8e01f7c2e4216f04470072 (diff)
V4L/DVB (11623): cx18: Verify cx18-av-core digitizer firmware loads correctly
Add code to verify the cx18-av-core digitizer firmware loads correctly. The verification function reads back and compares the firmware bytes loaded into the A/V core. The result of the verification is only used to log a message in the system log. This change was prompted by users with multiple card setups that have problems with broadcast audio decoding the first time the cx18 module is loaded. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-av-firmware.c')
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index 49a55cc8d83..ab99030dc18 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -27,6 +27,48 @@
27#define CX18_AUDIO_ENABLE 0xc72014 27#define CX18_AUDIO_ENABLE 0xc72014
28#define FWFILE "v4l-cx23418-dig.fw" 28#define FWFILE "v4l-cx23418-dig.fw"
29 29
30static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
31{
32 struct v4l2_subdev *sd = &cx->av_state.sd;
33 int ret = 0;
34 const u8 *data;
35 u32 size;
36 int addr;
37 u32 expected, dl_control;
38
39 /* Ensure we put the 8051 in reset and enable firmware upload mode */
40 dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
41 do {
42 dl_control &= 0x00ffffff;
43 dl_control |= 0x0f000000;
44 cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
45 dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
46 } while ((dl_control & 0xff000000) != 0x0f000000);
47
48 /* Read and auto increment until at address 0x0000 */
49 while (dl_control & 0x3fff)
50 dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
51
52 data = fw->data;
53 size = fw->size;
54 for (addr = 0; addr < size; addr++) {
55 dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
56 expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
57 if (expected != dl_control) {
58 CX18_ERR_DEV(sd, "verification of %s firmware load "
59 "failed: expected %#010x got %#010x\n",
60 FWFILE, expected, dl_control);
61 ret = -EIO;
62 break;
63 }
64 dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
65 }
66 if (ret == 0)
67 CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
68 FWFILE, size);
69 return ret;
70}
71
30int cx18_av_loadfw(struct cx18 *cx) 72int cx18_av_loadfw(struct cx18 *cx)
31{ 73{
32 struct v4l2_subdev *sd = &cx->av_state.sd; 74 struct v4l2_subdev *sd = &cx->av_state.sd;
@@ -95,6 +137,12 @@ int cx18_av_loadfw(struct cx18 *cx)
95 } 137 }
96 138
97 cx18_av_write4_expect(cx, CXADEC_DL_CTL, 139 cx18_av_write4_expect(cx, CXADEC_DL_CTL,
140 0x03000000 | fw->size, 0x03000000, 0x13000000);
141
142 CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
143
144 if (cx18_av_verifyfw(cx, fw) == 0)
145 cx18_av_write4_expect(cx, CXADEC_DL_CTL,
98 0x13000000 | fw->size, 0x13000000, 0x13000000); 146 0x13000000 | fw->size, 0x13000000, 0x13000000);
99 147
100 /* Output to the 416 */ 148 /* Output to the 416 */
@@ -143,7 +191,5 @@ int cx18_av_loadfw(struct cx18 *cx)
143 cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF); 191 cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
144 192
145 release_firmware(fw); 193 release_firmware(fw);
146
147 CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
148 return 0; 194 return 0;
149} 195}