diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 987a9308d938..054450f65a60 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -319,11 +319,27 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) | |||
319 | 319 | ||
320 | /* Teardown all streams */ | 320 | /* Teardown all streams */ |
321 | for (type = 0; type < CX18_MAX_STREAMS; type++) { | 321 | for (type = 0; type < CX18_MAX_STREAMS; type++) { |
322 | if (cx->streams[type].dvb.enabled) { | 322 | |
323 | cx18_dvb_unregister(&cx->streams[type]); | 323 | /* No struct video_device, but can have buffers allocated */ |
324 | cx->streams[type].dvb.enabled = false; | 324 | if (type == CX18_ENC_STREAM_TYPE_TS) { |
325 | if (cx->streams[type].dvb.enabled) { | ||
326 | cx18_dvb_unregister(&cx->streams[type]); | ||
327 | cx->streams[type].dvb.enabled = false; | ||
328 | cx18_stream_free(&cx->streams[type]); | ||
329 | } | ||
330 | continue; | ||
331 | } | ||
332 | |||
333 | /* No struct video_device, but can have buffers allocated */ | ||
334 | if (type == CX18_ENC_STREAM_TYPE_IDX) { | ||
335 | if (cx->stream_buffers[type] != 0) { | ||
336 | cx->stream_buffers[type] = 0; | ||
337 | cx18_stream_free(&cx->streams[type]); | ||
338 | } | ||
339 | continue; | ||
325 | } | 340 | } |
326 | 341 | ||
342 | /* If struct video_device exists, can have buffers allocated */ | ||
327 | vdev = cx->streams[type].video_dev; | 343 | vdev = cx->streams[type].video_dev; |
328 | 344 | ||
329 | cx->streams[type].video_dev = NULL; | 345 | cx->streams[type].video_dev = NULL; |
@@ -447,6 +463,32 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
447 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); | 463 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); |
448 | } | 464 | } |
449 | 465 | ||
466 | void cx18_stream_rotate_idx_mdls(struct cx18 *cx) | ||
467 | { | ||
468 | struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
469 | struct cx18_mdl *mdl; | ||
470 | |||
471 | if (!cx18_stream_enabled(s)) | ||
472 | return; | ||
473 | |||
474 | /* Return if the firmware is not running low on MDLs */ | ||
475 | if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >= | ||
476 | CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN) | ||
477 | return; | ||
478 | |||
479 | /* Return if there are no MDLs to rotate back to the firmware */ | ||
480 | if (atomic_read(&s->q_full.depth) < 2) | ||
481 | return; | ||
482 | |||
483 | /* | ||
484 | * Take the oldest IDX MDL still holding data, and discard its index | ||
485 | * entries by scheduling the MDL to go back to the firmware | ||
486 | */ | ||
487 | mdl = cx18_dequeue(s, &s->q_full); | ||
488 | if (mdl != NULL) | ||
489 | cx18_enqueue(s, mdl, &s->q_free); | ||
490 | } | ||
491 | |||
450 | static | 492 | static |
451 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, | 493 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, |
452 | struct cx18_mdl *mdl) | 494 | struct cx18_mdl *mdl) |
@@ -546,8 +588,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
546 | struct cx18 *cx = s->cx; | 588 | struct cx18 *cx = s->cx; |
547 | int captype = 0; | 589 | int captype = 0; |
548 | struct cx18_api_func_private priv; | 590 | struct cx18_api_func_private priv; |
591 | struct cx18_stream *s_idx; | ||
549 | 592 | ||
550 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 593 | if (!cx18_stream_enabled(s)) |
551 | return -EINVAL; | 594 | return -EINVAL; |
552 | 595 | ||
553 | CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); | 596 | CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); |
@@ -561,6 +604,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
561 | cx->search_pack_header = 0; | 604 | cx->search_pack_header = 0; |
562 | break; | 605 | break; |
563 | 606 | ||
607 | case CX18_ENC_STREAM_TYPE_IDX: | ||
608 | captype = CAPTURE_CHANNEL_TYPE_INDEX; | ||
609 | break; | ||
564 | case CX18_ENC_STREAM_TYPE_TS: | 610 | case CX18_ENC_STREAM_TYPE_TS: |
565 | captype = CAPTURE_CHANNEL_TYPE_TS; | 611 | captype = CAPTURE_CHANNEL_TYPE_TS; |
566 | break; | 612 | break; |
@@ -635,11 +681,13 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
635 | cx18_vbi_setup(s); | 681 | cx18_vbi_setup(s); |
636 | 682 | ||
637 | /* | 683 | /* |
638 | * assign program index info. | 684 | * Select to receive I, P, and B frame index entries, if the |
639 | * Mask 7: select I/P/B, Num_req: 400 max | 685 | * index stream is enabled. Otherwise disable index entry |
640 | * FIXME - currently we have this hardcoded as disabled | 686 | * generation. |
641 | */ | 687 | */ |
642 | cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); | 688 | s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
689 | cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2, | ||
690 | s->handle, cx18_stream_enabled(s_idx) ? 7 : 0); | ||
643 | 691 | ||
644 | /* Call out to the common CX2341x API setup for user controls */ | 692 | /* Call out to the common CX2341x API setup for user controls */ |
645 | priv.cx = cx; | 693 | priv.cx = cx; |
@@ -697,6 +745,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
697 | atomic_inc(&cx->tot_capturing); | 745 | atomic_inc(&cx->tot_capturing); |
698 | return 0; | 746 | return 0; |
699 | } | 747 | } |
748 | EXPORT_SYMBOL(cx18_start_v4l2_encode_stream); | ||
700 | 749 | ||
701 | void cx18_stop_all_captures(struct cx18 *cx) | 750 | void cx18_stop_all_captures(struct cx18 *cx) |
702 | { | 751 | { |
@@ -705,7 +754,7 @@ void cx18_stop_all_captures(struct cx18 *cx) | |||
705 | for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { | 754 | for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { |
706 | struct cx18_stream *s = &cx->streams[i]; | 755 | struct cx18_stream *s = &cx->streams[i]; |
707 | 756 | ||
708 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 757 | if (!cx18_stream_enabled(s)) |
709 | continue; | 758 | continue; |
710 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) | 759 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) |
711 | cx18_stop_v4l2_encode_stream(s, 0); | 760 | cx18_stop_v4l2_encode_stream(s, 0); |
@@ -717,7 +766,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
717 | struct cx18 *cx = s->cx; | 766 | struct cx18 *cx = s->cx; |
718 | unsigned long then; | 767 | unsigned long then; |
719 | 768 | ||
720 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 769 | if (!cx18_stream_enabled(s)) |
721 | return -EINVAL; | 770 | return -EINVAL; |
722 | 771 | ||
723 | /* This function assumes that you are allowed to stop the capture | 772 | /* This function assumes that you are allowed to stop the capture |
@@ -762,6 +811,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
762 | 811 | ||
763 | return 0; | 812 | return 0; |
764 | } | 813 | } |
814 | EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream); | ||
765 | 815 | ||
766 | u32 cx18_find_handle(struct cx18 *cx) | 816 | u32 cx18_find_handle(struct cx18 *cx) |
767 | { | 817 | { |
@@ -789,7 +839,7 @@ struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle) | |||
789 | s = &cx->streams[i]; | 839 | s = &cx->streams[i]; |
790 | if (s->handle != handle) | 840 | if (s->handle != handle) |
791 | continue; | 841 | continue; |
792 | if (s->video_dev || s->dvb.enabled) | 842 | if (cx18_stream_enabled(s)) |
793 | return s; | 843 | return s; |
794 | } | 844 | } |
795 | return NULL; | 845 | return NULL; |