Commit 1bd8e15a authored by Andy Walls's avatar Andy Walls Committed by Mauro Carvalho Chehab

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: default avatarAndy Walls <awalls@radix.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0c629252
...@@ -27,6 +27,48 @@ ...@@ -27,6 +27,48 @@
#define CX18_AUDIO_ENABLE 0xc72014 #define CX18_AUDIO_ENABLE 0xc72014
#define FWFILE "v4l-cx23418-dig.fw" #define FWFILE "v4l-cx23418-dig.fw"
static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
{
struct v4l2_subdev *sd = &cx->av_state.sd;
int ret = 0;
const u8 *data;
u32 size;
int addr;
u32 expected, dl_control;
/* Ensure we put the 8051 in reset and enable firmware upload mode */
dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
do {
dl_control &= 0x00ffffff;
dl_control |= 0x0f000000;
cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
} while ((dl_control & 0xff000000) != 0x0f000000);
/* Read and auto increment until at address 0x0000 */
while (dl_control & 0x3fff)
dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
data = fw->data;
size = fw->size;
for (addr = 0; addr < size; addr++) {
dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
if (expected != dl_control) {
CX18_ERR_DEV(sd, "verification of %s firmware load "
"failed: expected %#010x got %#010x\n",
FWFILE, expected, dl_control);
ret = -EIO;
break;
}
dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
}
if (ret == 0)
CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
FWFILE, size);
return ret;
}
int cx18_av_loadfw(struct cx18 *cx) int cx18_av_loadfw(struct cx18 *cx)
{ {
struct v4l2_subdev *sd = &cx->av_state.sd; struct v4l2_subdev *sd = &cx->av_state.sd;
...@@ -95,6 +137,12 @@ int cx18_av_loadfw(struct cx18 *cx) ...@@ -95,6 +137,12 @@ int cx18_av_loadfw(struct cx18 *cx)
} }
cx18_av_write4_expect(cx, CXADEC_DL_CTL, cx18_av_write4_expect(cx, CXADEC_DL_CTL,
0x03000000 | fw->size, 0x03000000, 0x13000000);
CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
if (cx18_av_verifyfw(cx, fw) == 0)
cx18_av_write4_expect(cx, CXADEC_DL_CTL,
0x13000000 | fw->size, 0x13000000, 0x13000000); 0x13000000 | fw->size, 0x13000000, 0x13000000);
/* Output to the 416 */ /* Output to the 416 */
...@@ -143,7 +191,5 @@ int cx18_av_loadfw(struct cx18 *cx) ...@@ -143,7 +191,5 @@ int cx18_av_loadfw(struct cx18 *cx)
cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF); cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
release_firmware(fw); release_firmware(fw);
CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment