summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-streams.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 19:50:49 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-09 19:50:49 -0800
commit3e7468313758913c5e4d372f35b271b96bad1298 (patch)
treeeb612d252a9e2349a1173451cd779beebd18a33e /drivers/media/video/cx18/cx18-streams.c
parent6825fbc4cb219f2c98bb7d157915d797cf5cb823 (diff)
parente97f4677961f68e29bd906022ebf60a6df7f530a (diff)
downloadop-kernel-dev-3e7468313758913c5e4d372f35b271b96bad1298.zip
op-kernel-dev-3e7468313758913c5e4d372f35b271b96bad1298.tar.gz
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (345 commits) V4L/DVB (13542): ir-keytable: Allow dynamic table change V4L/DVB (13541): atbm8830: replace 64-bit division and floating point usage V4L/DVB (13540): ir-common: Cleanup get key evdev code V4L/DVB (13539): ir-common: add __func__ for debug messages V4L/DVB (13538): ir-common: Use a dynamic keycode table V4L/DVB (13537): ir: Prepare the code for dynamic keycode table allocation V4L/DVB (13536): em28xx: Use the full RC5 code on HVR-950 Remote Controller V4L/DVB (13535): ir-common: Add a hauppauge new table with the complete RC5 code V4L/DVB (13534): ir-common: Remove some unused fields/structs V4L/DVB (13533): ir: use dynamic tables, instead of static ones V4L/DVB (13532): ir-common: Add infrastructure to use a dynamic keycode table V4L/DVB (13531): ir-common: rename the debug routine to allow exporting it V4L/DVB (13458): go7007: subdev conversion V4L/DVB (13457): s2250: subdev conversion V4L/DVB (13456): s2250: Change module structure V4L/DVB (13528): em28xx: add support for em2800 VC211A card em28xx: don't reduce scale to half size for em2800 em28xx: don't load audio modules when AC97 is mis-detected em28xx: em2800 chips support max width of 640 V4L/DVB (13523): dvb-bt8xx: fix compile warning ... Fix up trivial conflicts due to spelling fixes from the trivial tree in Documentation/video4linux/gspca.txt drivers/media/video/cx18/cx18-mailbox.h
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r--drivers/media/video/cx18/cx18-streams.c92
1 files changed, 66 insertions, 26 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 7df513a2..c398651 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -115,6 +115,9 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s->dma = cx18_stream_info[type].dma;
s->buffers = cx->stream_buffers[type];
s->buf_size = cx->stream_buf_size[type];
+ INIT_LIST_HEAD(&s->buf_pool);
+ s->bufs_per_mdl = 1;
+ s->mdl_size = s->buf_size * s->bufs_per_mdl;
init_waitqueue_head(&s->waitq);
s->id = -1;
@@ -124,6 +127,8 @@ static void cx18_stream_init(struct cx18 *cx, int type)
cx18_queue_init(&s->q_busy);
spin_lock_init(&s->q_full.lock);
cx18_queue_init(&s->q_full);
+ spin_lock_init(&s->q_idle.lock);
+ cx18_queue_init(&s->q_idle);
INIT_WORK(&s->out_work_order, cx18_out_work_handler);
}
@@ -257,9 +262,11 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
switch (vfl_type) {
case VFL_TYPE_GRABBER:
- CX18_INFO("Registered device video%d for %s (%d x %d kB)\n",
+ CX18_INFO("Registered device video%d for %s "
+ "(%d x %d.%02d kB)\n",
num, s->name, cx->stream_buffers[type],
- cx->stream_buf_size[type]/1024);
+ cx->stream_buf_size[type] / 1024,
+ (cx->stream_buf_size[type] * 100 / 1024) % 100);
break;
case VFL_TYPE_RADIO:
@@ -441,8 +448,8 @@ static void cx18_vbi_setup(struct cx18_stream *s)
}
static
-struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s,
- struct cx18_buffer *buf)
+struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,
+ struct cx18_mdl *mdl)
{
struct cx18 *cx = s->cx;
struct cx18_queue *q;
@@ -451,16 +458,16 @@ struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s,
if (s->handle == CX18_INVALID_TASK_HANDLE ||
test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
!test_bit(CX18_F_S_STREAMING, &s->s_flags))
- return cx18_enqueue(s, buf, &s->q_free);
+ return cx18_enqueue(s, mdl, &s->q_free);
- q = cx18_enqueue(s, buf, &s->q_busy);
+ q = cx18_enqueue(s, mdl, &s->q_busy);
if (q != &s->q_busy)
- return q; /* The firmware has the max buffers it can handle */
+ return q; /* The firmware has the max MDLs it can handle */
- cx18_buf_sync_for_device(s, buf);
+ cx18_mdl_sync_for_device(s, mdl);
cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
- (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
- 1, buf->id, s->buf_size);
+ (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem,
+ s->bufs_per_mdl, mdl->id, s->mdl_size);
return q;
}
@@ -468,19 +475,19 @@ static
void _cx18_stream_load_fw_queue(struct cx18_stream *s)
{
struct cx18_queue *q;
- struct cx18_buffer *buf;
+ struct cx18_mdl *mdl;
- if (atomic_read(&s->q_free.buffers) == 0 ||
- atomic_read(&s->q_busy.buffers) >= CX18_MAX_FW_MDLS_PER_STREAM)
+ if (atomic_read(&s->q_free.depth) == 0 ||
+ atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
return;
/* Move from q_free to q_busy notifying the firmware, until the limit */
do {
- buf = cx18_dequeue(s, &s->q_free);
- if (buf == NULL)
+ mdl = cx18_dequeue(s, &s->q_free);
+ if (mdl == NULL)
break;
- q = _cx18_stream_put_buf_fw(s, buf);
- } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM
+ q = _cx18_stream_put_mdl_fw(s, mdl);
+ } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM
&& q == &s->q_busy);
}
@@ -492,11 +499,51 @@ void cx18_out_work_handler(struct work_struct *work)
_cx18_stream_load_fw_queue(s);
}
+static void cx18_stream_configure_mdls(struct cx18_stream *s)
+{
+ cx18_unload_queues(s);
+
+ switch (s->type) {
+ case CX18_ENC_STREAM_TYPE_YUV:
+ /*
+ * Height should be a multiple of 32 lines.
+ * Set the MDL size to the exact size needed for one frame.
+ * Use enough buffers per MDL to cover the MDL size
+ */
+ s->mdl_size = 720 * s->cx->params.height * 3 / 2;
+ s->bufs_per_mdl = s->mdl_size / s->buf_size;
+ if (s->mdl_size % s->buf_size)
+ s->bufs_per_mdl++;
+ break;
+ case CX18_ENC_STREAM_TYPE_VBI:
+ s->bufs_per_mdl = 1;
+ if (cx18_raw_vbi(s->cx)) {
+ s->mdl_size = (s->cx->is_60hz ? 12 : 18)
+ * 2 * vbi_active_samples;
+ } else {
+ /*
+ * See comment in cx18_vbi_setup() below about the
+ * extra lines we capture in sliced VBI mode due to
+ * the lines on which EAV RP codes toggle.
+ */
+ s->mdl_size = s->cx->is_60hz
+ ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz
+ : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;
+ }
+ break;
+ default:
+ s->bufs_per_mdl = 1;
+ s->mdl_size = s->buf_size * s->bufs_per_mdl;
+ break;
+ }
+
+ cx18_load_queues(s);
+}
+
int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
{
u32 data[MAX_MB_ARGUMENTS];
struct cx18 *cx = s->cx;
- struct cx18_buffer *buf;
int captype = 0;
struct cx18_api_func_private priv;
@@ -619,14 +666,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
(void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
/* Init all the cpu_mdls for this stream */
- cx18_flush_queues(s);
- spin_lock(&s->q_free.lock);
- 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);
- }
- spin_unlock(&s->q_free.lock);
+ cx18_stream_configure_mdls(s);
_cx18_stream_load_fw_queue(s);
/* begin_capture */
OpenPOWER on IntegriCloud