aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-fileops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-fileops.c')
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c183
1 files changed, 118 insertions, 65 deletions
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index c0885c69fd89..b1ad03f61019 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -37,15 +37,21 @@
37 37
38/* This function tries to claim the stream for a specific file descriptor. 38/* This function tries to claim the stream for a specific file descriptor.
39 If no one else is using this stream then the stream is claimed and 39 If no one else is using this stream then the stream is claimed and
40 associated VBI streams are also automatically claimed. 40 associated VBI and IDX streams are also automatically claimed.
41 Possible error returns: -EBUSY if someone else has claimed 41 Possible error returns: -EBUSY if someone else has claimed
42 the stream or 0 on success. */ 42 the stream or 0 on success. */
43static int cx18_claim_stream(struct cx18_open_id *id, int type) 43static int cx18_claim_stream(struct cx18_open_id *id, int type)
44{ 44{
45 struct cx18 *cx = id->cx; 45 struct cx18 *cx = id->cx;
46 struct cx18_stream *s = &cx->streams[type]; 46 struct cx18_stream *s = &cx->streams[type];
47 struct cx18_stream *s_vbi; 47 struct cx18_stream *s_assoc;
48 int vbi_type; 48
49 /* Nothing should ever try to directly claim the IDX stream */
50 if (type == CX18_ENC_STREAM_TYPE_IDX) {
51 CX18_WARN("MPEG Index stream cannot be claimed "
52 "directly, but something tried.\n");
53 return -EINVAL;
54 }
49 55
50 if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { 56 if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
51 /* someone already claimed this stream */ 57 /* someone already claimed this stream */
@@ -67,21 +73,27 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type)
67 } 73 }
68 s->id = id->open_id; 74 s->id = id->open_id;
69 75
70 /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI 76 /*
71 (provided VBI insertion is on and sliced VBI is selected), for all 77 * CX18_ENC_STREAM_TYPE_MPG needs to claim:
72 other streams we're done */ 78 * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
73 if (type == CX18_ENC_STREAM_TYPE_MPG && 79 * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
74 cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) { 80 * (We don't yet fix up MPEG Index entries for our inserted packets).
75 vbi_type = CX18_ENC_STREAM_TYPE_VBI; 81 *
76 } else { 82 * For all other streams we're done.
83 */
84 if (type != CX18_ENC_STREAM_TYPE_MPG)
77 return 0; 85 return 0;
78 }
79 s_vbi = &cx->streams[vbi_type];
80 86
81 set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); 87 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
88 if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
89 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
90 else if (!cx18_stream_enabled(s_assoc))
91 return 0;
92
93 set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
82 94
83 /* mark that it is used internally */ 95 /* mark that it is used internally */
84 set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags); 96 set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
85 return 0; 97 return 0;
86} 98}
87 99
@@ -90,9 +102,17 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type)
90static void cx18_release_stream(struct cx18_stream *s) 102static void cx18_release_stream(struct cx18_stream *s)
91{ 103{
92 struct cx18 *cx = s->cx; 104 struct cx18 *cx = s->cx;
93 struct cx18_stream *s_vbi; 105 struct cx18_stream *s_assoc;
94 106
95 s->id = -1; 107 s->id = -1;
108 if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
109 /*
110 * The IDX stream is only used internally, and can
111 * only be indirectly unclaimed by unclaiming the MPG stream.
112 */
113 return;
114 }
115
96 if (s->type == CX18_ENC_STREAM_TYPE_VBI && 116 if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
97 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { 117 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
98 /* this stream is still in use internally */ 118 /* this stream is still in use internally */
@@ -105,24 +125,34 @@ static void cx18_release_stream(struct cx18_stream *s)
105 125
106 cx18_flush_queues(s); 126 cx18_flush_queues(s);
107 127
108 /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI, 128 /*
109 for all other streams we're done */ 129 * CX18_ENC_STREAM_TYPE_MPG needs to release the
110 if (s->type == CX18_ENC_STREAM_TYPE_MPG) 130 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
111 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; 131 *
112 else 132 * For all other streams we're done.
133 */
134 if (s->type != CX18_ENC_STREAM_TYPE_MPG)
113 return; 135 return;
114 136
115 /* clear internal use flag */ 137 /* Unclaim the associated MPEG Index stream */
116 if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) { 138 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
117 /* was already cleared */ 139 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
118 return; 140 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
141 cx18_flush_queues(s_assoc);
119 } 142 }
120 if (s_vbi->id != -1) { 143
121 /* VBI stream still claimed by a file descriptor */ 144 /* Unclaim the associated VBI stream */
122 return; 145 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
146 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
147 if (s_assoc->id == -1) {
148 /*
149 * The VBI stream is not still claimed by a file
150 * descriptor, so completely unclaim it.
151 */
152 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
153 cx18_flush_queues(s_assoc);
154 }
123 } 155 }
124 clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
125 cx18_flush_queues(s_vbi);
126} 156}
127 157
128static void cx18_dualwatch(struct cx18 *cx) 158static void cx18_dualwatch(struct cx18 *cx)
@@ -498,6 +528,7 @@ int cx18_start_capture(struct cx18_open_id *id)
498 struct cx18 *cx = id->cx; 528 struct cx18 *cx = id->cx;
499 struct cx18_stream *s = &cx->streams[id->type]; 529 struct cx18_stream *s = &cx->streams[id->type];
500 struct cx18_stream *s_vbi; 530 struct cx18_stream *s_vbi;
531 struct cx18_stream *s_idx;
501 532
502 if (s->type == CX18_ENC_STREAM_TYPE_RAD) { 533 if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
503 /* you cannot read from these stream types. */ 534 /* you cannot read from these stream types. */
@@ -516,25 +547,33 @@ int cx18_start_capture(struct cx18_open_id *id)
516 return 0; 547 return 0;
517 } 548 }
518 549
519 /* Start VBI capture if required */ 550 /* Start associated VBI or IDX stream capture if required */
520 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; 551 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
521 if (s->type == CX18_ENC_STREAM_TYPE_MPG && 552 s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
522 test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && 553 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
523 !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { 554 /*
524 /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed 555 * The VBI and IDX streams should have been claimed
525 automatically when the MPG stream is claimed. 556 * automatically, if for internal use, when the MPG stream was
526 We only need to start the VBI capturing. */ 557 * claimed. We only need to start these streams capturing.
527 if (cx18_start_v4l2_encode_stream(s_vbi)) { 558 */
528 CX18_DEBUG_WARN("VBI capture start failed\n"); 559 if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
529 560 !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
530 /* Failure, clean up and return an error */ 561 if (cx18_start_v4l2_encode_stream(s_idx)) {
531 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); 562 CX18_DEBUG_WARN("IDX capture start failed\n");
532 clear_bit(CX18_F_S_STREAMING, &s->s_flags); 563 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
533 /* also releases the associated VBI stream */ 564 goto start_failed;
534 cx18_release_stream(s); 565 }
535 return -EIO; 566 CX18_DEBUG_INFO("IDX capture started\n");
567 }
568 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
569 !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
570 if (cx18_start_v4l2_encode_stream(s_vbi)) {
571 CX18_DEBUG_WARN("VBI capture start failed\n");
572 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
573 goto start_failed;
574 }
575 CX18_DEBUG_INFO("VBI insertion started\n");
536 } 576 }
537 CX18_DEBUG_INFO("VBI insertion started\n");
538 } 577 }
539 578
540 /* Tell the card to start capturing */ 579 /* Tell the card to start capturing */
@@ -547,19 +586,29 @@ int cx18_start_capture(struct cx18_open_id *id)
547 return 0; 586 return 0;
548 } 587 }
549 588
550 /* failure, clean up */ 589start_failed:
551 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); 590 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
552 591
553 /* Note: the CX18_ENC_STREAM_TYPE_VBI is released 592 /*
554 automatically when the MPG stream is released. 593 * The associated VBI and IDX streams for internal use are released
555 We only need to stop the VBI capturing. */ 594 * automatically when the MPG stream is released. We only need to stop
556 if (s->type == CX18_ENC_STREAM_TYPE_MPG && 595 * the associated stream.
557 test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { 596 */
558 cx18_stop_v4l2_encode_stream(s_vbi, 0); 597 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
559 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); 598 /* Stop the IDX stream which is always for internal use */
599 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
600 cx18_stop_v4l2_encode_stream(s_idx, 0);
601 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
602 }
603 /* Stop the VBI stream, if only running for internal use */
604 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
605 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
606 cx18_stop_v4l2_encode_stream(s_vbi, 0);
607 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
608 }
560 } 609 }
561 clear_bit(CX18_F_S_STREAMING, &s->s_flags); 610 clear_bit(CX18_F_S_STREAMING, &s->s_flags);
562 cx18_release_stream(s); 611 cx18_release_stream(s); /* Also releases associated streams */
563 return -EIO; 612 return -EIO;
564} 613}
565 614
@@ -618,6 +667,8 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
618{ 667{
619 struct cx18 *cx = id->cx; 668 struct cx18 *cx = id->cx;
620 struct cx18_stream *s = &cx->streams[id->type]; 669 struct cx18_stream *s = &cx->streams[id->type];
670 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
671 struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
621 672
622 CX18_DEBUG_IOCTL("close() of %s\n", s->name); 673 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
623 674
@@ -625,17 +676,19 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
625 676
626 /* Stop capturing */ 677 /* Stop capturing */
627 if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { 678 if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
628 struct cx18_stream *s_vbi =
629 &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
630
631 CX18_DEBUG_INFO("close stopping capture\n"); 679 CX18_DEBUG_INFO("close stopping capture\n");
632 /* Special case: a running VBI capture for VBI insertion 680 if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
633 in the mpeg stream. Need to stop that too. */ 681 /* Stop internal use associated VBI and IDX streams */
634 if (id->type == CX18_ENC_STREAM_TYPE_MPG && 682 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
635 test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && 683 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
636 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { 684 CX18_DEBUG_INFO("close stopping embedded VBI "
637 CX18_DEBUG_INFO("close stopping embedded VBI capture\n"); 685 "capture\n");
638 cx18_stop_v4l2_encode_stream(s_vbi, 0); 686 cx18_stop_v4l2_encode_stream(s_vbi, 0);
687 }
688 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
689 CX18_DEBUG_INFO("close stopping IDX capture\n");
690 cx18_stop_v4l2_encode_stream(s_idx, 0);
691 }
639 } 692 }
640 if (id->type == CX18_ENC_STREAM_TYPE_VBI && 693 if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
641 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) 694 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))