1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * cx18 file operation functions
5 * Derived from ivtv-fileops.c
7 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
8 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
11 #include "cx18-driver.h"
12 #include "cx18-fileops.h"
14 #include "cx18-queue.h"
16 #include "cx18-audio.h"
17 #include "cx18-mailbox.h"
19 #include "cx18-streams.h"
20 #include "cx18-controls.h"
21 #include "cx18-ioctl.h"
22 #include "cx18-cards.h"
23 #include <media/v4l2-event.h>
25 /* This function tries to claim the stream for a specific file descriptor.
26 If no one else is using this stream then the stream is claimed and
27 associated VBI and IDX streams are also automatically claimed.
28 Possible error returns: -EBUSY if someone else has claimed
29 the stream or 0 on success. */
30 int cx18_claim_stream(struct cx18_open_id
*id
, int type
)
32 struct cx18
*cx
= id
->cx
;
33 struct cx18_stream
*s
= &cx
->streams
[type
];
34 struct cx18_stream
*s_assoc
;
36 /* Nothing should ever try to directly claim the IDX stream */
37 if (type
== CX18_ENC_STREAM_TYPE_IDX
) {
38 CX18_WARN("MPEG Index stream cannot be claimed directly, but something tried.\n");
42 if (test_and_set_bit(CX18_F_S_CLAIMED
, &s
->s_flags
)) {
43 /* someone already claimed this stream */
44 if (s
->id
== id
->open_id
) {
45 /* yes, this file descriptor did. So that's OK. */
48 if (s
->id
== -1 && type
== CX18_ENC_STREAM_TYPE_VBI
) {
49 /* VBI is handled already internally, now also assign
50 the file descriptor to this stream for external
51 reading of the stream. */
53 CX18_DEBUG_INFO("Start Read VBI\n");
56 /* someone else is using this stream already */
57 CX18_DEBUG_INFO("Stream %d is busy\n", type
);
63 * CX18_ENC_STREAM_TYPE_MPG needs to claim:
64 * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
65 * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
66 * (We don't yet fix up MPEG Index entries for our inserted packets).
68 * For all other streams we're done.
70 if (type
!= CX18_ENC_STREAM_TYPE_MPG
)
73 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
74 if (cx
->vbi
.insert_mpeg
&& !cx18_raw_vbi(cx
))
75 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
76 else if (!cx18_stream_enabled(s_assoc
))
79 set_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
81 /* mark that it is used internally */
82 set_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
);
85 EXPORT_SYMBOL(cx18_claim_stream
);
87 /* This function releases a previously claimed stream. It will take into
88 account associated VBI streams. */
89 void cx18_release_stream(struct cx18_stream
*s
)
91 struct cx18
*cx
= s
->cx
;
92 struct cx18_stream
*s_assoc
;
95 if (s
->type
== CX18_ENC_STREAM_TYPE_IDX
) {
97 * The IDX stream is only used internally, and can
98 * only be indirectly unclaimed by unclaiming the MPG stream.
103 if (s
->type
== CX18_ENC_STREAM_TYPE_VBI
&&
104 test_bit(CX18_F_S_INTERNAL_USE
, &s
->s_flags
)) {
105 /* this stream is still in use internally */
108 if (!test_and_clear_bit(CX18_F_S_CLAIMED
, &s
->s_flags
)) {
109 CX18_DEBUG_WARN("Release stream %s not in use!\n", s
->name
);
113 cx18_flush_queues(s
);
116 * CX18_ENC_STREAM_TYPE_MPG needs to release the
117 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
119 * For all other streams we're done.
121 if (s
->type
!= CX18_ENC_STREAM_TYPE_MPG
)
124 /* Unclaim the associated MPEG Index stream */
125 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
126 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
)) {
127 clear_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
128 cx18_flush_queues(s_assoc
);
131 /* Unclaim the associated VBI stream */
132 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
133 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
)) {
134 if (s_assoc
->id
== -1) {
136 * The VBI stream is not still claimed by a file
137 * descriptor, so completely unclaim it.
139 clear_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
140 cx18_flush_queues(s_assoc
);
144 EXPORT_SYMBOL(cx18_release_stream
);
146 static void cx18_dualwatch(struct cx18
*cx
)
148 struct v4l2_tuner vt
;
150 const u32 dual
= 0x0200;
152 new_stereo_mode
= v4l2_ctrl_g_ctrl(cx
->cxhdl
.audio_mode
);
153 memset(&vt
, 0, sizeof(vt
));
154 cx18_call_all(cx
, tuner
, g_tuner
, &vt
);
155 if (vt
.audmode
== V4L2_TUNER_MODE_LANG1_LANG2
&&
156 (vt
.rxsubchans
& V4L2_TUNER_SUB_LANG2
))
157 new_stereo_mode
= dual
;
159 if (new_stereo_mode
== cx
->dualwatch_stereo_mode
)
162 CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
163 cx
->dualwatch_stereo_mode
, new_stereo_mode
);
164 if (v4l2_ctrl_s_ctrl(cx
->cxhdl
.audio_mode
, new_stereo_mode
))
165 CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
169 static struct cx18_mdl
*cx18_get_mdl(struct cx18_stream
*s
, int non_block
,
172 struct cx18
*cx
= s
->cx
;
173 struct cx18_stream
*s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
174 struct cx18_mdl
*mdl
;
179 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
180 /* Process pending program updates and VBI data */
181 if (time_after(jiffies
, cx
->dualwatch_jiffies
+ msecs_to_jiffies(1000))) {
182 cx
->dualwatch_jiffies
= jiffies
;
185 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_vbi
->s_flags
) &&
186 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
187 while ((mdl
= cx18_dequeue(s_vbi
,
189 /* byteswap and process VBI data */
190 cx18_process_vbi_data(cx
, mdl
,
192 cx18_stream_put_mdl_fw(s_vbi
, mdl
);
195 mdl
= &cx
->vbi
.sliced_mpeg_mdl
;
196 if (mdl
->readpos
!= mdl
->bytesused
)
200 /* do we have new data? */
201 mdl
= cx18_dequeue(s
, &s
->q_full
);
203 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP
,
206 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
)
207 /* byteswap MPG data */
210 /* byteswap and process VBI data */
211 cx18_process_vbi_data(cx
, mdl
, s
->type
);
216 /* return if end of stream */
217 if (!test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
218 CX18_DEBUG_INFO("EOS %s\n", s
->name
);
222 /* return if file was opened with O_NONBLOCK */
228 /* wait for more data to arrive */
229 prepare_to_wait(&s
->waitq
, &wait
, TASK_INTERRUPTIBLE
);
230 /* New buffers might have become available before we were added
232 if (!atomic_read(&s
->q_full
.depth
))
234 finish_wait(&s
->waitq
, &wait
);
235 if (signal_pending(current
)) {
236 /* return if a signal was received */
237 CX18_DEBUG_INFO("User stopped %s\n", s
->name
);
244 static void cx18_setup_sliced_vbi_mdl(struct cx18
*cx
)
246 struct cx18_mdl
*mdl
= &cx
->vbi
.sliced_mpeg_mdl
;
247 struct cx18_buffer
*buf
= &cx
->vbi
.sliced_mpeg_buf
;
248 int idx
= cx
->vbi
.inserted_frame
% CX18_VBI_FRAMES
;
250 buf
->buf
= cx
->vbi
.sliced_mpeg_data
[idx
];
251 buf
->bytesused
= cx
->vbi
.sliced_mpeg_size
[idx
];
254 mdl
->curr_buf
= NULL
;
255 mdl
->bytesused
= cx
->vbi
.sliced_mpeg_size
[idx
];
259 static size_t cx18_copy_buf_to_user(struct cx18_stream
*s
,
260 struct cx18_buffer
*buf
, char __user
*ubuf
, size_t ucount
, bool *stop
)
262 struct cx18
*cx
= s
->cx
;
263 size_t len
= buf
->bytesused
- buf
->readpos
;
268 if (cx
->vbi
.insert_mpeg
&& s
->type
== CX18_ENC_STREAM_TYPE_MPG
&&
269 !cx18_raw_vbi(cx
) && buf
!= &cx
->vbi
.sliced_mpeg_buf
) {
271 * Try to find a good splice point in the PS, just before
272 * an MPEG-2 Program Pack start code, and provide only
273 * up to that point to the user, so it's easy to insert VBI data
274 * the next time around.
276 * This will not work for an MPEG-2 TS and has only been
277 * verified by analysis to work for an MPEG-2 PS. Helen Buus
278 * pointed out this works for the CX23416 MPEG-2 DVD compatible
279 * stream, and research indicates both the MPEG 2 SVCD and DVD
280 * stream types use an MPEG-2 PS container.
283 * An MPEG-2 Program Stream (PS) is a series of
284 * MPEG-2 Program Packs terminated by an
285 * MPEG Program End Code after the last Program Pack.
286 * A Program Pack may hold a PS System Header packet and any
287 * number of Program Elementary Stream (PES) Packets
289 const char *start
= buf
->buf
+ buf
->readpos
;
290 const char *p
= start
+ 1;
292 u8 ch
= cx
->search_pack_header
? 0xba : 0xe0;
295 while (start
+ len
> p
) {
296 /* Scan for a 0 to find a potential MPEG-2 start code */
297 q
= memchr(p
, 0, start
+ len
- p
);
302 * Keep looking if not a
303 * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba
304 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
306 if ((char *)q
+ 15 >= buf
->buf
+ buf
->bytesused
||
307 q
[1] != 0 || q
[2] != 1 || q
[3] != ch
)
310 /* If expecting the primary video PES */
311 if (!cx
->search_pack_header
) {
312 /* Continue if it couldn't be a PES packet */
313 if ((q
[6] & 0xc0) != 0x80)
315 /* Check if a PTS or PTS & DTS follow */
316 if (((q
[7] & 0xc0) == 0x80 && /* PTS only */
317 (q
[9] & 0xf0) == 0x20) || /* PTS only */
318 ((q
[7] & 0xc0) == 0xc0 && /* PTS & DTS */
319 (q
[9] & 0xf0) == 0x30)) { /* DTS follows */
320 /* Assume we found the video PES hdr */
321 ch
= 0xba; /* next want a Program Pack*/
322 cx
->search_pack_header
= 1;
323 p
= q
+ 9; /* Skip this video PES hdr */
328 /* We may have found a Program Pack start code */
330 /* Get the count of stuffing bytes & verify them */
331 stuffing
= q
[13] & 7;
332 /* all stuffing bytes must be 0xff */
333 for (i
= 0; i
< stuffing
; i
++)
334 if (q
[14 + i
] != 0xff)
336 if (i
== stuffing
&& /* right number of stuffing bytes*/
337 (q
[4] & 0xc4) == 0x44 && /* marker check */
338 (q
[12] & 3) == 3 && /* marker check */
339 q
[14 + stuffing
] == 0 && /* PES Pack or Sys Hdr */
340 q
[15 + stuffing
] == 0 &&
341 q
[16 + stuffing
] == 1) {
342 /* We declare we actually found a Program Pack*/
343 cx
->search_pack_header
= 0; /* expect vid PES */
344 len
= (char *)q
- start
;
345 cx18_setup_sliced_vbi_mdl(cx
);
351 if (copy_to_user(ubuf
, (u8
*)buf
->buf
+ buf
->readpos
, len
)) {
352 CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
357 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
&&
358 buf
!= &cx
->vbi
.sliced_mpeg_buf
)
359 cx
->mpg_data_received
+= len
;
363 static size_t cx18_copy_mdl_to_user(struct cx18_stream
*s
,
364 struct cx18_mdl
*mdl
, char __user
*ubuf
, size_t ucount
)
366 size_t tot_written
= 0;
370 if (mdl
->curr_buf
== NULL
)
371 mdl
->curr_buf
= list_first_entry(&mdl
->buf_list
,
372 struct cx18_buffer
, list
);
374 if (list_entry_is_past_end(mdl
->curr_buf
, &mdl
->buf_list
, list
)) {
376 * For some reason we've exhausted the buffers, but the MDL
377 * object still said some data was unread.
378 * Fix that and bail out.
380 mdl
->readpos
= mdl
->bytesused
;
384 list_for_each_entry_from(mdl
->curr_buf
, &mdl
->buf_list
, list
) {
386 if (mdl
->curr_buf
->readpos
>= mdl
->curr_buf
->bytesused
)
389 rc
= cx18_copy_buf_to_user(s
, mdl
->curr_buf
, ubuf
+ tot_written
,
390 ucount
- tot_written
, &stop
);
396 if (stop
|| /* Forced stopping point for VBI insertion */
397 tot_written
>= ucount
|| /* Reader request satisfied */
398 mdl
->curr_buf
->readpos
< mdl
->curr_buf
->bytesused
||
399 mdl
->readpos
>= mdl
->bytesused
) /* MDL buffers drained */
405 static ssize_t
cx18_read(struct cx18_stream
*s
, char __user
*ubuf
,
406 size_t tot_count
, int non_block
)
408 struct cx18
*cx
= s
->cx
;
409 size_t tot_written
= 0;
410 int single_frame
= 0;
412 if (atomic_read(&cx
->ana_capturing
) == 0 && s
->id
== -1) {
413 /* shouldn't happen */
414 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
419 /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
420 frames should arrive one-by-one, so make sure we never output more
421 than one VBI frame at a time */
422 if (s
->type
== CX18_ENC_STREAM_TYPE_VBI
&& !cx18_raw_vbi(cx
))
426 struct cx18_mdl
*mdl
;
429 mdl
= cx18_get_mdl(s
, non_block
, &rc
);
430 /* if there is no data available... */
432 /* if we got data, then return that regardless */
437 clear_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
438 clear_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
439 cx18_release_stream(s
);
445 rc
= cx18_copy_mdl_to_user(s
, mdl
, ubuf
+ tot_written
,
446 tot_count
- tot_written
);
448 if (mdl
!= &cx
->vbi
.sliced_mpeg_mdl
) {
449 if (mdl
->readpos
== mdl
->bytesused
)
450 cx18_stream_put_mdl_fw(s
, mdl
);
452 cx18_push(s
, mdl
, &s
->q_full
);
453 } else if (mdl
->readpos
== mdl
->bytesused
) {
454 int idx
= cx
->vbi
.inserted_frame
% CX18_VBI_FRAMES
;
456 cx
->vbi
.sliced_mpeg_size
[idx
] = 0;
457 cx
->vbi
.inserted_frame
++;
458 cx
->vbi_data_inserted
+= mdl
->bytesused
;
464 if (tot_written
== tot_count
|| single_frame
)
470 static ssize_t
cx18_read_pos(struct cx18_stream
*s
, char __user
*ubuf
,
471 size_t count
, loff_t
*pos
, int non_block
)
473 ssize_t rc
= count
? cx18_read(s
, ubuf
, count
, non_block
) : 0;
474 struct cx18
*cx
= s
->cx
;
476 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count
, s
->name
, rc
);
482 int cx18_start_capture(struct cx18_open_id
*id
)
484 struct cx18
*cx
= id
->cx
;
485 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
486 struct cx18_stream
*s_vbi
;
487 struct cx18_stream
*s_idx
;
489 if (s
->type
== CX18_ENC_STREAM_TYPE_RAD
) {
490 /* you cannot read from these stream types. */
494 /* Try to claim this stream. */
495 if (cx18_claim_stream(id
, s
->type
))
498 /* If capture is already in progress, then we also have to
500 if (test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
) ||
501 test_and_set_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
502 set_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
506 /* Start associated VBI or IDX stream capture if required */
507 s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
508 s_idx
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
509 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
511 * The VBI and IDX streams should have been claimed
512 * automatically, if for internal use, when the MPG stream was
513 * claimed. We only need to start these streams capturing.
515 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_idx
->s_flags
) &&
516 !test_and_set_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
517 if (cx18_start_v4l2_encode_stream(s_idx
)) {
518 CX18_DEBUG_WARN("IDX capture start failed\n");
519 clear_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
);
522 CX18_DEBUG_INFO("IDX capture started\n");
524 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_vbi
->s_flags
) &&
525 !test_and_set_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
)) {
526 if (cx18_start_v4l2_encode_stream(s_vbi
)) {
527 CX18_DEBUG_WARN("VBI capture start failed\n");
528 clear_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
);
531 CX18_DEBUG_INFO("VBI insertion started\n");
535 /* Tell the card to start capturing */
536 if (!cx18_start_v4l2_encode_stream(s
)) {
538 set_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
539 /* Resume a possibly paused encoder */
540 if (test_and_clear_bit(CX18_F_I_ENC_PAUSED
, &cx
->i_flags
))
541 cx18_vapi(cx
, CX18_CPU_CAPTURE_PAUSE
, 1, s
->handle
);
546 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s
->name
);
549 * The associated VBI and IDX streams for internal use are released
550 * automatically when the MPG stream is released. We only need to stop
551 * the associated stream.
553 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
554 /* Stop the IDX stream which is always for internal use */
555 if (test_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
556 cx18_stop_v4l2_encode_stream(s_idx
, 0);
557 clear_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
);
559 /* Stop the VBI stream, if only running for internal use */
560 if (test_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
) &&
561 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
562 cx18_stop_v4l2_encode_stream(s_vbi
, 0);
563 clear_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
);
566 clear_bit(CX18_F_S_STREAMING
, &s
->s_flags
);
567 cx18_release_stream(s
); /* Also releases associated streams */
571 ssize_t
cx18_v4l2_read(struct file
*filp
, char __user
*buf
, size_t count
,
574 struct cx18_open_id
*id
= file2id(filp
);
575 struct cx18
*cx
= id
->cx
;
576 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
579 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count
, s
->name
);
581 mutex_lock(&cx
->serialize_lock
);
582 rc
= cx18_start_capture(id
);
583 mutex_unlock(&cx
->serialize_lock
);
587 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
588 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
589 return videobuf_read_stream(&s
->vbuf_q
, buf
, count
, pos
, 0,
590 filp
->f_flags
& O_NONBLOCK
);
593 return cx18_read_pos(s
, buf
, count
, pos
, filp
->f_flags
& O_NONBLOCK
);
596 __poll_t
cx18_v4l2_enc_poll(struct file
*filp
, poll_table
*wait
)
598 __poll_t req_events
= poll_requested_events(wait
);
599 struct cx18_open_id
*id
= file2id(filp
);
600 struct cx18
*cx
= id
->cx
;
601 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
602 int eof
= test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
605 /* Start a capture if there is none */
606 if (!eof
&& !test_bit(CX18_F_S_STREAMING
, &s
->s_flags
) &&
607 (req_events
& (EPOLLIN
| EPOLLRDNORM
))) {
610 mutex_lock(&cx
->serialize_lock
);
611 rc
= cx18_start_capture(id
);
612 mutex_unlock(&cx
->serialize_lock
);
614 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
618 CX18_DEBUG_FILE("Encoder poll started capture\n");
621 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
622 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
623 __poll_t videobuf_poll
= videobuf_poll_stream(filp
, &s
->vbuf_q
, wait
);
625 if (v4l2_event_pending(&id
->fh
))
627 if (eof
&& videobuf_poll
== EPOLLERR
)
628 return res
| EPOLLHUP
;
629 return res
| videobuf_poll
;
632 /* add stream's waitq to the poll list */
633 CX18_DEBUG_HI_FILE("Encoder poll\n");
634 if (v4l2_event_pending(&id
->fh
))
637 poll_wait(filp
, &s
->waitq
, wait
);
639 if (atomic_read(&s
->q_full
.depth
))
640 return res
| EPOLLIN
| EPOLLRDNORM
;
642 return res
| EPOLLHUP
;
646 int cx18_v4l2_mmap(struct file
*file
, struct vm_area_struct
*vma
)
648 struct cx18_open_id
*id
= file
->private_data
;
649 struct cx18
*cx
= id
->cx
;
650 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
651 int eof
= test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
653 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
654 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
656 /* Start a capture if there is none */
657 if (!eof
&& !test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
660 mutex_lock(&cx
->serialize_lock
);
661 rc
= cx18_start_capture(id
);
662 mutex_unlock(&cx
->serialize_lock
);
665 "Could not start capture for %s (%d)\n",
669 CX18_DEBUG_FILE("Encoder mmap started capture\n");
672 return videobuf_mmap_mapper(&s
->vbuf_q
, vma
);
678 void cx18_vb_timeout(struct timer_list
*t
)
680 struct cx18_stream
*s
= from_timer(s
, t
, vb_timeout
);
681 struct cx18_videobuf_buffer
*buf
;
684 /* Return all of the buffers in error state, so the vbi/vid inode
685 * can return from blocking.
687 spin_lock_irqsave(&s
->vb_lock
, flags
);
688 while (!list_empty(&s
->vb_capture
)) {
689 buf
= list_entry(s
->vb_capture
.next
,
690 struct cx18_videobuf_buffer
, vb
.queue
);
691 list_del(&buf
->vb
.queue
);
692 buf
->vb
.state
= VIDEOBUF_ERROR
;
693 wake_up(&buf
->vb
.done
);
695 spin_unlock_irqrestore(&s
->vb_lock
, flags
);
698 void cx18_stop_capture(struct cx18_open_id
*id
, int gop_end
)
700 struct cx18
*cx
= id
->cx
;
701 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
702 struct cx18_stream
*s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
703 struct cx18_stream
*s_idx
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
705 CX18_DEBUG_IOCTL("close() of %s\n", s
->name
);
707 /* 'Unclaim' this stream */
710 if (test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
711 CX18_DEBUG_INFO("close stopping capture\n");
712 if (id
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
713 /* Stop internal use associated VBI and IDX streams */
714 if (test_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
) &&
715 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
716 CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
717 cx18_stop_v4l2_encode_stream(s_vbi
, 0);
719 if (test_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
720 CX18_DEBUG_INFO("close stopping IDX capture\n");
721 cx18_stop_v4l2_encode_stream(s_idx
, 0);
724 if (id
->type
== CX18_ENC_STREAM_TYPE_VBI
&&
725 test_bit(CX18_F_S_INTERNAL_USE
, &s
->s_flags
))
726 /* Also used internally, don't stop capturing */
729 cx18_stop_v4l2_encode_stream(s
, gop_end
);
732 clear_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
733 clear_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
734 cx18_release_stream(s
);
738 int cx18_v4l2_close(struct file
*filp
)
740 struct v4l2_fh
*fh
= filp
->private_data
;
741 struct cx18_open_id
*id
= fh2id(fh
);
742 struct cx18
*cx
= id
->cx
;
743 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
745 CX18_DEBUG_IOCTL("close() of %s\n", s
->name
);
747 mutex_lock(&cx
->serialize_lock
);
749 if (id
->type
== CX18_ENC_STREAM_TYPE_RAD
&&
750 v4l2_fh_is_singular_file(filp
)) {
751 /* Closing radio device, return to TV mode */
753 /* Mark that the radio is no longer in use */
754 clear_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
);
755 /* Switch tuner to TV */
756 cx18_call_all(cx
, video
, s_std
, cx
->std
);
757 /* Select correct audio input (i.e. TV tuner or Line in) */
758 cx18_audio_set_io(cx
);
759 if (atomic_read(&cx
->ana_capturing
) > 0) {
760 /* Undo video mute */
761 cx18_vapi(cx
, CX18_CPU_SET_VIDEO_MUTE
, 2, s
->handle
,
762 (v4l2_ctrl_g_ctrl(cx
->cxhdl
.video_mute
) |
763 (v4l2_ctrl_g_ctrl(cx
->cxhdl
.video_mute_yuv
) << 8)));
765 /* Done! Unmute and continue. */
772 /* 'Unclaim' this stream */
773 if (s
->id
== id
->open_id
)
774 cx18_stop_capture(id
, 0);
776 mutex_unlock(&cx
->serialize_lock
);
780 static int cx18_serialized_open(struct cx18_stream
*s
, struct file
*filp
)
782 struct cx18
*cx
= s
->cx
;
783 struct cx18_open_id
*item
;
785 CX18_DEBUG_FILE("open %s\n", s
->name
);
787 /* Allocate memory */
788 item
= kzalloc(sizeof(struct cx18_open_id
), GFP_KERNEL
);
790 CX18_DEBUG_WARN("nomem on v4l2 open\n");
793 v4l2_fh_init(&item
->fh
, &s
->video_dev
);
796 item
->type
= s
->type
;
798 item
->open_id
= cx
->open_id
++;
799 filp
->private_data
= &item
->fh
;
800 v4l2_fh_add(&item
->fh
);
802 if (item
->type
== CX18_ENC_STREAM_TYPE_RAD
&&
803 v4l2_fh_is_singular_file(filp
)) {
804 if (!test_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
)) {
805 if (atomic_read(&cx
->ana_capturing
) > 0) {
806 /* switching to radio while capture is
807 in progress is not polite */
808 v4l2_fh_del(&item
->fh
);
809 v4l2_fh_exit(&item
->fh
);
815 /* Mark that the radio is being used. */
816 set_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
);
817 /* We have the radio */
819 /* Switch tuner to radio */
820 cx18_call_all(cx
, tuner
, s_radio
);
821 /* Select the correct audio input (i.e. radio tuner) */
822 cx18_audio_set_io(cx
);
823 /* Done! Unmute and continue. */
829 int cx18_v4l2_open(struct file
*filp
)
832 struct video_device
*video_dev
= video_devdata(filp
);
833 struct cx18_stream
*s
= video_get_drvdata(video_dev
);
834 struct cx18
*cx
= s
->cx
;
836 mutex_lock(&cx
->serialize_lock
);
837 if (cx18_init_on_first_open(cx
)) {
838 CX18_ERR("Failed to initialize on %s\n",
839 video_device_node_name(video_dev
));
840 mutex_unlock(&cx
->serialize_lock
);
843 res
= cx18_serialized_open(s
, filp
);
844 mutex_unlock(&cx
->serialize_lock
);
848 void cx18_mute(struct cx18
*cx
)
851 if (atomic_read(&cx
->ana_capturing
)) {
852 h
= cx18_find_handle(cx
);
853 if (h
!= CX18_INVALID_TASK_HANDLE
)
854 cx18_vapi(cx
, CX18_CPU_SET_AUDIO_MUTE
, 2, h
, 1);
856 CX18_ERR("Can't find valid task handle for mute\n");
858 CX18_DEBUG_INFO("Mute\n");
861 void cx18_unmute(struct cx18
*cx
)
864 if (atomic_read(&cx
->ana_capturing
)) {
865 h
= cx18_find_handle(cx
);
866 if (h
!= CX18_INVALID_TASK_HANDLE
) {
867 cx18_msleep_timeout(100, 0);
868 cx18_vapi(cx
, CX18_CPU_SET_MISC_PARAMETERS
, 2, h
, 12);
869 cx18_vapi(cx
, CX18_CPU_SET_AUDIO_MUTE
, 2, h
, 0);
871 CX18_ERR("Can't find valid task handle for unmute\n");
873 CX18_DEBUG_INFO("Unmute\n");