aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r--drivers/media/video/cx18/cx18-streams.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 0932b76b2373..54d248e16d85 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -116,12 +116,16 @@ static void cx18_stream_init(struct cx18 *cx, int type)
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 118
119 mutex_init(&s->qlock);
120 init_waitqueue_head(&s->waitq); 119 init_waitqueue_head(&s->waitq);
121 s->id = -1; 120 s->id = -1;
121 spin_lock_init(&s->q_free.lock);
122 cx18_queue_init(&s->q_free); 122 cx18_queue_init(&s->q_free);
123 spin_lock_init(&s->q_busy.lock);
123 cx18_queue_init(&s->q_busy); 124 cx18_queue_init(&s->q_busy);
125 spin_lock_init(&s->q_full.lock);
124 cx18_queue_init(&s->q_full); 126 cx18_queue_init(&s->q_full);
127
128 INIT_WORK(&s->out_work_order, cx18_out_work_handler);
125} 129}
126 130
127static int cx18_prep_dev(struct cx18 *cx, int type) 131static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -367,9 +371,14 @@ static void cx18_vbi_setup(struct cx18_stream *s)
367 * Tell the encoder to capture 21-4+1=18 lines per field, 371 * Tell the encoder to capture 21-4+1=18 lines per field,
368 * since we want lines 10 through 21. 372 * since we want lines 10 through 21.
369 * 373 *
370 * FIXME - revisit for 625/50 systems 374 * For 625/50 systems, according to the VIP 2 & BT.656 std:
375 * The EAV RP code's Field bit toggles on line 1, a few lines
376 * after the Vertcal Blank bit has already toggled.
377 * (We've actually set the digitizer so that the Field bit
378 * toggles on line 2.) Tell the encoder to capture 23-2+1=22
379 * lines per field, since we want lines 6 through 23.
371 */ 380 */
372 lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38; 381 lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2;
373 } 382 }
374 383
375 data[0] = s->handle; 384 data[0] = s->handle;
@@ -431,14 +440,16 @@ static void cx18_vbi_setup(struct cx18_stream *s)
431 cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); 440 cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
432} 441}
433 442
434struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, 443static
435 struct cx18_buffer *buf) 444struct cx18_queue *_cx18_stream_put_buf_fw(struct cx18_stream *s,
445 struct cx18_buffer *buf)
436{ 446{
437 struct cx18 *cx = s->cx; 447 struct cx18 *cx = s->cx;
438 struct cx18_queue *q; 448 struct cx18_queue *q;
439 449
440 /* Don't give it to the firmware, if we're not running a capture */ 450 /* Don't give it to the firmware, if we're not running a capture */
441 if (s->handle == CX18_INVALID_TASK_HANDLE || 451 if (s->handle == CX18_INVALID_TASK_HANDLE ||
452 test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
442 !test_bit(CX18_F_S_STREAMING, &s->s_flags)) 453 !test_bit(CX18_F_S_STREAMING, &s->s_flags))
443 return cx18_enqueue(s, buf, &s->q_free); 454 return cx18_enqueue(s, buf, &s->q_free);
444 455
@@ -453,7 +464,8 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
453 return q; 464 return q;
454} 465}
455 466
456void cx18_stream_load_fw_queue(struct cx18_stream *s) 467static
468void _cx18_stream_load_fw_queue(struct cx18_stream *s)
457{ 469{
458 struct cx18_queue *q; 470 struct cx18_queue *q;
459 struct cx18_buffer *buf; 471 struct cx18_buffer *buf;
@@ -467,11 +479,19 @@ void cx18_stream_load_fw_queue(struct cx18_stream *s)
467 buf = cx18_dequeue(s, &s->q_free); 479 buf = cx18_dequeue(s, &s->q_free);
468 if (buf == NULL) 480 if (buf == NULL)
469 break; 481 break;
470 q = cx18_stream_put_buf_fw(s, buf); 482 q = _cx18_stream_put_buf_fw(s, buf);
471 } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM 483 } while (atomic_read(&s->q_busy.buffers) < CX18_MAX_FW_MDLS_PER_STREAM
472 && q == &s->q_busy); 484 && q == &s->q_busy);
473} 485}
474 486
487void cx18_out_work_handler(struct work_struct *work)
488{
489 struct cx18_stream *s =
490 container_of(work, struct cx18_stream, out_work_order);
491
492 _cx18_stream_load_fw_queue(s);
493}
494
475int cx18_start_v4l2_encode_stream(struct cx18_stream *s) 495int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
476{ 496{
477 u32 data[MAX_MB_ARGUMENTS]; 497 u32 data[MAX_MB_ARGUMENTS];
@@ -600,19 +620,20 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
600 620
601 /* Init all the cpu_mdls for this stream */ 621 /* Init all the cpu_mdls for this stream */
602 cx18_flush_queues(s); 622 cx18_flush_queues(s);
603 mutex_lock(&s->qlock); 623 spin_lock(&s->q_free.lock);
604 list_for_each_entry(buf, &s->q_free.list, list) { 624 list_for_each_entry(buf, &s->q_free.list, list) {
605 cx18_writel(cx, buf->dma_handle, 625 cx18_writel(cx, buf->dma_handle,
606 &cx->scb->cpu_mdl[buf->id].paddr); 626 &cx->scb->cpu_mdl[buf->id].paddr);
607 cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); 627 cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
608 } 628 }
609 mutex_unlock(&s->qlock); 629 spin_unlock(&s->q_free.lock);
610 cx18_stream_load_fw_queue(s); 630 _cx18_stream_load_fw_queue(s);
611 631
612 /* begin_capture */ 632 /* begin_capture */
613 if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { 633 if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
614 CX18_DEBUG_WARN("Error starting capture!\n"); 634 CX18_DEBUG_WARN("Error starting capture!\n");
615 /* Ensure we're really not capturing before releasing MDLs */ 635 /* Ensure we're really not capturing before releasing MDLs */
636 set_bit(CX18_F_S_STOPPING, &s->s_flags);
616 if (s->type == CX18_ENC_STREAM_TYPE_MPG) 637 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
617 cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); 638 cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
618 else 639 else
@@ -622,6 +643,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
622 cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); 643 cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
623 cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); 644 cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
624 s->handle = CX18_INVALID_TASK_HANDLE; 645 s->handle = CX18_INVALID_TASK_HANDLE;
646 clear_bit(CX18_F_S_STOPPING, &s->s_flags);
625 if (atomic_read(&cx->tot_capturing) == 0) { 647 if (atomic_read(&cx->tot_capturing) == 0) {
626 set_bit(CX18_F_I_EOS, &cx->i_flags); 648 set_bit(CX18_F_I_EOS, &cx->i_flags);
627 cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); 649 cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
@@ -666,6 +688,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
666 if (atomic_read(&cx->tot_capturing) == 0) 688 if (atomic_read(&cx->tot_capturing) == 0)
667 return 0; 689 return 0;
668 690
691 set_bit(CX18_F_S_STOPPING, &s->s_flags);
669 if (s->type == CX18_ENC_STREAM_TYPE_MPG) 692 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
670 cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end); 693 cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
671 else 694 else
@@ -689,6 +712,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
689 712
690 cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); 713 cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
691 s->handle = CX18_INVALID_TASK_HANDLE; 714 s->handle = CX18_INVALID_TASK_HANDLE;
715 clear_bit(CX18_F_S_STOPPING, &s->s_flags);
692 716
693 if (atomic_read(&cx->tot_capturing) > 0) 717 if (atomic_read(&cx->tot_capturing) > 0)
694 return 0; 718 return 0;