diff options
author | Andy Walls <awalls@radix.net> | 2009-11-08 21:45:24 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:41:51 -0500 |
commit | 52fcb3ecc6707f52dfe4297f96b7609d4ba517fb (patch) | |
tree | fe8ecd66c20b10e8b2ba63c667a6afe78c23a2e1 /drivers/media/video/cx18/cx18-streams.c | |
parent | fa655dda5ce6e5ac4a9b94fd451358edca2ddab8 (diff) |
V4L/DVB (13429): cx18: Add Memory Descriptor List (MDL) layer to buffer handling
Add a Memory Descriptor List (MDL) layer to buffer handling to implement
scatter-gather I/O. Currently there is still only 1 buffer per MDL.
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-streams.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 10228c5ca5a0..9f8adda6f261 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) | |||
115 | s->dma = cx18_stream_info[type].dma; | 115 | s->dma = cx18_stream_info[type].dma; |
116 | s->buffers = cx->stream_buffers[type]; | 116 | s->buffers = cx->stream_buffers[type]; |
117 | s->buf_size = cx->stream_buf_size[type]; | 117 | s->buf_size = cx->stream_buf_size[type]; |
118 | INIT_LIST_HEAD(&s->buf_pool); | ||
119 | s->bufs_per_mdl = 1; | ||
120 | s->mdl_size = s->buf_size * s->bufs_per_mdl; | ||
118 | 121 | ||
119 | init_waitqueue_head(&s->waitq); | 122 | init_waitqueue_head(&s->waitq); |
120 | s->id = -1; | 123 | s->id = -1; |
@@ -124,6 +127,8 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
124 | cx18_queue_init(&s->q_busy); | 127 | cx18_queue_init(&s->q_busy); |
125 | spin_lock_init(&s->q_full.lock); | 128 | spin_lock_init(&s->q_full.lock); |
126 | cx18_queue_init(&s->q_full); | 129 | cx18_queue_init(&s->q_full); |
130 | spin_lock_init(&s->q_idle.lock); | ||
131 | cx18_queue_init(&s->q_idle); | ||
127 | 132 | ||
128 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); | 133 | INIT_WORK(&s->out_work_order, cx18_out_work_handler); |
129 | } | 134 | } |
@@ -441,8 +446,8 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
441 | } | 446 | } |
442 | 447 | ||
443 | static | 448 | static |
444 | struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, | 449 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, |
445 | struct cx18_buffer *buf) | 450 | struct cx18_mdl *mdl) |
446 | { | 451 | { |
447 | struct cx18 *cx = s->cx; | 452 | struct cx18 *cx = s->cx; |
448 | struct cx18_queue *q; | 453 | struct cx18_queue *q; |
@@ -451,16 +456,16 @@ struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s, | |||
451 | if (s->handle == CX18_INVALID_TASK_HANDLE || | 456 | if (s->handle == CX18_INVALID_TASK_HANDLE || |
452 | test_bit(CX18_F_S_STOPPING, &s->s_flags) || | 457 | test_bit(CX18_F_S_STOPPING, &s->s_flags) || |
453 | !test_bit(CX18_F_S_STREAMING, &s->s_flags)) | 458 | !test_bit(CX18_F_S_STREAMING, &s->s_flags)) |
454 | return cx18_enqueue(s, buf, &s->q_free); | 459 | return cx18_enqueue(s, mdl, &s->q_free); |
455 | 460 | ||
456 | q = cx18_enqueue(s, buf, &s->q_busy); | 461 | q = cx18_enqueue(s, mdl, &s->q_busy); |
457 | if (q != &s->q_busy) | 462 | if (q != &s->q_busy) |
458 | return q; /* The firmware has the max buffers it can handle */ | 463 | return q; /* The firmware has the max MDLs it can handle */ |
459 | 464 | ||
460 | cx18_buf_sync_for_device(s, buf); | 465 | cx18_mdl_sync_for_device(s, mdl); |
461 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 466 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
462 | (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 467 | (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem, |
463 | 1, buf->id, s->buf_size); | 468 | s->bufs_per_mdl, mdl->id, s->mdl_size); |
464 | return q; | 469 | return q; |
465 | } | 470 | } |
466 | 471 | ||
@@ -468,7 +473,7 @@ static | |||
468 | void _cx18_stream_load_fw_queue(struct cx18_stream *s) | 473 | void _cx18_stream_load_fw_queue(struct cx18_stream *s) |
469 | { | 474 | { |
470 | struct cx18_queue *q; | 475 | struct cx18_queue *q; |
471 | struct cx18_buffer *buf; | 476 | struct cx18_mdl *mdl; |
472 | 477 | ||
473 | if (atomic_read(&s->q_free.depth) == 0 || | 478 | if (atomic_read(&s->q_free.depth) == 0 || |
474 | atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM) | 479 | atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM) |
@@ -476,10 +481,10 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s) | |||
476 | 481 | ||
477 | /* Move from q_free to q_busy notifying the firmware, until the limit */ | 482 | /* Move from q_free to q_busy notifying the firmware, until the limit */ |
478 | do { | 483 | do { |
479 | buf = cx18_dequeue(s, &s->q_free); | 484 | mdl = cx18_dequeue(s, &s->q_free); |
480 | if (buf == NULL) | 485 | if (mdl == NULL) |
481 | break; | 486 | break; |
482 | q = _cx18_stream_put_buf_fw(s, buf); | 487 | q = _cx18_stream_put_mdl_fw(s, mdl); |
483 | } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM | 488 | } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM |
484 | && q == &s->q_busy); | 489 | && q == &s->q_busy); |
485 | } | 490 | } |
@@ -492,11 +497,21 @@ void cx18_out_work_handler(struct work_struct *work) | |||
492 | _cx18_stream_load_fw_queue(s); | 497 | _cx18_stream_load_fw_queue(s); |
493 | } | 498 | } |
494 | 499 | ||
500 | static void cx18_stream_configure_mdls(struct cx18_stream *s) | ||
501 | { | ||
502 | cx18_unload_queues(s); | ||
503 | |||
504 | /* For now */ | ||
505 | s->bufs_per_mdl = 1; | ||
506 | s->mdl_size = s->buf_size * s->bufs_per_mdl; | ||
507 | |||
508 | cx18_load_queues(s); | ||
509 | } | ||
510 | |||
495 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | 511 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) |
496 | { | 512 | { |
497 | u32 data[MAX_MB_ARGUMENTS]; | 513 | u32 data[MAX_MB_ARGUMENTS]; |
498 | struct cx18 *cx = s->cx; | 514 | struct cx18 *cx = s->cx; |
499 | struct cx18_buffer *buf; | ||
500 | int captype = 0; | 515 | int captype = 0; |
501 | struct cx18_api_func_private priv; | 516 | struct cx18_api_func_private priv; |
502 | 517 | ||
@@ -619,14 +634,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
619 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); | 634 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); |
620 | 635 | ||
621 | /* Init all the cpu_mdls for this stream */ | 636 | /* Init all the cpu_mdls for this stream */ |
622 | cx18_flush_queues(s); | 637 | cx18_stream_configure_mdls(s); |
623 | spin_lock(&s->q_free.lock); | ||
624 | list_for_each_entry(buf, &s->q_free.list, list) { | ||
625 | cx18_writel(cx, buf->dma_handle, | ||
626 | &cx->scb->cpu_mdl[buf->id].paddr); | ||
627 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | ||
628 | } | ||
629 | spin_unlock(&s->q_free.lock); | ||
630 | _cx18_stream_load_fw_queue(s); | 638 | _cx18_stream_load_fw_queue(s); |
631 | 639 | ||
632 | /* begin_capture */ | 640 | /* begin_capture */ |