diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-17 00:15:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-17 00:15:42 -0400 |
commit | 0dd5198672dd2bbeb933862e1fc82162e0b636be (patch) | |
tree | c9efed20d90603c4d1626c21bd7aab1e7fc74a58 /drivers/media/video/cx18/cx18-streams.c | |
parent | c868d550115b9ccc0027c67265b9520790f05601 (diff) | |
parent | 11c635a25b9f3a5d87409ce46cf2e05c500251ec (diff) |
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: (425 commits)
V4L/DVB (11870): gspca - main: VIDIOC_ENUM_FRAMESIZES ioctl added.
V4L/DVB (12004): poll method lose race condition
V4L/DVB (11894): flexcop-pci: dmesg visible names broken
V4L/DVB (11892): Siano: smsendian - declare function as extern
V4L/DVB (11891): Siano: smscore - bind the GPIO SMS protocol
V4L/DVB (11890): Siano: smscore - remove redundant code
V4L/DVB (11889): Siano: smsdvb - add DVB v3 events
V4L/DVB (11888): Siano: smsusb - remove redundant ifdef
V4L/DVB (11887): Siano: smscards - add board (target) events
V4L/DVB (11886): Siano: smscore - fix some new GPIO definitions names
V4L/DVB (11885): Siano: Add new GPIO management interface
V4L/DVB (11884): Siano: smssdio - revert to stand alone module
V4L/DVB (11883): Siano: cards - add two additional (USB) devices
V4L/DVB (11824): Siano: smsusb - change exit func debug msg
V4L/DVB (11823): Siano: smsusb - fix typo in module description
V4L/DVB (11822): Siano: smscore - bug fix at get_device_mode
V4L/DVB (11821): Siano: smscore - fix isdb-t firmware name
V4L/DVB (11820): Siano: smscore - fix byte ordering bug
V4L/DVB (11819): Siano: smscore - fix get_common_buffer bug
V4L/DVB (11818): Siano: smscards - assign gpio to HPG targets
...
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 44 |
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 | ||
127 | static int cx18_prep_dev(struct cx18 *cx, int type) | 131 | static 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 | ||
434 | struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, | 443 | static |
435 | struct cx18_buffer *buf) | 444 | struct 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 | ||
456 | void cx18_stream_load_fw_queue(struct cx18_stream *s) | 467 | static |
468 | void _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 | ||
487 | void 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 | |||
475 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | 495 | int 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; |