2 * cx18 file operation functions
4 * Derived from ivtv-fileops.c
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 #include "cx18-driver.h"
21 #include "cx18-fileops.h"
23 #include "cx18-queue.h"
25 #include "cx18-audio.h"
26 #include "cx18-mailbox.h"
28 #include "cx18-streams.h"
29 #include "cx18-controls.h"
30 #include "cx18-ioctl.h"
31 #include "cx18-cards.h"
32 #include <media/v4l2-event.h>
34 /* This function tries to claim the stream for a specific file descriptor.
35 If no one else is using this stream then the stream is claimed and
36 associated VBI and IDX streams are also automatically claimed.
37 Possible error returns: -EBUSY if someone else has claimed
38 the stream or 0 on success. */
39 int cx18_claim_stream(struct cx18_open_id
*id
, int type
)
41 struct cx18
*cx
= id
->cx
;
42 struct cx18_stream
*s
= &cx
->streams
[type
];
43 struct cx18_stream
*s_assoc
;
45 /* Nothing should ever try to directly claim the IDX stream */
46 if (type
== CX18_ENC_STREAM_TYPE_IDX
) {
47 CX18_WARN("MPEG Index stream cannot be claimed directly, but something tried.\n");
51 if (test_and_set_bit(CX18_F_S_CLAIMED
, &s
->s_flags
)) {
52 /* someone already claimed this stream */
53 if (s
->id
== id
->open_id
) {
54 /* yes, this file descriptor did. So that's OK. */
57 if (s
->id
== -1 && type
== CX18_ENC_STREAM_TYPE_VBI
) {
58 /* VBI is handled already internally, now also assign
59 the file descriptor to this stream for external
60 reading of the stream. */
62 CX18_DEBUG_INFO("Start Read VBI\n");
65 /* someone else is using this stream already */
66 CX18_DEBUG_INFO("Stream %d is busy\n", type
);
72 * CX18_ENC_STREAM_TYPE_MPG needs to claim:
73 * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
74 * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
75 * (We don't yet fix up MPEG Index entries for our inserted packets).
77 * For all other streams we're done.
79 if (type
!= CX18_ENC_STREAM_TYPE_MPG
)
82 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
83 if (cx
->vbi
.insert_mpeg
&& !cx18_raw_vbi(cx
))
84 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
85 else if (!cx18_stream_enabled(s_assoc
))
88 set_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
90 /* mark that it is used internally */
91 set_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
);
94 EXPORT_SYMBOL(cx18_claim_stream
);
96 /* This function releases a previously claimed stream. It will take into
97 account associated VBI streams. */
98 void cx18_release_stream(struct cx18_stream
*s
)
100 struct cx18
*cx
= s
->cx
;
101 struct cx18_stream
*s_assoc
;
104 if (s
->type
== CX18_ENC_STREAM_TYPE_IDX
) {
106 * The IDX stream is only used internally, and can
107 * only be indirectly unclaimed by unclaiming the MPG stream.
112 if (s
->type
== CX18_ENC_STREAM_TYPE_VBI
&&
113 test_bit(CX18_F_S_INTERNAL_USE
, &s
->s_flags
)) {
114 /* this stream is still in use internally */
117 if (!test_and_clear_bit(CX18_F_S_CLAIMED
, &s
->s_flags
)) {
118 CX18_DEBUG_WARN("Release stream %s not in use!\n", s
->name
);
122 cx18_flush_queues(s
);
125 * CX18_ENC_STREAM_TYPE_MPG needs to release the
126 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
128 * For all other streams we're done.
130 if (s
->type
!= CX18_ENC_STREAM_TYPE_MPG
)
133 /* Unclaim the associated MPEG Index stream */
134 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
135 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
)) {
136 clear_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
137 cx18_flush_queues(s_assoc
);
140 /* Unclaim the associated VBI stream */
141 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
142 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
)) {
143 if (s_assoc
->id
== -1) {
145 * The VBI stream is not still claimed by a file
146 * descriptor, so completely unclaim it.
148 clear_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
149 cx18_flush_queues(s_assoc
);
153 EXPORT_SYMBOL(cx18_release_stream
);
155 static void cx18_dualwatch(struct cx18
*cx
)
157 struct v4l2_tuner vt
;
159 const u32 dual
= 0x0200;
161 new_stereo_mode
= v4l2_ctrl_g_ctrl(cx
->cxhdl
.audio_mode
);
162 memset(&vt
, 0, sizeof(vt
));
163 cx18_call_all(cx
, tuner
, g_tuner
, &vt
);
164 if (vt
.audmode
== V4L2_TUNER_MODE_LANG1_LANG2
&&
165 (vt
.rxsubchans
& V4L2_TUNER_SUB_LANG2
))
166 new_stereo_mode
= dual
;
168 if (new_stereo_mode
== cx
->dualwatch_stereo_mode
)
171 CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
172 cx
->dualwatch_stereo_mode
, new_stereo_mode
);
173 if (v4l2_ctrl_s_ctrl(cx
->cxhdl
.audio_mode
, new_stereo_mode
))
174 CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
178 static struct cx18_mdl
*cx18_get_mdl(struct cx18_stream
*s
, int non_block
,
181 struct cx18
*cx
= s
->cx
;
182 struct cx18_stream
*s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
183 struct cx18_mdl
*mdl
;
188 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
189 /* Process pending program updates and VBI data */
190 if (time_after(jiffies
, cx
->dualwatch_jiffies
+ msecs_to_jiffies(1000))) {
191 cx
->dualwatch_jiffies
= jiffies
;
194 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_vbi
->s_flags
) &&
195 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
196 while ((mdl
= cx18_dequeue(s_vbi
,
198 /* byteswap and process VBI data */
199 cx18_process_vbi_data(cx
, mdl
,
201 cx18_stream_put_mdl_fw(s_vbi
, mdl
);
204 mdl
= &cx
->vbi
.sliced_mpeg_mdl
;
205 if (mdl
->readpos
!= mdl
->bytesused
)
209 /* do we have new data? */
210 mdl
= cx18_dequeue(s
, &s
->q_full
);
212 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP
,
215 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
)
216 /* byteswap MPG data */
219 /* byteswap and process VBI data */
220 cx18_process_vbi_data(cx
, mdl
, s
->type
);
225 /* return if end of stream */
226 if (!test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
227 CX18_DEBUG_INFO("EOS %s\n", s
->name
);
231 /* return if file was opened with O_NONBLOCK */
237 /* wait for more data to arrive */
238 prepare_to_wait(&s
->waitq
, &wait
, TASK_INTERRUPTIBLE
);
239 /* New buffers might have become available before we were added
241 if (!atomic_read(&s
->q_full
.depth
))
243 finish_wait(&s
->waitq
, &wait
);
244 if (signal_pending(current
)) {
245 /* return if a signal was received */
246 CX18_DEBUG_INFO("User stopped %s\n", s
->name
);
253 static void cx18_setup_sliced_vbi_mdl(struct cx18
*cx
)
255 struct cx18_mdl
*mdl
= &cx
->vbi
.sliced_mpeg_mdl
;
256 struct cx18_buffer
*buf
= &cx
->vbi
.sliced_mpeg_buf
;
257 int idx
= cx
->vbi
.inserted_frame
% CX18_VBI_FRAMES
;
259 buf
->buf
= cx
->vbi
.sliced_mpeg_data
[idx
];
260 buf
->bytesused
= cx
->vbi
.sliced_mpeg_size
[idx
];
263 mdl
->curr_buf
= NULL
;
264 mdl
->bytesused
= cx
->vbi
.sliced_mpeg_size
[idx
];
268 static size_t cx18_copy_buf_to_user(struct cx18_stream
*s
,
269 struct cx18_buffer
*buf
, char __user
*ubuf
, size_t ucount
, bool *stop
)
271 struct cx18
*cx
= s
->cx
;
272 size_t len
= buf
->bytesused
- buf
->readpos
;
277 if (cx
->vbi
.insert_mpeg
&& s
->type
== CX18_ENC_STREAM_TYPE_MPG
&&
278 !cx18_raw_vbi(cx
) && buf
!= &cx
->vbi
.sliced_mpeg_buf
) {
280 * Try to find a good splice point in the PS, just before
281 * an MPEG-2 Program Pack start code, and provide only
282 * up to that point to the user, so it's easy to insert VBI data
283 * the next time around.
285 * This will not work for an MPEG-2 TS and has only been
286 * verified by analysis to work for an MPEG-2 PS. Helen Buus
287 * pointed out this works for the CX23416 MPEG-2 DVD compatible
288 * stream, and research indicates both the MPEG 2 SVCD and DVD
289 * stream types use an MPEG-2 PS container.
292 * An MPEG-2 Program Stream (PS) is a series of
293 * MPEG-2 Program Packs terminated by an
294 * MPEG Program End Code after the last Program Pack.
295 * A Program Pack may hold a PS System Header packet and any
296 * number of Program Elementary Stream (PES) Packets
298 const char *start
= buf
->buf
+ buf
->readpos
;
299 const char *p
= start
+ 1;
301 u8 ch
= cx
->search_pack_header
? 0xba : 0xe0;
304 while (start
+ len
> p
) {
305 /* Scan for a 0 to find a potential MPEG-2 start code */
306 q
= memchr(p
, 0, start
+ len
- p
);
311 * Keep looking if not a
312 * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba
313 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
315 if ((char *)q
+ 15 >= buf
->buf
+ buf
->bytesused
||
316 q
[1] != 0 || q
[2] != 1 || q
[3] != ch
)
319 /* If expecting the primary video PES */
320 if (!cx
->search_pack_header
) {
321 /* Continue if it couldn't be a PES packet */
322 if ((q
[6] & 0xc0) != 0x80)
324 /* Check if a PTS or PTS & DTS follow */
325 if (((q
[7] & 0xc0) == 0x80 && /* PTS only */
326 (q
[9] & 0xf0) == 0x20) || /* PTS only */
327 ((q
[7] & 0xc0) == 0xc0 && /* PTS & DTS */
328 (q
[9] & 0xf0) == 0x30)) { /* DTS follows */
329 /* Assume we found the video PES hdr */
330 ch
= 0xba; /* next want a Program Pack*/
331 cx
->search_pack_header
= 1;
332 p
= q
+ 9; /* Skip this video PES hdr */
337 /* We may have found a Program Pack start code */
339 /* Get the count of stuffing bytes & verify them */
340 stuffing
= q
[13] & 7;
341 /* all stuffing bytes must be 0xff */
342 for (i
= 0; i
< stuffing
; i
++)
343 if (q
[14 + i
] != 0xff)
345 if (i
== stuffing
&& /* right number of stuffing bytes*/
346 (q
[4] & 0xc4) == 0x44 && /* marker check */
347 (q
[12] & 3) == 3 && /* marker check */
348 q
[14 + stuffing
] == 0 && /* PES Pack or Sys Hdr */
349 q
[15 + stuffing
] == 0 &&
350 q
[16 + stuffing
] == 1) {
351 /* We declare we actually found a Program Pack*/
352 cx
->search_pack_header
= 0; /* expect vid PES */
353 len
= (char *)q
- start
;
354 cx18_setup_sliced_vbi_mdl(cx
);
360 if (copy_to_user(ubuf
, (u8
*)buf
->buf
+ buf
->readpos
, len
)) {
361 CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
366 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
&&
367 buf
!= &cx
->vbi
.sliced_mpeg_buf
)
368 cx
->mpg_data_received
+= len
;
372 static size_t cx18_copy_mdl_to_user(struct cx18_stream
*s
,
373 struct cx18_mdl
*mdl
, char __user
*ubuf
, size_t ucount
)
375 size_t tot_written
= 0;
379 if (mdl
->curr_buf
== NULL
)
380 mdl
->curr_buf
= list_first_entry(&mdl
->buf_list
,
381 struct cx18_buffer
, list
);
383 if (list_entry_is_past_end(mdl
->curr_buf
, &mdl
->buf_list
, list
)) {
385 * For some reason we've exhausted the buffers, but the MDL
386 * object still said some data was unread.
387 * Fix that and bail out.
389 mdl
->readpos
= mdl
->bytesused
;
393 list_for_each_entry_from(mdl
->curr_buf
, &mdl
->buf_list
, list
) {
395 if (mdl
->curr_buf
->readpos
>= mdl
->curr_buf
->bytesused
)
398 rc
= cx18_copy_buf_to_user(s
, mdl
->curr_buf
, ubuf
+ tot_written
,
399 ucount
- tot_written
, &stop
);
405 if (stop
|| /* Forced stopping point for VBI insertion */
406 tot_written
>= ucount
|| /* Reader request statisfied */
407 mdl
->curr_buf
->readpos
< mdl
->curr_buf
->bytesused
||
408 mdl
->readpos
>= mdl
->bytesused
) /* MDL buffers drained */
414 static ssize_t
cx18_read(struct cx18_stream
*s
, char __user
*ubuf
,
415 size_t tot_count
, int non_block
)
417 struct cx18
*cx
= s
->cx
;
418 size_t tot_written
= 0;
419 int single_frame
= 0;
421 if (atomic_read(&cx
->ana_capturing
) == 0 && s
->id
== -1) {
422 /* shouldn't happen */
423 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
428 /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
429 frames should arrive one-by-one, so make sure we never output more
430 than one VBI frame at a time */
431 if (s
->type
== CX18_ENC_STREAM_TYPE_VBI
&& !cx18_raw_vbi(cx
))
435 struct cx18_mdl
*mdl
;
438 mdl
= cx18_get_mdl(s
, non_block
, &rc
);
439 /* if there is no data available... */
441 /* if we got data, then return that regardless */
446 clear_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
447 clear_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
448 cx18_release_stream(s
);
454 rc
= cx18_copy_mdl_to_user(s
, mdl
, ubuf
+ tot_written
,
455 tot_count
- tot_written
);
457 if (mdl
!= &cx
->vbi
.sliced_mpeg_mdl
) {
458 if (mdl
->readpos
== mdl
->bytesused
)
459 cx18_stream_put_mdl_fw(s
, mdl
);
461 cx18_push(s
, mdl
, &s
->q_full
);
462 } else if (mdl
->readpos
== mdl
->bytesused
) {
463 int idx
= cx
->vbi
.inserted_frame
% CX18_VBI_FRAMES
;
465 cx
->vbi
.sliced_mpeg_size
[idx
] = 0;
466 cx
->vbi
.inserted_frame
++;
467 cx
->vbi_data_inserted
+= mdl
->bytesused
;
473 if (tot_written
== tot_count
|| single_frame
)
479 static ssize_t
cx18_read_pos(struct cx18_stream
*s
, char __user
*ubuf
,
480 size_t count
, loff_t
*pos
, int non_block
)
482 ssize_t rc
= count
? cx18_read(s
, ubuf
, count
, non_block
) : 0;
483 struct cx18
*cx
= s
->cx
;
485 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count
, s
->name
, rc
);
491 int cx18_start_capture(struct cx18_open_id
*id
)
493 struct cx18
*cx
= id
->cx
;
494 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
495 struct cx18_stream
*s_vbi
;
496 struct cx18_stream
*s_idx
;
498 if (s
->type
== CX18_ENC_STREAM_TYPE_RAD
) {
499 /* you cannot read from these stream types. */
503 /* Try to claim this stream. */
504 if (cx18_claim_stream(id
, s
->type
))
507 /* If capture is already in progress, then we also have to
509 if (test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
) ||
510 test_and_set_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
511 set_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
515 /* Start associated VBI or IDX stream capture if required */
516 s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
517 s_idx
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
518 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
520 * The VBI and IDX streams should have been claimed
521 * automatically, if for internal use, when the MPG stream was
522 * claimed. We only need to start these streams capturing.
524 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_idx
->s_flags
) &&
525 !test_and_set_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
526 if (cx18_start_v4l2_encode_stream(s_idx
)) {
527 CX18_DEBUG_WARN("IDX capture start failed\n");
528 clear_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
);
531 CX18_DEBUG_INFO("IDX capture started\n");
533 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_vbi
->s_flags
) &&
534 !test_and_set_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
)) {
535 if (cx18_start_v4l2_encode_stream(s_vbi
)) {
536 CX18_DEBUG_WARN("VBI capture start failed\n");
537 clear_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
);
540 CX18_DEBUG_INFO("VBI insertion started\n");
544 /* Tell the card to start capturing */
545 if (!cx18_start_v4l2_encode_stream(s
)) {
547 set_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
548 /* Resume a possibly paused encoder */
549 if (test_and_clear_bit(CX18_F_I_ENC_PAUSED
, &cx
->i_flags
))
550 cx18_vapi(cx
, CX18_CPU_CAPTURE_PAUSE
, 1, s
->handle
);
555 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s
->name
);
558 * The associated VBI and IDX streams for internal use are released
559 * automatically when the MPG stream is released. We only need to stop
560 * the associated stream.
562 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
563 /* Stop the IDX stream which is always for internal use */
564 if (test_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
565 cx18_stop_v4l2_encode_stream(s_idx
, 0);
566 clear_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
);
568 /* Stop the VBI stream, if only running for internal use */
569 if (test_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
) &&
570 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
571 cx18_stop_v4l2_encode_stream(s_vbi
, 0);
572 clear_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
);
575 clear_bit(CX18_F_S_STREAMING
, &s
->s_flags
);
576 cx18_release_stream(s
); /* Also releases associated streams */
580 ssize_t
cx18_v4l2_read(struct file
*filp
, char __user
*buf
, size_t count
,
583 struct cx18_open_id
*id
= file2id(filp
);
584 struct cx18
*cx
= id
->cx
;
585 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
588 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count
, s
->name
);
590 mutex_lock(&cx
->serialize_lock
);
591 rc
= cx18_start_capture(id
);
592 mutex_unlock(&cx
->serialize_lock
);
596 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
597 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
598 return videobuf_read_stream(&s
->vbuf_q
, buf
, count
, pos
, 0,
599 filp
->f_flags
& O_NONBLOCK
);
602 return cx18_read_pos(s
, buf
, count
, pos
, filp
->f_flags
& O_NONBLOCK
);
605 __poll_t
cx18_v4l2_enc_poll(struct file
*filp
, poll_table
*wait
)
607 __poll_t req_events
= poll_requested_events(wait
);
608 struct cx18_open_id
*id
= file2id(filp
);
609 struct cx18
*cx
= id
->cx
;
610 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
611 int eof
= test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
614 /* Start a capture if there is none */
615 if (!eof
&& !test_bit(CX18_F_S_STREAMING
, &s
->s_flags
) &&
616 (req_events
& (EPOLLIN
| EPOLLRDNORM
))) {
619 mutex_lock(&cx
->serialize_lock
);
620 rc
= cx18_start_capture(id
);
621 mutex_unlock(&cx
->serialize_lock
);
623 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
627 CX18_DEBUG_FILE("Encoder poll started capture\n");
630 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
631 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
632 __poll_t videobuf_poll
= videobuf_poll_stream(filp
, &s
->vbuf_q
, wait
);
634 if (v4l2_event_pending(&id
->fh
))
636 if (eof
&& videobuf_poll
== EPOLLERR
)
637 return res
| EPOLLHUP
;
638 return res
| videobuf_poll
;
641 /* add stream's waitq to the poll list */
642 CX18_DEBUG_HI_FILE("Encoder poll\n");
643 if (v4l2_event_pending(&id
->fh
))
646 poll_wait(filp
, &s
->waitq
, wait
);
648 if (atomic_read(&s
->q_full
.depth
))
649 return res
| EPOLLIN
| EPOLLRDNORM
;
651 return res
| EPOLLHUP
;
655 int cx18_v4l2_mmap(struct file
*file
, struct vm_area_struct
*vma
)
657 struct cx18_open_id
*id
= file
->private_data
;
658 struct cx18
*cx
= id
->cx
;
659 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
660 int eof
= test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
662 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
663 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
665 /* Start a capture if there is none */
666 if (!eof
&& !test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
669 mutex_lock(&cx
->serialize_lock
);
670 rc
= cx18_start_capture(id
);
671 mutex_unlock(&cx
->serialize_lock
);
674 "Could not start capture for %s (%d)\n",
678 CX18_DEBUG_FILE("Encoder mmap started capture\n");
681 return videobuf_mmap_mapper(&s
->vbuf_q
, vma
);
687 void cx18_vb_timeout(struct timer_list
*t
)
689 struct cx18_stream
*s
= from_timer(s
, t
, vb_timeout
);
690 struct cx18_videobuf_buffer
*buf
;
693 /* Return all of the buffers in error state, so the vbi/vid inode
694 * can return from blocking.
696 spin_lock_irqsave(&s
->vb_lock
, flags
);
697 while (!list_empty(&s
->vb_capture
)) {
698 buf
= list_entry(s
->vb_capture
.next
,
699 struct cx18_videobuf_buffer
, vb
.queue
);
700 list_del(&buf
->vb
.queue
);
701 buf
->vb
.state
= VIDEOBUF_ERROR
;
702 wake_up(&buf
->vb
.done
);
704 spin_unlock_irqrestore(&s
->vb_lock
, flags
);
707 void cx18_stop_capture(struct cx18_open_id
*id
, int gop_end
)
709 struct cx18
*cx
= id
->cx
;
710 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
711 struct cx18_stream
*s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
712 struct cx18_stream
*s_idx
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
714 CX18_DEBUG_IOCTL("close() of %s\n", s
->name
);
716 /* 'Unclaim' this stream */
719 if (test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
720 CX18_DEBUG_INFO("close stopping capture\n");
721 if (id
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
722 /* Stop internal use associated VBI and IDX streams */
723 if (test_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
) &&
724 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
725 CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
726 cx18_stop_v4l2_encode_stream(s_vbi
, 0);
728 if (test_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
729 CX18_DEBUG_INFO("close stopping IDX capture\n");
730 cx18_stop_v4l2_encode_stream(s_idx
, 0);
733 if (id
->type
== CX18_ENC_STREAM_TYPE_VBI
&&
734 test_bit(CX18_F_S_INTERNAL_USE
, &s
->s_flags
))
735 /* Also used internally, don't stop capturing */
738 cx18_stop_v4l2_encode_stream(s
, gop_end
);
741 clear_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
742 clear_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
743 cx18_release_stream(s
);
747 int cx18_v4l2_close(struct file
*filp
)
749 struct v4l2_fh
*fh
= filp
->private_data
;
750 struct cx18_open_id
*id
= fh2id(fh
);
751 struct cx18
*cx
= id
->cx
;
752 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
754 CX18_DEBUG_IOCTL("close() of %s\n", s
->name
);
756 mutex_lock(&cx
->serialize_lock
);
758 if (id
->type
== CX18_ENC_STREAM_TYPE_RAD
&&
759 v4l2_fh_is_singular_file(filp
)) {
760 /* Closing radio device, return to TV mode */
762 /* Mark that the radio is no longer in use */
763 clear_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
);
764 /* Switch tuner to TV */
765 cx18_call_all(cx
, video
, s_std
, cx
->std
);
766 /* Select correct audio input (i.e. TV tuner or Line in) */
767 cx18_audio_set_io(cx
);
768 if (atomic_read(&cx
->ana_capturing
) > 0) {
769 /* Undo video mute */
770 cx18_vapi(cx
, CX18_CPU_SET_VIDEO_MUTE
, 2, s
->handle
,
771 (v4l2_ctrl_g_ctrl(cx
->cxhdl
.video_mute
) |
772 (v4l2_ctrl_g_ctrl(cx
->cxhdl
.video_mute_yuv
) << 8)));
774 /* Done! Unmute and continue. */
781 /* 'Unclaim' this stream */
782 if (s
->id
== id
->open_id
)
783 cx18_stop_capture(id
, 0);
785 mutex_unlock(&cx
->serialize_lock
);
789 static int cx18_serialized_open(struct cx18_stream
*s
, struct file
*filp
)
791 struct cx18
*cx
= s
->cx
;
792 struct cx18_open_id
*item
;
794 CX18_DEBUG_FILE("open %s\n", s
->name
);
796 /* Allocate memory */
797 item
= kzalloc(sizeof(struct cx18_open_id
), GFP_KERNEL
);
799 CX18_DEBUG_WARN("nomem on v4l2 open\n");
802 v4l2_fh_init(&item
->fh
, &s
->video_dev
);
805 item
->type
= s
->type
;
807 item
->open_id
= cx
->open_id
++;
808 filp
->private_data
= &item
->fh
;
809 v4l2_fh_add(&item
->fh
);
811 if (item
->type
== CX18_ENC_STREAM_TYPE_RAD
&&
812 v4l2_fh_is_singular_file(filp
)) {
813 if (!test_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
)) {
814 if (atomic_read(&cx
->ana_capturing
) > 0) {
815 /* switching to radio while capture is
816 in progress is not polite */
817 v4l2_fh_del(&item
->fh
);
818 v4l2_fh_exit(&item
->fh
);
824 /* Mark that the radio is being used. */
825 set_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
);
826 /* We have the radio */
828 /* Switch tuner to radio */
829 cx18_call_all(cx
, tuner
, s_radio
);
830 /* Select the correct audio input (i.e. radio tuner) */
831 cx18_audio_set_io(cx
);
832 /* Done! Unmute and continue. */
838 int cx18_v4l2_open(struct file
*filp
)
841 struct video_device
*video_dev
= video_devdata(filp
);
842 struct cx18_stream
*s
= video_get_drvdata(video_dev
);
843 struct cx18
*cx
= s
->cx
;
845 mutex_lock(&cx
->serialize_lock
);
846 if (cx18_init_on_first_open(cx
)) {
847 CX18_ERR("Failed to initialize on %s\n",
848 video_device_node_name(video_dev
));
849 mutex_unlock(&cx
->serialize_lock
);
852 res
= cx18_serialized_open(s
, filp
);
853 mutex_unlock(&cx
->serialize_lock
);
857 void cx18_mute(struct cx18
*cx
)
860 if (atomic_read(&cx
->ana_capturing
)) {
861 h
= cx18_find_handle(cx
);
862 if (h
!= CX18_INVALID_TASK_HANDLE
)
863 cx18_vapi(cx
, CX18_CPU_SET_AUDIO_MUTE
, 2, h
, 1);
865 CX18_ERR("Can't find valid task handle for mute\n");
867 CX18_DEBUG_INFO("Mute\n");
870 void cx18_unmute(struct cx18
*cx
)
873 if (atomic_read(&cx
->ana_capturing
)) {
874 h
= cx18_find_handle(cx
);
875 if (h
!= CX18_INVALID_TASK_HANDLE
) {
876 cx18_msleep_timeout(100, 0);
877 cx18_vapi(cx
, CX18_CPU_SET_MISC_PARAMETERS
, 2, h
, 12);
878 cx18_vapi(cx
, CX18_CPU_SET_AUDIO_MUTE
, 2, h
, 0);
880 CX18_ERR("Can't find valid task handle for unmute\n");
882 CX18_DEBUG_INFO("Unmute\n");