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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 #include "cx18-driver.h"
26 #include "cx18-fileops.h"
28 #include "cx18-queue.h"
30 #include "cx18-audio.h"
31 #include "cx18-mailbox.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>
39 /* This function tries to claim the stream for a specific file descriptor.
40 If no one else is using this stream then the stream is claimed and
41 associated VBI and IDX streams are also automatically claimed.
42 Possible error returns: -EBUSY if someone else has claimed
43 the stream or 0 on success. */
44 int cx18_claim_stream(struct cx18_open_id
*id
, int type
)
46 struct cx18
*cx
= id
->cx
;
47 struct cx18_stream
*s
= &cx
->streams
[type
];
48 struct cx18_stream
*s_assoc
;
50 /* Nothing should ever try to directly claim the IDX stream */
51 if (type
== CX18_ENC_STREAM_TYPE_IDX
) {
52 CX18_WARN("MPEG Index stream cannot be claimed directly, but something tried.\n");
56 if (test_and_set_bit(CX18_F_S_CLAIMED
, &s
->s_flags
)) {
57 /* someone already claimed this stream */
58 if (s
->id
== id
->open_id
) {
59 /* yes, this file descriptor did. So that's OK. */
62 if (s
->id
== -1 && type
== CX18_ENC_STREAM_TYPE_VBI
) {
63 /* VBI is handled already internally, now also assign
64 the file descriptor to this stream for external
65 reading of the stream. */
67 CX18_DEBUG_INFO("Start Read VBI\n");
70 /* someone else is using this stream already */
71 CX18_DEBUG_INFO("Stream %d is busy\n", type
);
77 * CX18_ENC_STREAM_TYPE_MPG needs to claim:
78 * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
79 * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
80 * (We don't yet fix up MPEG Index entries for our inserted packets).
82 * For all other streams we're done.
84 if (type
!= CX18_ENC_STREAM_TYPE_MPG
)
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
))
93 set_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
95 /* mark that it is used internally */
96 set_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
);
99 EXPORT_SYMBOL(cx18_claim_stream
);
101 /* This function releases a previously claimed stream. It will take into
102 account associated VBI streams. */
103 void cx18_release_stream(struct cx18_stream
*s
)
105 struct cx18
*cx
= s
->cx
;
106 struct cx18_stream
*s_assoc
;
109 if (s
->type
== CX18_ENC_STREAM_TYPE_IDX
) {
111 * The IDX stream is only used internally, and can
112 * only be indirectly unclaimed by unclaiming the MPG stream.
117 if (s
->type
== CX18_ENC_STREAM_TYPE_VBI
&&
118 test_bit(CX18_F_S_INTERNAL_USE
, &s
->s_flags
)) {
119 /* this stream is still in use internally */
122 if (!test_and_clear_bit(CX18_F_S_CLAIMED
, &s
->s_flags
)) {
123 CX18_DEBUG_WARN("Release stream %s not in use!\n", s
->name
);
127 cx18_flush_queues(s
);
130 * CX18_ENC_STREAM_TYPE_MPG needs to release the
131 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
133 * For all other streams we're done.
135 if (s
->type
!= CX18_ENC_STREAM_TYPE_MPG
)
138 /* Unclaim the associated MPEG Index stream */
139 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
140 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
)) {
141 clear_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
142 cx18_flush_queues(s_assoc
);
145 /* Unclaim the associated VBI stream */
146 s_assoc
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
147 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE
, &s_assoc
->s_flags
)) {
148 if (s_assoc
->id
== -1) {
150 * The VBI stream is not still claimed by a file
151 * descriptor, so completely unclaim it.
153 clear_bit(CX18_F_S_CLAIMED
, &s_assoc
->s_flags
);
154 cx18_flush_queues(s_assoc
);
158 EXPORT_SYMBOL(cx18_release_stream
);
160 static void cx18_dualwatch(struct cx18
*cx
)
162 struct v4l2_tuner vt
;
164 const u32 dual
= 0x0200;
166 new_stereo_mode
= v4l2_ctrl_g_ctrl(cx
->cxhdl
.audio_mode
);
167 memset(&vt
, 0, sizeof(vt
));
168 cx18_call_all(cx
, tuner
, g_tuner
, &vt
);
169 if (vt
.audmode
== V4L2_TUNER_MODE_LANG1_LANG2
&&
170 (vt
.rxsubchans
& V4L2_TUNER_SUB_LANG2
))
171 new_stereo_mode
= dual
;
173 if (new_stereo_mode
== cx
->dualwatch_stereo_mode
)
176 CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
177 cx
->dualwatch_stereo_mode
, new_stereo_mode
);
178 if (v4l2_ctrl_s_ctrl(cx
->cxhdl
.audio_mode
, new_stereo_mode
))
179 CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
183 static struct cx18_mdl
*cx18_get_mdl(struct cx18_stream
*s
, int non_block
,
186 struct cx18
*cx
= s
->cx
;
187 struct cx18_stream
*s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
188 struct cx18_mdl
*mdl
;
193 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
194 /* Process pending program updates and VBI data */
195 if (time_after(jiffies
, cx
->dualwatch_jiffies
+ msecs_to_jiffies(1000))) {
196 cx
->dualwatch_jiffies
= jiffies
;
199 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_vbi
->s_flags
) &&
200 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
201 while ((mdl
= cx18_dequeue(s_vbi
,
203 /* byteswap and process VBI data */
204 cx18_process_vbi_data(cx
, mdl
,
206 cx18_stream_put_mdl_fw(s_vbi
, mdl
);
209 mdl
= &cx
->vbi
.sliced_mpeg_mdl
;
210 if (mdl
->readpos
!= mdl
->bytesused
)
214 /* do we have new data? */
215 mdl
= cx18_dequeue(s
, &s
->q_full
);
217 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP
,
220 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
)
221 /* byteswap MPG data */
224 /* byteswap and process VBI data */
225 cx18_process_vbi_data(cx
, mdl
, s
->type
);
230 /* return if end of stream */
231 if (!test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
232 CX18_DEBUG_INFO("EOS %s\n", s
->name
);
236 /* return if file was opened with O_NONBLOCK */
242 /* wait for more data to arrive */
243 prepare_to_wait(&s
->waitq
, &wait
, TASK_INTERRUPTIBLE
);
244 /* New buffers might have become available before we were added
246 if (!atomic_read(&s
->q_full
.depth
))
248 finish_wait(&s
->waitq
, &wait
);
249 if (signal_pending(current
)) {
250 /* return if a signal was received */
251 CX18_DEBUG_INFO("User stopped %s\n", s
->name
);
258 static void cx18_setup_sliced_vbi_mdl(struct cx18
*cx
)
260 struct cx18_mdl
*mdl
= &cx
->vbi
.sliced_mpeg_mdl
;
261 struct cx18_buffer
*buf
= &cx
->vbi
.sliced_mpeg_buf
;
262 int idx
= cx
->vbi
.inserted_frame
% CX18_VBI_FRAMES
;
264 buf
->buf
= cx
->vbi
.sliced_mpeg_data
[idx
];
265 buf
->bytesused
= cx
->vbi
.sliced_mpeg_size
[idx
];
268 mdl
->curr_buf
= NULL
;
269 mdl
->bytesused
= cx
->vbi
.sliced_mpeg_size
[idx
];
273 static size_t cx18_copy_buf_to_user(struct cx18_stream
*s
,
274 struct cx18_buffer
*buf
, char __user
*ubuf
, size_t ucount
, bool *stop
)
276 struct cx18
*cx
= s
->cx
;
277 size_t len
= buf
->bytesused
- buf
->readpos
;
282 if (cx
->vbi
.insert_mpeg
&& s
->type
== CX18_ENC_STREAM_TYPE_MPG
&&
283 !cx18_raw_vbi(cx
) && buf
!= &cx
->vbi
.sliced_mpeg_buf
) {
285 * Try to find a good splice point in the PS, just before
286 * an MPEG-2 Program Pack start code, and provide only
287 * up to that point to the user, so it's easy to insert VBI data
288 * the next time around.
290 * This will not work for an MPEG-2 TS and has only been
291 * verified by analysis to work for an MPEG-2 PS. Helen Buus
292 * pointed out this works for the CX23416 MPEG-2 DVD compatible
293 * stream, and research indicates both the MPEG 2 SVCD and DVD
294 * stream types use an MPEG-2 PS container.
297 * An MPEG-2 Program Stream (PS) is a series of
298 * MPEG-2 Program Packs terminated by an
299 * MPEG Program End Code after the last Program Pack.
300 * A Program Pack may hold a PS System Header packet and any
301 * number of Program Elementary Stream (PES) Packets
303 const char *start
= buf
->buf
+ buf
->readpos
;
304 const char *p
= start
+ 1;
306 u8 ch
= cx
->search_pack_header
? 0xba : 0xe0;
309 while (start
+ len
> p
) {
310 /* Scan for a 0 to find a potential MPEG-2 start code */
311 q
= memchr(p
, 0, start
+ len
- p
);
316 * Keep looking if not a
317 * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba
318 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
320 if ((char *)q
+ 15 >= buf
->buf
+ buf
->bytesused
||
321 q
[1] != 0 || q
[2] != 1 || q
[3] != ch
)
324 /* If expecting the primary video PES */
325 if (!cx
->search_pack_header
) {
326 /* Continue if it couldn't be a PES packet */
327 if ((q
[6] & 0xc0) != 0x80)
329 /* Check if a PTS or PTS & DTS follow */
330 if (((q
[7] & 0xc0) == 0x80 && /* PTS only */
331 (q
[9] & 0xf0) == 0x20) || /* PTS only */
332 ((q
[7] & 0xc0) == 0xc0 && /* PTS & DTS */
333 (q
[9] & 0xf0) == 0x30)) { /* DTS follows */
334 /* Assume we found the video PES hdr */
335 ch
= 0xba; /* next want a Program Pack*/
336 cx
->search_pack_header
= 1;
337 p
= q
+ 9; /* Skip this video PES hdr */
342 /* We may have found a Program Pack start code */
344 /* Get the count of stuffing bytes & verify them */
345 stuffing
= q
[13] & 7;
346 /* all stuffing bytes must be 0xff */
347 for (i
= 0; i
< stuffing
; i
++)
348 if (q
[14 + i
] != 0xff)
350 if (i
== stuffing
&& /* right number of stuffing bytes*/
351 (q
[4] & 0xc4) == 0x44 && /* marker check */
352 (q
[12] & 3) == 3 && /* marker check */
353 q
[14 + stuffing
] == 0 && /* PES Pack or Sys Hdr */
354 q
[15 + stuffing
] == 0 &&
355 q
[16 + stuffing
] == 1) {
356 /* We declare we actually found a Program Pack*/
357 cx
->search_pack_header
= 0; /* expect vid PES */
358 len
= (char *)q
- start
;
359 cx18_setup_sliced_vbi_mdl(cx
);
365 if (copy_to_user(ubuf
, (u8
*)buf
->buf
+ buf
->readpos
, len
)) {
366 CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
371 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
&&
372 buf
!= &cx
->vbi
.sliced_mpeg_buf
)
373 cx
->mpg_data_received
+= len
;
377 static size_t cx18_copy_mdl_to_user(struct cx18_stream
*s
,
378 struct cx18_mdl
*mdl
, char __user
*ubuf
, size_t ucount
)
380 size_t tot_written
= 0;
384 if (mdl
->curr_buf
== NULL
)
385 mdl
->curr_buf
= list_first_entry(&mdl
->buf_list
,
386 struct cx18_buffer
, list
);
388 if (list_entry_is_past_end(mdl
->curr_buf
, &mdl
->buf_list
, list
)) {
390 * For some reason we've exhausted the buffers, but the MDL
391 * object still said some data was unread.
392 * Fix that and bail out.
394 mdl
->readpos
= mdl
->bytesused
;
398 list_for_each_entry_from(mdl
->curr_buf
, &mdl
->buf_list
, list
) {
400 if (mdl
->curr_buf
->readpos
>= mdl
->curr_buf
->bytesused
)
403 rc
= cx18_copy_buf_to_user(s
, mdl
->curr_buf
, ubuf
+ tot_written
,
404 ucount
- tot_written
, &stop
);
410 if (stop
|| /* Forced stopping point for VBI insertion */
411 tot_written
>= ucount
|| /* Reader request statisfied */
412 mdl
->curr_buf
->readpos
< mdl
->curr_buf
->bytesused
||
413 mdl
->readpos
>= mdl
->bytesused
) /* MDL buffers drained */
419 static ssize_t
cx18_read(struct cx18_stream
*s
, char __user
*ubuf
,
420 size_t tot_count
, int non_block
)
422 struct cx18
*cx
= s
->cx
;
423 size_t tot_written
= 0;
424 int single_frame
= 0;
426 if (atomic_read(&cx
->ana_capturing
) == 0 && s
->id
== -1) {
427 /* shouldn't happen */
428 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
433 /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
434 frames should arrive one-by-one, so make sure we never output more
435 than one VBI frame at a time */
436 if (s
->type
== CX18_ENC_STREAM_TYPE_VBI
&& !cx18_raw_vbi(cx
))
440 struct cx18_mdl
*mdl
;
443 mdl
= cx18_get_mdl(s
, non_block
, &rc
);
444 /* if there is no data available... */
446 /* if we got data, then return that regardless */
451 clear_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
452 clear_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
453 cx18_release_stream(s
);
459 rc
= cx18_copy_mdl_to_user(s
, mdl
, ubuf
+ tot_written
,
460 tot_count
- tot_written
);
462 if (mdl
!= &cx
->vbi
.sliced_mpeg_mdl
) {
463 if (mdl
->readpos
== mdl
->bytesused
)
464 cx18_stream_put_mdl_fw(s
, mdl
);
466 cx18_push(s
, mdl
, &s
->q_full
);
467 } else if (mdl
->readpos
== mdl
->bytesused
) {
468 int idx
= cx
->vbi
.inserted_frame
% CX18_VBI_FRAMES
;
470 cx
->vbi
.sliced_mpeg_size
[idx
] = 0;
471 cx
->vbi
.inserted_frame
++;
472 cx
->vbi_data_inserted
+= mdl
->bytesused
;
478 if (tot_written
== tot_count
|| single_frame
)
484 static ssize_t
cx18_read_pos(struct cx18_stream
*s
, char __user
*ubuf
,
485 size_t count
, loff_t
*pos
, int non_block
)
487 ssize_t rc
= count
? cx18_read(s
, ubuf
, count
, non_block
) : 0;
488 struct cx18
*cx
= s
->cx
;
490 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count
, s
->name
, rc
);
496 int cx18_start_capture(struct cx18_open_id
*id
)
498 struct cx18
*cx
= id
->cx
;
499 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
500 struct cx18_stream
*s_vbi
;
501 struct cx18_stream
*s_idx
;
503 if (s
->type
== CX18_ENC_STREAM_TYPE_RAD
) {
504 /* you cannot read from these stream types. */
508 /* Try to claim this stream. */
509 if (cx18_claim_stream(id
, s
->type
))
512 /* If capture is already in progress, then we also have to
514 if (test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
) ||
515 test_and_set_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
516 set_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
520 /* Start associated VBI or IDX stream capture if required */
521 s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
522 s_idx
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
523 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
525 * The VBI and IDX streams should have been claimed
526 * automatically, if for internal use, when the MPG stream was
527 * claimed. We only need to start these streams capturing.
529 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_idx
->s_flags
) &&
530 !test_and_set_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
531 if (cx18_start_v4l2_encode_stream(s_idx
)) {
532 CX18_DEBUG_WARN("IDX capture start failed\n");
533 clear_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
);
536 CX18_DEBUG_INFO("IDX capture started\n");
538 if (test_bit(CX18_F_S_INTERNAL_USE
, &s_vbi
->s_flags
) &&
539 !test_and_set_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
)) {
540 if (cx18_start_v4l2_encode_stream(s_vbi
)) {
541 CX18_DEBUG_WARN("VBI capture start failed\n");
542 clear_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
);
545 CX18_DEBUG_INFO("VBI insertion started\n");
549 /* Tell the card to start capturing */
550 if (!cx18_start_v4l2_encode_stream(s
)) {
552 set_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
553 /* Resume a possibly paused encoder */
554 if (test_and_clear_bit(CX18_F_I_ENC_PAUSED
, &cx
->i_flags
))
555 cx18_vapi(cx
, CX18_CPU_CAPTURE_PAUSE
, 1, s
->handle
);
560 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s
->name
);
563 * The associated VBI and IDX streams for internal use are released
564 * automatically when the MPG stream is released. We only need to stop
565 * the associated stream.
567 if (s
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
568 /* Stop the IDX stream which is always for internal use */
569 if (test_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
570 cx18_stop_v4l2_encode_stream(s_idx
, 0);
571 clear_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
);
573 /* Stop the VBI stream, if only running for internal use */
574 if (test_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
) &&
575 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
576 cx18_stop_v4l2_encode_stream(s_vbi
, 0);
577 clear_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
);
580 clear_bit(CX18_F_S_STREAMING
, &s
->s_flags
);
581 cx18_release_stream(s
); /* Also releases associated streams */
585 ssize_t
cx18_v4l2_read(struct file
*filp
, char __user
*buf
, size_t count
,
588 struct cx18_open_id
*id
= file2id(filp
);
589 struct cx18
*cx
= id
->cx
;
590 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
593 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count
, s
->name
);
595 mutex_lock(&cx
->serialize_lock
);
596 rc
= cx18_start_capture(id
);
597 mutex_unlock(&cx
->serialize_lock
);
601 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
602 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
603 return videobuf_read_stream(&s
->vbuf_q
, buf
, count
, pos
, 0,
604 filp
->f_flags
& O_NONBLOCK
);
607 return cx18_read_pos(s
, buf
, count
, pos
, filp
->f_flags
& O_NONBLOCK
);
610 unsigned int cx18_v4l2_enc_poll(struct file
*filp
, poll_table
*wait
)
612 unsigned long req_events
= poll_requested_events(wait
);
613 struct cx18_open_id
*id
= file2id(filp
);
614 struct cx18
*cx
= id
->cx
;
615 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
616 int eof
= test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
619 /* Start a capture if there is none */
620 if (!eof
&& !test_bit(CX18_F_S_STREAMING
, &s
->s_flags
) &&
621 (req_events
& (POLLIN
| POLLRDNORM
))) {
624 mutex_lock(&cx
->serialize_lock
);
625 rc
= cx18_start_capture(id
);
626 mutex_unlock(&cx
->serialize_lock
);
628 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
632 CX18_DEBUG_FILE("Encoder poll started capture\n");
635 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
636 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
637 int videobuf_poll
= videobuf_poll_stream(filp
, &s
->vbuf_q
, wait
);
639 if (v4l2_event_pending(&id
->fh
))
641 if (eof
&& videobuf_poll
== POLLERR
)
642 return res
| POLLHUP
;
643 return res
| videobuf_poll
;
646 /* add stream's waitq to the poll list */
647 CX18_DEBUG_HI_FILE("Encoder poll\n");
648 if (v4l2_event_pending(&id
->fh
))
651 poll_wait(filp
, &s
->waitq
, wait
);
653 if (atomic_read(&s
->q_full
.depth
))
654 return res
| POLLIN
| POLLRDNORM
;
656 return res
| POLLHUP
;
660 int cx18_v4l2_mmap(struct file
*file
, struct vm_area_struct
*vma
)
662 struct cx18_open_id
*id
= file
->private_data
;
663 struct cx18
*cx
= id
->cx
;
664 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
665 int eof
= test_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
667 if ((s
->vb_type
== V4L2_BUF_TYPE_VIDEO_CAPTURE
) &&
668 (id
->type
== CX18_ENC_STREAM_TYPE_YUV
)) {
670 /* Start a capture if there is none */
671 if (!eof
&& !test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
674 mutex_lock(&cx
->serialize_lock
);
675 rc
= cx18_start_capture(id
);
676 mutex_unlock(&cx
->serialize_lock
);
679 "Could not start capture for %s (%d)\n",
683 CX18_DEBUG_FILE("Encoder mmap started capture\n");
686 return videobuf_mmap_mapper(&s
->vbuf_q
, vma
);
692 void cx18_vb_timeout(unsigned long data
)
694 struct cx18_stream
*s
= (struct cx18_stream
*)data
;
695 struct cx18_videobuf_buffer
*buf
;
698 /* Return all of the buffers in error state, so the vbi/vid inode
699 * can return from blocking.
701 spin_lock_irqsave(&s
->vb_lock
, flags
);
702 while (!list_empty(&s
->vb_capture
)) {
703 buf
= list_entry(s
->vb_capture
.next
,
704 struct cx18_videobuf_buffer
, vb
.queue
);
705 list_del(&buf
->vb
.queue
);
706 buf
->vb
.state
= VIDEOBUF_ERROR
;
707 wake_up(&buf
->vb
.done
);
709 spin_unlock_irqrestore(&s
->vb_lock
, flags
);
712 void cx18_stop_capture(struct cx18_open_id
*id
, int gop_end
)
714 struct cx18
*cx
= id
->cx
;
715 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
716 struct cx18_stream
*s_vbi
= &cx
->streams
[CX18_ENC_STREAM_TYPE_VBI
];
717 struct cx18_stream
*s_idx
= &cx
->streams
[CX18_ENC_STREAM_TYPE_IDX
];
719 CX18_DEBUG_IOCTL("close() of %s\n", s
->name
);
721 /* 'Unclaim' this stream */
724 if (test_bit(CX18_F_S_STREAMING
, &s
->s_flags
)) {
725 CX18_DEBUG_INFO("close stopping capture\n");
726 if (id
->type
== CX18_ENC_STREAM_TYPE_MPG
) {
727 /* Stop internal use associated VBI and IDX streams */
728 if (test_bit(CX18_F_S_STREAMING
, &s_vbi
->s_flags
) &&
729 !test_bit(CX18_F_S_APPL_IO
, &s_vbi
->s_flags
)) {
730 CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
731 cx18_stop_v4l2_encode_stream(s_vbi
, 0);
733 if (test_bit(CX18_F_S_STREAMING
, &s_idx
->s_flags
)) {
734 CX18_DEBUG_INFO("close stopping IDX capture\n");
735 cx18_stop_v4l2_encode_stream(s_idx
, 0);
738 if (id
->type
== CX18_ENC_STREAM_TYPE_VBI
&&
739 test_bit(CX18_F_S_INTERNAL_USE
, &s
->s_flags
))
740 /* Also used internally, don't stop capturing */
743 cx18_stop_v4l2_encode_stream(s
, gop_end
);
746 clear_bit(CX18_F_S_APPL_IO
, &s
->s_flags
);
747 clear_bit(CX18_F_S_STREAMOFF
, &s
->s_flags
);
748 cx18_release_stream(s
);
752 int cx18_v4l2_close(struct file
*filp
)
754 struct v4l2_fh
*fh
= filp
->private_data
;
755 struct cx18_open_id
*id
= fh2id(fh
);
756 struct cx18
*cx
= id
->cx
;
757 struct cx18_stream
*s
= &cx
->streams
[id
->type
];
759 CX18_DEBUG_IOCTL("close() of %s\n", s
->name
);
761 mutex_lock(&cx
->serialize_lock
);
763 if (id
->type
== CX18_ENC_STREAM_TYPE_RAD
&&
764 v4l2_fh_is_singular_file(filp
)) {
765 /* Closing radio device, return to TV mode */
767 /* Mark that the radio is no longer in use */
768 clear_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
);
769 /* Switch tuner to TV */
770 cx18_call_all(cx
, video
, s_std
, cx
->std
);
771 /* Select correct audio input (i.e. TV tuner or Line in) */
772 cx18_audio_set_io(cx
);
773 if (atomic_read(&cx
->ana_capturing
) > 0) {
774 /* Undo video mute */
775 cx18_vapi(cx
, CX18_CPU_SET_VIDEO_MUTE
, 2, s
->handle
,
776 (v4l2_ctrl_g_ctrl(cx
->cxhdl
.video_mute
) |
777 (v4l2_ctrl_g_ctrl(cx
->cxhdl
.video_mute_yuv
) << 8)));
779 /* Done! Unmute and continue. */
786 /* 'Unclaim' this stream */
787 if (s
->id
== id
->open_id
)
788 cx18_stop_capture(id
, 0);
790 mutex_unlock(&cx
->serialize_lock
);
794 static int cx18_serialized_open(struct cx18_stream
*s
, struct file
*filp
)
796 struct cx18
*cx
= s
->cx
;
797 struct cx18_open_id
*item
;
799 CX18_DEBUG_FILE("open %s\n", s
->name
);
801 /* Allocate memory */
802 item
= kzalloc(sizeof(struct cx18_open_id
), GFP_KERNEL
);
804 CX18_DEBUG_WARN("nomem on v4l2 open\n");
807 v4l2_fh_init(&item
->fh
, &s
->video_dev
);
810 item
->type
= s
->type
;
812 item
->open_id
= cx
->open_id
++;
813 filp
->private_data
= &item
->fh
;
814 v4l2_fh_add(&item
->fh
);
816 if (item
->type
== CX18_ENC_STREAM_TYPE_RAD
&&
817 v4l2_fh_is_singular_file(filp
)) {
818 if (!test_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
)) {
819 if (atomic_read(&cx
->ana_capturing
) > 0) {
820 /* switching to radio while capture is
821 in progress is not polite */
822 v4l2_fh_del(&item
->fh
);
823 v4l2_fh_exit(&item
->fh
);
829 /* Mark that the radio is being used. */
830 set_bit(CX18_F_I_RADIO_USER
, &cx
->i_flags
);
831 /* We have the radio */
833 /* Switch tuner to radio */
834 cx18_call_all(cx
, tuner
, s_radio
);
835 /* Select the correct audio input (i.e. radio tuner) */
836 cx18_audio_set_io(cx
);
837 /* Done! Unmute and continue. */
843 int cx18_v4l2_open(struct file
*filp
)
846 struct video_device
*video_dev
= video_devdata(filp
);
847 struct cx18_stream
*s
= video_get_drvdata(video_dev
);
848 struct cx18
*cx
= s
->cx
;
850 mutex_lock(&cx
->serialize_lock
);
851 if (cx18_init_on_first_open(cx
)) {
852 CX18_ERR("Failed to initialize on %s\n",
853 video_device_node_name(video_dev
));
854 mutex_unlock(&cx
->serialize_lock
);
857 res
= cx18_serialized_open(s
, filp
);
858 mutex_unlock(&cx
->serialize_lock
);
862 void cx18_mute(struct cx18
*cx
)
865 if (atomic_read(&cx
->ana_capturing
)) {
866 h
= cx18_find_handle(cx
);
867 if (h
!= CX18_INVALID_TASK_HANDLE
)
868 cx18_vapi(cx
, CX18_CPU_SET_AUDIO_MUTE
, 2, h
, 1);
870 CX18_ERR("Can't find valid task handle for mute\n");
872 CX18_DEBUG_INFO("Mute\n");
875 void cx18_unmute(struct cx18
*cx
)
878 if (atomic_read(&cx
->ana_capturing
)) {
879 h
= cx18_find_handle(cx
);
880 if (h
!= CX18_INVALID_TASK_HANDLE
) {
881 cx18_msleep_timeout(100, 0);
882 cx18_vapi(cx
, CX18_CPU_SET_MISC_PARAMETERS
, 2, h
, 12);
883 cx18_vapi(cx
, CX18_CPU_SET_AUDIO_MUTE
, 2, h
, 0);
885 CX18_ERR("Can't find valid task handle for unmute\n");
887 CX18_DEBUG_INFO("Unmute\n");