1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "cx18-driver.h"
26#include "cx18-fileops.h"
27#include "cx18-i2c.h"
28#include "cx18-queue.h"
29#include "cx18-vbi.h"
30#include "cx18-audio.h"
31#include "cx18-mailbox.h"
32#include "cx18-scb.h"
33#include "cx18-streams.h"
34#include "cx18-controls.h"
35#include "cx18-ioctl.h"
36#include "cx18-cards.h"
37#include <media/v4l2-event.h>
38
39
40
41
42
43
44int cx18_claim_stream(struct cx18_open_id *id, int type)
45{
46 struct cx18 *cx = id->cx;
47 struct cx18_stream *s = &cx->streams[type];
48 struct cx18_stream *s_assoc;
49
50
51 if (type == CX18_ENC_STREAM_TYPE_IDX) {
52 CX18_WARN("MPEG Index stream cannot be claimed "
53 "directly, but something tried.\n");
54 return -EINVAL;
55 }
56
57 if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
58
59 if (s->id == id->open_id) {
60
61 return 0;
62 }
63 if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
64
65
66
67 s->id = id->open_id;
68 CX18_DEBUG_INFO("Start Read VBI\n");
69 return 0;
70 }
71
72 CX18_DEBUG_INFO("Stream %d is busy\n", type);
73 return -EBUSY;
74 }
75 s->id = id->open_id;
76
77
78
79
80
81
82
83
84
85 if (type != CX18_ENC_STREAM_TYPE_MPG)
86 return 0;
87
88 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
89 if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
90 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
91 else if (!cx18_stream_enabled(s_assoc))
92 return 0;
93
94 set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
95
96
97 set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
98 return 0;
99}
100EXPORT_SYMBOL(cx18_claim_stream);
101
102
103
104void cx18_release_stream(struct cx18_stream *s)
105{
106 struct cx18 *cx = s->cx;
107 struct cx18_stream *s_assoc;
108
109 s->id = -1;
110 if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
111
112
113
114
115 return;
116 }
117
118 if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
119 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
120
121 return;
122 }
123 if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
124 CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
125 return;
126 }
127
128 cx18_flush_queues(s);
129
130
131
132
133
134
135
136 if (s->type != CX18_ENC_STREAM_TYPE_MPG)
137 return;
138
139
140 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
141 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
142 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
143 cx18_flush_queues(s_assoc);
144 }
145
146
147 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
148 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
149 if (s_assoc->id == -1) {
150
151
152
153
154 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
155 cx18_flush_queues(s_assoc);
156 }
157 }
158}
159EXPORT_SYMBOL(cx18_release_stream);
160
161static void cx18_dualwatch(struct cx18 *cx)
162{
163 struct v4l2_tuner vt;
164 u32 new_stereo_mode;
165 const u32 dual = 0x0200;
166
167 new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
168 memset(&vt, 0, sizeof(vt));
169 cx18_call_all(cx, tuner, g_tuner, &vt);
170 if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
171 (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
172 new_stereo_mode = dual;
173
174 if (new_stereo_mode == cx->dualwatch_stereo_mode)
175 return;
176
177 CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
178 cx->dualwatch_stereo_mode, new_stereo_mode);
179 if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
180 CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
181}
182
183
184static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
185 int *err)
186{
187 struct cx18 *cx = s->cx;
188 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
189 struct cx18_mdl *mdl;
190 DEFINE_WAIT(wait);
191
192 *err = 0;
193 while (1) {
194 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
195
196 if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
197 cx->dualwatch_jiffies = jiffies;
198 cx18_dualwatch(cx);
199 }
200 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
201 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
202 while ((mdl = cx18_dequeue(s_vbi,
203 &s_vbi->q_full))) {
204
205 cx18_process_vbi_data(cx, mdl,
206 s_vbi->type);
207 cx18_stream_put_mdl_fw(s_vbi, mdl);
208 }
209 }
210 mdl = &cx->vbi.sliced_mpeg_mdl;
211 if (mdl->readpos != mdl->bytesused)
212 return mdl;
213 }
214
215
216 mdl = cx18_dequeue(s, &s->q_full);
217 if (mdl) {
218 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
219 &mdl->m_flags))
220 return mdl;
221 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
222
223 cx18_mdl_swap(mdl);
224 else {
225
226 cx18_process_vbi_data(cx, mdl, s->type);
227 }
228 return mdl;
229 }
230
231
232 if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
233 CX18_DEBUG_INFO("EOS %s\n", s->name);
234 return NULL;
235 }
236
237
238 if (non_block) {
239 *err = -EAGAIN;
240 return NULL;
241 }
242
243
244 prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
245
246
247 if (!atomic_read(&s->q_full.depth))
248 schedule();
249 finish_wait(&s->waitq, &wait);
250 if (signal_pending(current)) {
251
252 CX18_DEBUG_INFO("User stopped %s\n", s->name);
253 *err = -EINTR;
254 return NULL;
255 }
256 }
257}
258
259static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
260{
261 struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
262 struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
263 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
264
265 buf->buf = cx->vbi.sliced_mpeg_data[idx];
266 buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
267 buf->readpos = 0;
268
269 mdl->curr_buf = NULL;
270 mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
271 mdl->readpos = 0;
272}
273
274static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
275 struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
276{
277 struct cx18 *cx = s->cx;
278 size_t len = buf->bytesused - buf->readpos;
279
280 *stop = false;
281 if (len > ucount)
282 len = ucount;
283 if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
284 !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304 const char *start = buf->buf + buf->readpos;
305 const char *p = start + 1;
306 const u8 *q;
307 u8 ch = cx->search_pack_header ? 0xba : 0xe0;
308 int stuffing, i;
309
310 while (start + len > p) {
311
312 q = memchr(p, 0, start + len - p);
313 if (q == NULL)
314 break;
315 p = q + 1;
316
317
318
319
320
321 if ((char *)q + 15 >= buf->buf + buf->bytesused ||
322 q[1] != 0 || q[2] != 1 || q[3] != ch)
323 continue;
324
325
326 if (!cx->search_pack_header) {
327
328 if ((q[6] & 0xc0) != 0x80)
329 continue;
330
331 if (((q[7] & 0xc0) == 0x80 &&
332 (q[9] & 0xf0) == 0x20) ||
333 ((q[7] & 0xc0) == 0xc0 &&
334 (q[9] & 0xf0) == 0x30)) {
335
336 ch = 0xba;
337 cx->search_pack_header = 1;
338 p = q + 9;
339 }
340 continue;
341 }
342
343
344
345
346 stuffing = q[13] & 7;
347
348 for (i = 0; i < stuffing; i++)
349 if (q[14 + i] != 0xff)
350 break;
351 if (i == stuffing &&
352 (q[4] & 0xc4) == 0x44 &&
353 (q[12] & 3) == 3 &&
354 q[14 + stuffing] == 0 &&
355 q[15 + stuffing] == 0 &&
356 q[16 + stuffing] == 1) {
357
358 cx->search_pack_header = 0;
359 len = (char *)q - start;
360 cx18_setup_sliced_vbi_mdl(cx);
361 *stop = true;
362 break;
363 }
364 }
365 }
366 if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
367 CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
368 len, s->name);
369 return -EFAULT;
370 }
371 buf->readpos += len;
372 if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
373 buf != &cx->vbi.sliced_mpeg_buf)
374 cx->mpg_data_received += len;
375 return len;
376}
377
378static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
379 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
380{
381 size_t tot_written = 0;
382 int rc;
383 bool stop = false;
384
385 if (mdl->curr_buf == NULL)
386 mdl->curr_buf = list_first_entry(&mdl->buf_list,
387 struct cx18_buffer, list);
388
389 if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
390
391
392
393
394
395 mdl->readpos = mdl->bytesused;
396 return 0;
397 }
398
399 list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
400
401 if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
402 continue;
403
404 rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
405 ucount - tot_written, &stop);
406 if (rc < 0)
407 return rc;
408 mdl->readpos += rc;
409 tot_written += rc;
410
411 if (stop ||
412 tot_written >= ucount ||
413 mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
414 mdl->readpos >= mdl->bytesused)
415 break;
416 }
417 return tot_written;
418}
419
420static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
421 size_t tot_count, int non_block)
422{
423 struct cx18 *cx = s->cx;
424 size_t tot_written = 0;
425 int single_frame = 0;
426
427 if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
428
429 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
430 s->name);
431 return -EIO;
432 }
433
434
435
436
437 if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
438 single_frame = 1;
439
440 for (;;) {
441 struct cx18_mdl *mdl;
442 int rc;
443
444 mdl = cx18_get_mdl(s, non_block, &rc);
445
446 if (mdl == NULL) {
447
448 if (tot_written)
449 break;
450
451 if (rc == 0) {
452 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
453 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
454 cx18_release_stream(s);
455 }
456
457 return rc;
458 }
459
460 rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
461 tot_count - tot_written);
462
463 if (mdl != &cx->vbi.sliced_mpeg_mdl) {
464 if (mdl->readpos == mdl->bytesused)
465 cx18_stream_put_mdl_fw(s, mdl);
466 else
467 cx18_push(s, mdl, &s->q_full);
468 } else if (mdl->readpos == mdl->bytesused) {
469 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
470
471 cx->vbi.sliced_mpeg_size[idx] = 0;
472 cx->vbi.inserted_frame++;
473 cx->vbi_data_inserted += mdl->bytesused;
474 }
475 if (rc < 0)
476 return rc;
477 tot_written += rc;
478
479 if (tot_written == tot_count || single_frame)
480 break;
481 }
482 return tot_written;
483}
484
485static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
486 size_t count, loff_t *pos, int non_block)
487{
488 ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
489 struct cx18 *cx = s->cx;
490
491 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
492 if (rc > 0)
493 pos += rc;
494 return rc;
495}
496
497int cx18_start_capture(struct cx18_open_id *id)
498{
499 struct cx18 *cx = id->cx;
500 struct cx18_stream *s = &cx->streams[id->type];
501 struct cx18_stream *s_vbi;
502 struct cx18_stream *s_idx;
503
504 if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
505
506 return -EPERM;
507 }
508
509
510 if (cx18_claim_stream(id, s->type))
511 return -EBUSY;
512
513
514
515 if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
516 test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
517 set_bit(CX18_F_S_APPL_IO, &s->s_flags);
518 return 0;
519 }
520
521
522 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
523 s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
524 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
525
526
527
528
529
530 if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
531 !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
532 if (cx18_start_v4l2_encode_stream(s_idx)) {
533 CX18_DEBUG_WARN("IDX capture start failed\n");
534 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
535 goto start_failed;
536 }
537 CX18_DEBUG_INFO("IDX capture started\n");
538 }
539 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
540 !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
541 if (cx18_start_v4l2_encode_stream(s_vbi)) {
542 CX18_DEBUG_WARN("VBI capture start failed\n");
543 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
544 goto start_failed;
545 }
546 CX18_DEBUG_INFO("VBI insertion started\n");
547 }
548 }
549
550
551 if (!cx18_start_v4l2_encode_stream(s)) {
552
553 set_bit(CX18_F_S_APPL_IO, &s->s_flags);
554
555 if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
556 cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
557 return 0;
558 }
559
560start_failed:
561 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
562
563
564
565
566
567
568 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
569
570 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
571 cx18_stop_v4l2_encode_stream(s_idx, 0);
572 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
573 }
574
575 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
576 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
577 cx18_stop_v4l2_encode_stream(s_vbi, 0);
578 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
579 }
580 }
581 clear_bit(CX18_F_S_STREAMING, &s->s_flags);
582 cx18_release_stream(s);
583 return -EIO;
584}
585
586ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
587 loff_t *pos)
588{
589 struct cx18_open_id *id = file2id(filp);
590 struct cx18 *cx = id->cx;
591 struct cx18_stream *s = &cx->streams[id->type];
592 int rc;
593
594 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
595
596 mutex_lock(&cx->serialize_lock);
597 rc = cx18_start_capture(id);
598 mutex_unlock(&cx->serialize_lock);
599 if (rc)
600 return rc;
601
602 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
603 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
604 return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
605 filp->f_flags & O_NONBLOCK);
606 }
607
608 return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
609}
610
611unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
612{
613 unsigned long req_events = poll_requested_events(wait);
614 struct cx18_open_id *id = file2id(filp);
615 struct cx18 *cx = id->cx;
616 struct cx18_stream *s = &cx->streams[id->type];
617 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
618 unsigned res = 0;
619
620
621 if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags) &&
622 (req_events & (POLLIN | POLLRDNORM))) {
623 int rc;
624
625 mutex_lock(&cx->serialize_lock);
626 rc = cx18_start_capture(id);
627 mutex_unlock(&cx->serialize_lock);
628 if (rc) {
629 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
630 s->name, rc);
631 return POLLERR;
632 }
633 CX18_DEBUG_FILE("Encoder poll started capture\n");
634 }
635
636 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
637 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
638 int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
639
640 if (v4l2_event_pending(&id->fh))
641 res |= POLLPRI;
642 if (eof && videobuf_poll == POLLERR)
643 return res | POLLHUP;
644 return res | videobuf_poll;
645 }
646
647
648 CX18_DEBUG_HI_FILE("Encoder poll\n");
649 if (v4l2_event_pending(&id->fh))
650 res |= POLLPRI;
651 else
652 poll_wait(filp, &s->waitq, wait);
653
654 if (atomic_read(&s->q_full.depth))
655 return res | POLLIN | POLLRDNORM;
656 if (eof)
657 return res | POLLHUP;
658 return res;
659}
660
661int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
662{
663 struct cx18_open_id *id = file->private_data;
664 struct cx18 *cx = id->cx;
665 struct cx18_stream *s = &cx->streams[id->type];
666 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
667
668 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
669 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
670
671
672 if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
673 int rc;
674
675 mutex_lock(&cx->serialize_lock);
676 rc = cx18_start_capture(id);
677 mutex_unlock(&cx->serialize_lock);
678 if (rc) {
679 CX18_DEBUG_INFO(
680 "Could not start capture for %s (%d)\n",
681 s->name, rc);
682 return -EINVAL;
683 }
684 CX18_DEBUG_FILE("Encoder mmap started capture\n");
685 }
686
687 return videobuf_mmap_mapper(&s->vbuf_q, vma);
688 }
689
690 return -EINVAL;
691}
692
693void cx18_vb_timeout(unsigned long data)
694{
695 struct cx18_stream *s = (struct cx18_stream *)data;
696 struct cx18_videobuf_buffer *buf;
697 unsigned long flags;
698
699
700
701
702 spin_lock_irqsave(&s->vb_lock, flags);
703 while (!list_empty(&s->vb_capture)) {
704 buf = list_entry(s->vb_capture.next,
705 struct cx18_videobuf_buffer, vb.queue);
706 list_del(&buf->vb.queue);
707 buf->vb.state = VIDEOBUF_ERROR;
708 wake_up(&buf->vb.done);
709 }
710 spin_unlock_irqrestore(&s->vb_lock, flags);
711}
712
713void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
714{
715 struct cx18 *cx = id->cx;
716 struct cx18_stream *s = &cx->streams[id->type];
717 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
718 struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
719
720 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
721
722
723
724
725 if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
726 CX18_DEBUG_INFO("close stopping capture\n");
727 if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
728
729 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
730 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
731 CX18_DEBUG_INFO("close stopping embedded VBI "
732 "capture\n");
733 cx18_stop_v4l2_encode_stream(s_vbi, 0);
734 }
735 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
736 CX18_DEBUG_INFO("close stopping IDX capture\n");
737 cx18_stop_v4l2_encode_stream(s_idx, 0);
738 }
739 }
740 if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
741 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
742
743 s->id = -1;
744 else
745 cx18_stop_v4l2_encode_stream(s, gop_end);
746 }
747 if (!gop_end) {
748 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
749 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
750 cx18_release_stream(s);
751 }
752}
753
754int cx18_v4l2_close(struct file *filp)
755{
756 struct v4l2_fh *fh = filp->private_data;
757 struct cx18_open_id *id = fh2id(fh);
758 struct cx18 *cx = id->cx;
759 struct cx18_stream *s = &cx->streams[id->type];
760
761 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
762
763 mutex_lock(&cx->serialize_lock);
764
765 if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
766 v4l2_fh_is_singular_file(filp)) {
767
768 cx18_mute(cx);
769
770 clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
771
772 cx18_call_all(cx, video, s_std, cx->std);
773
774 cx18_audio_set_io(cx);
775 if (atomic_read(&cx->ana_capturing) > 0) {
776
777 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
778 (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
779 (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
780 }
781
782 cx18_unmute(cx);
783 }
784
785 v4l2_fh_del(fh);
786 v4l2_fh_exit(fh);
787
788
789 if (s->id == id->open_id)
790 cx18_stop_capture(id, 0);
791 kfree(id);
792 mutex_unlock(&cx->serialize_lock);
793 return 0;
794}
795
796static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
797{
798 struct cx18 *cx = s->cx;
799 struct cx18_open_id *item;
800
801 CX18_DEBUG_FILE("open %s\n", s->name);
802
803
804 item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
805 if (NULL == item) {
806 CX18_DEBUG_WARN("nomem on v4l2 open\n");
807 return -ENOMEM;
808 }
809 v4l2_fh_init(&item->fh, &s->video_dev);
810
811 item->cx = cx;
812 item->type = s->type;
813
814 item->open_id = cx->open_id++;
815 filp->private_data = &item->fh;
816 v4l2_fh_add(&item->fh);
817
818 if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
819 v4l2_fh_is_singular_file(filp)) {
820 if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
821 if (atomic_read(&cx->ana_capturing) > 0) {
822
823
824 v4l2_fh_del(&item->fh);
825 v4l2_fh_exit(&item->fh);
826 kfree(item);
827 return -EBUSY;
828 }
829 }
830
831
832 set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
833
834 cx18_mute(cx);
835
836 cx18_call_all(cx, tuner, s_radio);
837
838 cx18_audio_set_io(cx);
839
840 cx18_unmute(cx);
841 }
842 return 0;
843}
844
845int cx18_v4l2_open(struct file *filp)
846{
847 int res;
848 struct video_device *video_dev = video_devdata(filp);
849 struct cx18_stream *s = video_get_drvdata(video_dev);
850 struct cx18 *cx = s->cx;
851
852 mutex_lock(&cx->serialize_lock);
853 if (cx18_init_on_first_open(cx)) {
854 CX18_ERR("Failed to initialize on %s\n",
855 video_device_node_name(video_dev));
856 mutex_unlock(&cx->serialize_lock);
857 return -ENXIO;
858 }
859 res = cx18_serialized_open(s, filp);
860 mutex_unlock(&cx->serialize_lock);
861 return res;
862}
863
864void cx18_mute(struct cx18 *cx)
865{
866 u32 h;
867 if (atomic_read(&cx->ana_capturing)) {
868 h = cx18_find_handle(cx);
869 if (h != CX18_INVALID_TASK_HANDLE)
870 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
871 else
872 CX18_ERR("Can't find valid task handle for mute\n");
873 }
874 CX18_DEBUG_INFO("Mute\n");
875}
876
877void cx18_unmute(struct cx18 *cx)
878{
879 u32 h;
880 if (atomic_read(&cx->ana_capturing)) {
881 h = cx18_find_handle(cx);
882 if (h != CX18_INVALID_TASK_HANDLE) {
883 cx18_msleep_timeout(100, 0);
884 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
885 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
886 } else
887 CX18_ERR("Can't find valid task handle for unmute\n");
888 }
889 CX18_DEBUG_INFO("Unmute\n");
890}
891