From d06ed8475f6edc68d8aee44a9e8c9cf0e87e29ef Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 16:52:12 -0500 Subject: cx18 Replace magic number 63 with CX18_MAX_FW_MDLS_PER_STREAM From: Andy Walls Removed magic number that referred to firmware limit on the number of MDLs the firmware can maintain for any stream at any one time. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 5 +++-- linux/drivers/media/video/cx18/cx18-queue.c | 5 +++-- linux/drivers/media/video/cx18/cx18-streams.c | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 018d98f94..0d2edebc3 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -116,7 +116,7 @@ #define CX18_DEFAULT_ENC_PCM_BUFFERS 1 /* Maximum firmware DMA buffers per stream */ -#define CX18_MAX_MDLS_PER_STREAM 63 +#define CX18_MAX_FW_MDLS_PER_STREAM 63 /* DMA buffer, default size in kB allocated */ #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 @@ -255,7 +255,8 @@ struct cx18_scb; /* forward reference */ #define CX18_MAX_MDL_ACKS 2 -#define CX18_MAX_EPU_WORK_ORDERS 70 /* CPU_DE_RELEASE_MDL bursts 63 commands */ +#define CX18_MAX_EPU_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7) +/* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */ #define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1 #define CX18_F_EWO_MB_STALE_WHILE_PROC 0x2 diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index a6b0666f0..2c58b0c47 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -55,8 +55,9 @@ struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, mutex_lock(&s->qlock); - /* q_busy is restricted to 63 buffers to stay within firmware limits */ - if (q == &s->q_busy && atomic_read(&q->buffers) >= 63) + /* q_busy is restricted to a max buffer count imposed by firmware */ + if (q == &s->q_busy && + atomic_read(&q->buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) q = &s->q_free; if (to_front) diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 9ed542624..acaf774d8 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -425,7 +425,7 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s) struct cx18_buffer *buf; if (atomic_read(&s->q_free.buffers) == 0 || - atomic_read(&s->q_busy.buffers) >= 63) + atomic_read(&s->q_busy.buffers) >= CX18_MAX_FW_MDLS_PER_STREAM) return; /* Move from q_free to q_busy notifying the firmware, until the limit */ @@ -434,7 +434,8 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s) if (buf == NULL) break; q = cx18_stream_put_buf_fw(s, buf); - } while (atomic_read(&s->q_busy.buffers) < 63 && q == &s->q_busy); + } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM + && q == &s->q_busy); } int cx18_start_v4l2_encode_stream(struct cx18_stream *s) -- cgit v1.2.3 From 33d2dd93cb9c5d52dfee61dcd037b3dc290ada81 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 17:21:35 -0500 Subject: cx18: VBI comment corrections and comments about VBI issues From: Andy Walls VBI comment corrections to avoid future confusion about standards. Comments on cx18 VBI implementation shortcomings that need resolution. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index cea4735b6..f2a5b2c4d 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -614,18 +614,21 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line * length of 720 pixels @ 4:2:2 sampling. Thus... * - * For NTSC: + * For systems that use a 15.734 kHz horizontal rate, such as + * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: * - * (1/15,734 kHz) * 2 * 13.5 MHz = 1716 samples/line = + * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples * - * For PAL: + * For systems that use a 15.625 kHz horizontal rate, such as + * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: * - * (1/15,625 kHz) * 2 * 13.5 MHz = 1728 samples/line = + * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples * */ + /* FIXME: init these based on tuner std & modify when std changes */ /* CX18-AV-Core number of VBI samples output per horizontal line */ cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */ cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */ @@ -929,6 +932,11 @@ static int __devinit cx18_probe(struct pci_dev *dev, } cx->params.video_gop_size = cx->is_60hz ? 15 : 12; + /* + * FIXME: setting the buffer size based on the tuner standard is + * suboptimal, as the CVBS and SVideo inputs could use a different std + * and the buffer could end up being too small in that case. + */ vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; -- cgit v1.2.3 From 75db59d39a9a9df4b32e034d483c126aed873c1a Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 19:05:36 -0500 Subject: cx18: Convert some list manipulations to emphasize entries not lists From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-queue.c | 14 ++++++-------- linux/drivers/media/video/cx18/cx18-streams.c | 4 +--- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-queue.c b/linux/drivers/media/video/cx18/cx18-queue.c index 2c58b0c47..8d9441e88 100644 --- a/linux/drivers/media/video/cx18/cx18-queue.c +++ b/linux/drivers/media/video/cx18/cx18-queue.c @@ -77,8 +77,8 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) mutex_lock(&s->qlock); if (!list_empty(&q->list)) { - buf = list_entry(q->list.next, struct cx18_buffer, list); - list_del_init(q->list.next); + buf = list_first_entry(&q->list, struct cx18_buffer, list); + list_del_init(&buf->list); q->bytesused -= buf->bytesused - buf->readpos; buf->skipped = 0; atomic_dec(&q->buffers); @@ -92,13 +92,11 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, { struct cx18 *cx = s->cx; struct cx18_buffer *buf; + struct cx18_buffer *tmp; struct cx18_buffer *ret = NULL; - struct list_head *p, *t; mutex_lock(&s->qlock); - list_for_each_safe(p, t, &s->q_busy.list) { - buf = list_entry(p, struct cx18_buffer, list); - + list_for_each_entry_safe(buf, tmp, &s->q_busy.list, list) { if (buf->id != id) { buf->skipped++; if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { @@ -152,8 +150,8 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) mutex_lock(&s->qlock); while (!list_empty(&q->list)) { - buf = list_entry(q->list.next, struct cx18_buffer, list); - list_move_tail(q->list.next, &s->q_free.list); + buf = list_first_entry(&q->list, struct cx18_buffer, list); + list_move_tail(&buf->list, &s->q_free.list); buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; atomic_inc(&s->q_free.buffers); } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index acaf774d8..5acefd059 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -442,7 +442,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) { u32 data[MAX_MB_ARGUMENTS]; struct cx18 *cx = s->cx; - struct list_head *p; struct cx18_buffer *buf; int ts = 0; int captype = 0; @@ -529,8 +528,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* Init all the cpu_mdls for this stream */ cx18_flush_queues(s); mutex_lock(&s->qlock); - list_for_each(p, &s->q_free.list) { - buf = list_entry(p, struct cx18_buffer, list); + list_for_each_entry(buf, &s->q_free.list, list) { cx18_writel(cx, buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); -- cgit v1.2.3 From 4a31b6de97b5e45eaff001a1e7a813964660f436 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 23 Nov 2008 17:16:44 -0500 Subject: cx18: Use a known open task handle when setting stream CX2341x parameters From: Andy Walls cx18: Use a known open task handle when setting stream CX2341x parameters Sometimes, we might only have VBI or YUV stream open instead of an MPEG stream. Let's make sure we use a valid task handle to perform the CX2341x control settings. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-controls.c | 5 ++++- linux/drivers/media/video/cx18/cx18-mailbox.c | 5 +++-- linux/drivers/media/video/cx18/cx18-mailbox.h | 7 +++++++ linux/drivers/media/video/cx18/cx18-streams.c | 6 +++++- 4 files changed, 19 insertions(+), 4 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index f46c7e5ed..17edf305d 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -259,6 +259,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) return err; } if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { + struct cx18_api_func_private priv; struct cx2341x_mpeg_params p = cx->params; int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), c, VIDIOC_S_EXT_CTRLS); @@ -278,7 +279,9 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) fmt.fmt.pix.height = cx->params.height; cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt); } - err = cx2341x_update(cx, cx18_api_func, &cx->params, &p); + priv.cx = cx; + priv.s = &cx->streams[id->type]; + err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p); if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt) err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt); cx->params = p; diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index eb5c31af6..f20fbf091 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -612,8 +612,9 @@ static int cx18_set_filter_param(struct cx18_stream *s) int cx18_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) { - struct cx18 *cx = priv; - struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; + struct cx18_api_func_private *api_priv = priv; + struct cx18 *cx = api_priv->cx; + struct cx18_stream *s = api_priv->s; switch (cmd) { case CX2341X_ENC_SET_OUTPUT_PORT: diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.h b/linux/drivers/media/video/cx18/cx18-mailbox.h index 35104458e..a667f1ae4 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.h +++ b/linux/drivers/media/video/cx18/cx18-mailbox.h @@ -79,6 +79,13 @@ struct cx18_mailbox { u32 error; }; +struct cx18_stream; + +struct cx18_api_func_private { + struct cx18 *cx; + struct cx18_stream *s; +}; + int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]); int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd, int args, ...); diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 5acefd059..f9e44c0cf 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -494,6 +494,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); if (atomic_read(&cx->ana_capturing) == 0 && !ts) { + struct cx18_api_func_private priv; + /* Stuff from Windows, we don't know what it is */ cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); @@ -513,7 +515,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); /* Setup API for Stream */ - cx2341x_update(cx, cx18_api_func, NULL, &cx->params); + priv.cx = cx; + priv.s = s; + cx2341x_update(&priv, cx18_api_func, NULL, &cx->params); } if (atomic_read(&cx->tot_capturing) == 0) { -- cgit v1.2.3 From c8e6336414973fe34750afe8327988ddab7d1a58 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 14 Dec 2008 12:59:55 +0100 Subject: Minor fixes for cx24113-driver (codingstyle) From: Patrick Boettcher Fixed some minor coding style issues and some driver information printed when using the driver on a board. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 70 ++++++++++++++++------------- 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index e2e5df9de..8850f2303 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -50,46 +50,46 @@ struct cx24113_state { u8 rev; u8 ver; - u8 icp_mode:1; + u8 icp_mode:1; #define ICP_LEVEL1 0 #define ICP_LEVEL2 1 #define ICP_LEVEL3 2 #define ICP_LEVEL4 3 - u8 icp_man:2; - u8 icp_auto_low:2; - u8 icp_auto_mlow:2; - u8 icp_auto_mhi:2; - u8 icp_auto_hi:2; - u8 icp_dig; + u8 icp_man:2; + u8 icp_auto_low:2; + u8 icp_auto_mlow:2; + u8 icp_auto_mhi:2; + u8 icp_auto_hi:2; + u8 icp_dig; #define LNA_MIN_GAIN 0 #define LNA_MID_GAIN 1 #define LNA_MAX_GAIN 2 - u8 lna_gain:2; + u8 lna_gain:2; - u8 acp_on:1; + u8 acp_on:1; - u8 vco_mode:2; - u8 vco_shift:1; + u8 vco_mode:2; + u8 vco_shift:1; #define VCOBANDSEL_6 0x80 #define VCOBANDSEL_5 0x01 #define VCOBANDSEL_4 0x02 #define VCOBANDSEL_3 0x04 #define VCOBANDSEL_2 0x08 #define VCOBANDSEL_1 0x10 - u8 vco_band; + u8 vco_band; #define VCODIV4 4 #define VCODIV2 2 u8 vcodiv; - u8 bs_delay:4; - u16 bs_freqcnt:13; - u16 bs_rdiv; - u8 prescaler_mode:1; + u8 bs_delay:4; + u16 bs_freqcnt:13; + u16 bs_rdiv; + u8 prescaler_mode:1; - u8 rfvga_bias_ctrl; + u8 rfvga_bias_ctrl; s16 tuner_gain_thres; u8 gain_level; @@ -345,12 +345,12 @@ static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f) } F = freq_hz; F *= (u64) (R * vcodiv * 262144); - dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("1 N: %d, F: %lld, R: %d\n", N, F, R); do_div(F, state->config->xtal_khz*1000 * factor * 2); - dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("2 N: %d, F: %lld, R: %d\n", N, F, R); F -= (N + 32) * 262144; - dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); + dprintk("3 N: %d, F: %lld, R: %d\n", N, F, R); if (state->Fwindow_enabled) { if (F > (262144 / 2 - 1638)) @@ -392,21 +392,21 @@ static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency) u16 n = 6; s32 f = 0; - r = cx24113_readreg(state, 0x14); + r = cx24113_readreg(state, 0x14); cx24113_writereg(state, 0x14, r & 0x3f); - r = cx24113_readreg(state, 0x10); - cx24113_writereg(state, 0x10, r & 0xbf); + r = cx24113_readreg(state, 0x10); + cx24113_writereg(state, 0x10, r & 0xbf); state->frequency = frequency; dprintk("tuning to frequency: %d\n", frequency); - cx24113_calc_pll_nf(state, &n, &f); - cx24113_set_nfr(state, n, f, state->refdiv); + cx24113_calc_pll_nf(state, &n, &f); + cx24113_set_nfr(state, n, f, state->refdiv); r = cx24113_readreg(state, 0x18) & 0xbf; - if (state->vcodiv != VCODIV2) + if (state->vcodiv != VCODIV2) r |= 1 << 6; cx24113_writereg(state, 0x18, r); @@ -527,7 +527,7 @@ static int cx24113_release(struct dvb_frontend *fe) { struct cx24113_state *state = fe->tuner_priv; dprintk("\n"); - fe->tuner_priv = NULL; + fe->tuner_priv = NULL; kfree(state); return 0; } @@ -557,6 +557,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, /* allocate memory for the internal state */ struct cx24113_state *state = kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); + int rc; if (state == NULL) { err("Unable to kmalloc\n"); goto error; @@ -572,15 +573,22 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, * after power on */ cx24113_readreg(state, 0x00); - switch (state->rev = cx24113_readreg(state, 0x00)) { + rc = cx24113_readreg(state, 0x00); + if (rc < 0) { + info("cx24113 not found.\n"); + goto error; + } + state->rev = rc; + + switch (rc) { case 0x43: - info("unknown device\n"); + info("detected Cx24113 variant\n"); break; case REV_CX24113: - info("CX24113\n"); + info("sucessfully detected\n"); break; default: - err("unsupported revision: %x\n", state->rev); + err("unsupported device id: %x\n", state->rev); goto error; } state->ver = cx24113_readreg(state, 0x01); -- cgit v1.2.3 From 89634f12bf2fabd82e3043863cc01da40ec3bfc4 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 14 Dec 2008 13:11:53 +0100 Subject: Patch: fix a typo in cx24113.c From: Uwe Bugla This patch fixes a typo in cx24113.c. Priority: normal Signed-off-by: Uwe Bugla Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index 8850f2303..e130b228e 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -1,5 +1,5 @@ /* - * Driver for Conexant CX24113/CX24128 Tuner (Satelite) + * Driver for Conexant CX24113/CX24128 Tuner (Satellite) * * Copyright (C) 2007-8 Patrick Boettcher * -- cgit v1.2.3 From 3bef875602189a42ca85a89ace6fc225d739512c Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 14 Dec 2008 15:56:28 +0100 Subject: CX24113: Fixed more typos From: Patrick Boettcher Uwe Bugla pointed out that there are some more typos in some print-statements. Fixed. Priority: normal Signed-off-by: Patrick Boettcher --- linux/drivers/media/dvb/frontends/cx24113.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/dvb/frontends/cx24113.c b/linux/drivers/media/dvb/frontends/cx24113.c index e130b228e..93f35941a 100644 --- a/linux/drivers/media/dvb/frontends/cx24113.c +++ b/linux/drivers/media/dvb/frontends/cx24113.c @@ -575,14 +575,14 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe, rc = cx24113_readreg(state, 0x00); if (rc < 0) { - info("cx24113 not found.\n"); + info("CX24113 not found.\n"); goto error; } state->rev = rc; switch (rc) { case 0x43: - info("detected Cx24113 variant\n"); + info("detected CX24113 variant\n"); break; case REV_CX24113: info("sucessfully detected\n"); -- cgit v1.2.3 From 75cb6237407f2d533da57987203cfc43c221e380 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 14 Dec 2008 19:26:25 -0500 Subject: cx18: Refine the firmware load and firmware startup process From: Andy Walls Refine the firmware load and firmware startup process. Significant changes are to ensure the SCB and IPC area are correct before starting up the firmware, and letting the CPU firmware start up the APU firmware for us. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 1 + linux/drivers/media/video/cx18/cx18-firmware.c | 101 +++++++++++++------------ linux/drivers/media/video/cx18/cx18-mailbox.c | 3 +- linux/drivers/media/video/cx18/cx18-scb.c | 1 - linux/drivers/media/video/cx18/cx23418.h | 6 ++ 5 files changed, 60 insertions(+), 52 deletions(-) (limited to 'linux/drivers') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index f2a5b2c4d..e447b4ce7 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -883,6 +883,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, goto free_i2c; } cx18_init_memory(cx); + cx18_init_scb(cx); /* Register IRQ */ retval = request_irq(cx->dev->irq, cx18_irq_handler, diff --git a/linux/drivers/media/video/cx18/cx18-firmware.c b/linux/drivers/media/video/cx18/cx18-firmware.c index 8eac84314..e74f76d47 100644 --- a/linux/drivers/media/video/cx18/cx18-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-firmware.c @@ -332,6 +332,10 @@ void cx18_init_memory(struct cx18 *cx) int cx18_firmware_init(struct cx18 *cx) { + u32 fw_entry_addr; + int sz, retries; + u32 api_args[MAX_MB_ARGUMENTS]; + /* Allow chip to control CLKRUN */ cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK); @@ -341,65 +345,62 @@ int cx18_firmware_init(struct cx18 *cx) cx18_msleep_timeout(1, 0); + /* If the CPU is still running */ + if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) { + CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__); + return -EIO; + } + cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU); cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); - /* Only if the processor is not running */ - if (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) { - u32 fw_entry_addr = 0; - int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", - cx->enc_mem, cx, &fw_entry_addr); - - if (sz <= 0) - return sz; - - /* Clear bit0 for APU to start from 0 */ - cx18_write_reg(cx, cx18_read_reg(cx, 0xc72030) & ~1, 0xc72030); - - cx18_write_enc(cx, 0xE51FF004, 0); /* ldr pc, [pc, #-4] */ - cx18_write_enc(cx, fw_entry_addr, 4); - - /* Start APU */ - cx18_write_reg_expect(cx, 0x00010000, CX18_PROC_SOFT_RESET, - 0x00000000, 0x00010001); - cx18_msleep_timeout(500, 0); - - sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", - cx->enc_mem, cx); - - if (sz > 0) { - int retries = 0; - - /* start the CPU */ - cx18_write_reg_expect(cx, - 0x00080000, CX18_PROC_SOFT_RESET, - 0x00000000, 0x00080008); - while (retries++ < 50) { /* Loop for max 500mS */ - if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) - & 1) == 0) - break; - cx18_msleep_timeout(10, 0); - } - cx18_msleep_timeout(200, 0); - if (retries == 51) { - CX18_ERR("Could not start the CPU\n"); - return -EIO; - } - } - if (sz <= 0) - return -EIO; + sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx); + if (sz <= 0) + return sz; + + /* The SCB & IPC area *must* be correct before starting the firmwares */ + cx18_init_scb(cx); + + fw_entry_addr = 0; + sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx, + &fw_entry_addr); + if (sz <= 0) + return sz; + + /* Start the CPU. The CPU will take care of the APU for us. */ + cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET, + 0x00000000, 0x00080008); + + /* Wait up to 500 ms for the APU to come out of reset */ + for (retries = 0; + retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1; + retries++) + cx18_msleep_timeout(10, 0); + + cx18_msleep_timeout(200, 0); + + if (retries == 50 && + (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) { + CX18_ERR("Could not start the CPU\n"); + return -EIO; } /* - * The CPU firmware apparently sets up to receive an interrupt for it's - * outgoing IRQ_CPU_TO_EPU_ACK to us (*boggle*). We get an interrupt - * when it sends us an ack, but by the time we process it, that flag in - * the SW2 status register has been cleared by the CPU firmware. - * We'll prevent that not so useful behavior by clearing the CPU's - * interrupt enables for Ack IRQ's we want to process. + * The CPU had once before set up to receive an interrupt for it's + * outgoing IRQ_CPU_TO_EPU_ACK to us. If it ever does this, we get an + * interrupt when it sends us an ack, but by the time we process it, + * that flag in the SW2 status register has been cleared by the CPU + * firmware. We'll prevent that not so useful condition from happening + * by clearing the CPU's interrupt enables for Ack IRQ's we want to + * process. */ cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK); + /* Try a benign command to see if the CPU is alive and well */ + sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0); + if (sz < 0) + return sz; + /* initialize GPIO */ cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400); return 0; diff --git a/linux/drivers/media/video/cx18/cx18-mailbox.c b/linux/drivers/media/video/cx18/cx18-mailbox.c index f20fbf091..89a45f51f 100644 --- a/linux/drivers/media/video/cx18/cx18-mailbox.c +++ b/linux/drivers/media/video/cx18/cx18-mailbox.c @@ -82,8 +82,9 @@ static const struct cx18_api_info api_info[] = { API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), - API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), + API_ENTRY(APU, CX18_APU_RESETAI, 0), + API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32, 0), API_ENTRY(0, 0, 0), }; diff --git a/linux/drivers/media/video/cx18/cx18-scb.c b/linux/drivers/media/video/cx18/cx18-scb.c index ac18bd932..34b4d03c5 100644 --- a/linux/drivers/media/video/cx18/cx18-scb.c +++ b/linux/drivers/media/video/cx18/cx18-scb.c @@ -118,6 +118,5 @@ void cx18_init_scb(struct cx18 *cx) cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state), &cx->scb->ipc_offset); - cx18_writel(cx, 1, &cx->scb->hpu_state); cx18_writel(cx, 1, &cx->scb->epu_state); } diff --git a/linux/drivers/media/video/cx18/cx23418.h b/linux/drivers/media/video/cx18/cx23418.h index 668f968d7..601f3a2ab 100644 --- a/linux/drivers/media/video/cx18/cx23418.h +++ b/linux/drivers/media/video/cx18/cx23418.h @@ -44,6 +44,7 @@ /* All commands for CPU have the following mask set */ #define CPU_CMD_MASK 0x20000000 +#define CPU_CMD_MASK_DEBUG (CPU_CMD_MASK | 0x00000000) #define CPU_CMD_MASK_ACK (CPU_CMD_MASK | 0x80000000) #define CPU_CMD_MASK_CAPTURE (CPU_CMD_MASK | 0x00020000) #define CPU_CMD_MASK_TS (CPU_CMD_MASK | 0x00040000) @@ -71,6 +72,11 @@ 0/zero/NULL means "I have nothing to say" */ #define CX18_EPU_DEBUG (EPU_CMD_MASK_DEBUG | 0x0003) +/* Reads memory/registers (32-bit) + IN[0] - Address + OUT[1] - Value */ +#define CX18_CPU_DEBUG_PEEK32 (CPU_CMD_MASK_DEBUG | 0x0003) + /* Description: This command starts streaming with the set channel type IN[0] - Task handle. Handle of the task to start ReturnCode - One of the ERR_CAPTURE_... */ -- cgit v1.2.3