V4L/DVB (13906): cx18: Start IDX streams automatically as an internal associated...
[linux-2.6/cjktty.git] / drivers / media / video / cx18 / cx18-fileops.c
blobb1ad03f61019b69b0c591dcfca74b136fc5502e2
1 /*
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@radix.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
22 * 02111-1307 USA
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"
38 /* This function tries to claim the stream for a specific file descriptor.
39 If no one else is using this stream then the stream is claimed and
40 associated VBI and IDX streams are also automatically claimed.
41 Possible error returns: -EBUSY if someone else has claimed
42 the stream or 0 on success. */
43 static int cx18_claim_stream(struct cx18_open_id *id, int type)
45 struct cx18 *cx = id->cx;
46 struct cx18_stream *s = &cx->streams[type];
47 struct cx18_stream *s_assoc;
49 /* Nothing should ever try to directly claim the IDX stream */
50 if (type == CX18_ENC_STREAM_TYPE_IDX) {
51 CX18_WARN("MPEG Index stream cannot be claimed "
52 "directly, but something tried.\n");
53 return -EINVAL;
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. */
60 return 0;
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. */
66 s->id = id->open_id;
67 CX18_DEBUG_INFO("Start Read VBI\n");
68 return 0;
70 /* someone else is using this stream already */
71 CX18_DEBUG_INFO("Stream %d is busy\n", type);
72 return -EBUSY;
74 s->id = id->open_id;
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)
85 return 0;
87 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
88 if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
89 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
90 else if (!cx18_stream_enabled(s_assoc))
91 return 0;
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);
97 return 0;
100 /* This function releases a previously claimed stream. It will take into
101 account associated VBI streams. */
102 static void cx18_release_stream(struct cx18_stream *s)
104 struct cx18 *cx = s->cx;
105 struct cx18_stream *s_assoc;
107 s->id = -1;
108 if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
110 * The IDX stream is only used internally, and can
111 * only be indirectly unclaimed by unclaiming the MPG stream.
113 return;
116 if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
117 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
118 /* this stream is still in use internally */
119 return;
121 if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
122 CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
123 return;
126 cx18_flush_queues(s);
129 * CX18_ENC_STREAM_TYPE_MPG needs to release the
130 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
132 * For all other streams we're done.
134 if (s->type != CX18_ENC_STREAM_TYPE_MPG)
135 return;
137 /* Unclaim the associated MPEG Index stream */
138 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
139 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
140 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
141 cx18_flush_queues(s_assoc);
144 /* Unclaim the associated VBI stream */
145 s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
146 if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
147 if (s_assoc->id == -1) {
149 * The VBI stream is not still claimed by a file
150 * descriptor, so completely unclaim it.
152 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
153 cx18_flush_queues(s_assoc);
158 static void cx18_dualwatch(struct cx18 *cx)
160 struct v4l2_tuner vt;
161 u32 new_bitmap;
162 u32 new_stereo_mode;
163 const u32 stereo_mask = 0x0300;
164 const u32 dual = 0x0200;
165 u32 h;
167 new_stereo_mode = cx->params.audio_properties & stereo_mask;
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;
174 if (new_stereo_mode == cx->dualwatch_stereo_mode)
175 return;
177 new_bitmap = new_stereo_mode
178 | (cx->params.audio_properties & ~stereo_mask);
180 CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
181 "new audio_bitmask=0x%ux\n",
182 cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
184 h = cx18_find_handle(cx);
185 if (h == CX18_INVALID_TASK_HANDLE) {
186 CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
187 return;
190 if (cx18_vapi(cx,
191 CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
192 cx->dualwatch_stereo_mode = new_stereo_mode;
193 return;
195 CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
199 static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
200 int *err)
202 struct cx18 *cx = s->cx;
203 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
204 struct cx18_mdl *mdl;
205 DEFINE_WAIT(wait);
207 *err = 0;
208 while (1) {
209 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
210 /* Process pending program info updates and pending
211 VBI data */
213 if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
214 cx->dualwatch_jiffies = jiffies;
215 cx18_dualwatch(cx);
217 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
218 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
219 while ((mdl = cx18_dequeue(s_vbi,
220 &s_vbi->q_full))) {
221 /* byteswap and process VBI data */
222 cx18_process_vbi_data(cx, mdl,
223 s_vbi->type);
224 cx18_stream_put_mdl_fw(s_vbi, mdl);
227 mdl = &cx->vbi.sliced_mpeg_mdl;
228 if (mdl->readpos != mdl->bytesused)
229 return mdl;
232 /* do we have new data? */
233 mdl = cx18_dequeue(s, &s->q_full);
234 if (mdl) {
235 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
236 &mdl->m_flags))
237 return mdl;
238 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
239 /* byteswap MPG data */
240 cx18_mdl_swap(mdl);
241 else {
242 /* byteswap and process VBI data */
243 cx18_process_vbi_data(cx, mdl, s->type);
245 return mdl;
248 /* return if end of stream */
249 if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
250 CX18_DEBUG_INFO("EOS %s\n", s->name);
251 return NULL;
254 /* return if file was opened with O_NONBLOCK */
255 if (non_block) {
256 *err = -EAGAIN;
257 return NULL;
260 /* wait for more data to arrive */
261 prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
262 /* New buffers might have become available before we were added
263 to the waitqueue */
264 if (!atomic_read(&s->q_full.depth))
265 schedule();
266 finish_wait(&s->waitq, &wait);
267 if (signal_pending(current)) {
268 /* return if a signal was received */
269 CX18_DEBUG_INFO("User stopped %s\n", s->name);
270 *err = -EINTR;
271 return NULL;
276 static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
278 struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
279 struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
280 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
282 buf->buf = cx->vbi.sliced_mpeg_data[idx];
283 buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
284 buf->readpos = 0;
286 mdl->curr_buf = NULL;
287 mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
288 mdl->readpos = 0;
291 static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
292 struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
294 struct cx18 *cx = s->cx;
295 size_t len = buf->bytesused - buf->readpos;
297 *stop = false;
298 if (len > ucount)
299 len = ucount;
300 if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
301 !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
303 * Try to find a good splice point in the PS, just before
304 * an MPEG-2 Program Pack start code, and provide only
305 * up to that point to the user, so it's easy to insert VBI data
306 * the next time around.
308 * This will not work for an MPEG-2 TS and has only been
309 * verified by analysis to work for an MPEG-2 PS. Helen Buus
310 * pointed out this works for the CX23416 MPEG-2 DVD compatible
311 * stream, and research indicates both the MPEG 2 SVCD and DVD
312 * stream types use an MPEG-2 PS container.
315 * An MPEG-2 Program Stream (PS) is a series of
316 * MPEG-2 Program Packs terminated by an
317 * MPEG Program End Code after the last Program Pack.
318 * A Program Pack may hold a PS System Header packet and any
319 * number of Program Elementary Stream (PES) Packets
321 const char *start = buf->buf + buf->readpos;
322 const char *p = start + 1;
323 const u8 *q;
324 u8 ch = cx->search_pack_header ? 0xba : 0xe0;
325 int stuffing, i;
327 while (start + len > p) {
328 /* Scan for a 0 to find a potential MPEG-2 start code */
329 q = memchr(p, 0, start + len - p);
330 if (q == NULL)
331 break;
332 p = q + 1;
334 * Keep looking if not a
335 * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba
336 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
338 if ((char *)q + 15 >= buf->buf + buf->bytesused ||
339 q[1] != 0 || q[2] != 1 || q[3] != ch)
340 continue;
342 /* If expecting the primary video PES */
343 if (!cx->search_pack_header) {
344 /* Continue if it couldn't be a PES packet */
345 if ((q[6] & 0xc0) != 0x80)
346 continue;
347 /* Check if a PTS or PTS & DTS follow */
348 if (((q[7] & 0xc0) == 0x80 && /* PTS only */
349 (q[9] & 0xf0) == 0x20) || /* PTS only */
350 ((q[7] & 0xc0) == 0xc0 && /* PTS & DTS */
351 (q[9] & 0xf0) == 0x30)) { /* DTS follows */
352 /* Assume we found the video PES hdr */
353 ch = 0xba; /* next want a Program Pack*/
354 cx->search_pack_header = 1;
355 p = q + 9; /* Skip this video PES hdr */
357 continue;
360 /* We may have found a Program Pack start code */
362 /* Get the count of stuffing bytes & verify them */
363 stuffing = q[13] & 7;
364 /* all stuffing bytes must be 0xff */
365 for (i = 0; i < stuffing; i++)
366 if (q[14 + i] != 0xff)
367 break;
368 if (i == stuffing && /* right number of stuffing bytes*/
369 (q[4] & 0xc4) == 0x44 && /* marker check */
370 (q[12] & 3) == 3 && /* marker check */
371 q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
372 q[15 + stuffing] == 0 &&
373 q[16 + stuffing] == 1) {
374 /* We declare we actually found a Program Pack*/
375 cx->search_pack_header = 0; /* expect vid PES */
376 len = (char *)q - start;
377 cx18_setup_sliced_vbi_mdl(cx);
378 *stop = true;
379 break;
383 if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
384 CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
385 len, s->name);
386 return -EFAULT;
388 buf->readpos += len;
389 if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
390 buf != &cx->vbi.sliced_mpeg_buf)
391 cx->mpg_data_received += len;
392 return len;
396 * list_entry_is_past_end - check if a previous loop cursor is off list end
397 * @pos: the type * previously used as a loop cursor.
398 * @head: the head for your list.
399 * @member: the name of the list_struct within the struct.
401 * Check if the entry's list_head is the head of the list, thus it's not a
402 * real entry but was the loop cursor that walked past the end
404 #define list_entry_is_past_end(pos, head, member) \
405 (&pos->member == (head))
407 static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
408 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
410 size_t tot_written = 0;
411 int rc;
412 bool stop = false;
414 if (mdl->curr_buf == NULL)
415 mdl->curr_buf = list_first_entry(&mdl->buf_list,
416 struct cx18_buffer, list);
418 if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
420 * For some reason we've exhausted the buffers, but the MDL
421 * object still said some data was unread.
422 * Fix that and bail out.
424 mdl->readpos = mdl->bytesused;
425 return 0;
428 list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
430 if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
431 continue;
433 rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
434 ucount - tot_written, &stop);
435 if (rc < 0)
436 return rc;
437 mdl->readpos += rc;
438 tot_written += rc;
440 if (stop || /* Forced stopping point for VBI insertion */
441 tot_written >= ucount || /* Reader request statisfied */
442 mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
443 mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
444 break;
446 return tot_written;
449 static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
450 size_t tot_count, int non_block)
452 struct cx18 *cx = s->cx;
453 size_t tot_written = 0;
454 int single_frame = 0;
456 if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
457 /* shouldn't happen */
458 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
459 s->name);
460 return -EIO;
463 /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
464 frames should arrive one-by-one, so make sure we never output more
465 than one VBI frame at a time */
466 if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
467 single_frame = 1;
469 for (;;) {
470 struct cx18_mdl *mdl;
471 int rc;
473 mdl = cx18_get_mdl(s, non_block, &rc);
474 /* if there is no data available... */
475 if (mdl == NULL) {
476 /* if we got data, then return that regardless */
477 if (tot_written)
478 break;
479 /* EOS condition */
480 if (rc == 0) {
481 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
482 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
483 cx18_release_stream(s);
485 /* set errno */
486 return rc;
489 rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
490 tot_count - tot_written);
492 if (mdl != &cx->vbi.sliced_mpeg_mdl) {
493 if (mdl->readpos == mdl->bytesused)
494 cx18_stream_put_mdl_fw(s, mdl);
495 else
496 cx18_push(s, mdl, &s->q_full);
497 } else if (mdl->readpos == mdl->bytesused) {
498 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
500 cx->vbi.sliced_mpeg_size[idx] = 0;
501 cx->vbi.inserted_frame++;
502 cx->vbi_data_inserted += mdl->bytesused;
504 if (rc < 0)
505 return rc;
506 tot_written += rc;
508 if (tot_written == tot_count || single_frame)
509 break;
511 return tot_written;
514 static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
515 size_t count, loff_t *pos, int non_block)
517 ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
518 struct cx18 *cx = s->cx;
520 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
521 if (rc > 0)
522 pos += rc;
523 return rc;
526 int cx18_start_capture(struct cx18_open_id *id)
528 struct cx18 *cx = id->cx;
529 struct cx18_stream *s = &cx->streams[id->type];
530 struct cx18_stream *s_vbi;
531 struct cx18_stream *s_idx;
533 if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
534 /* you cannot read from these stream types. */
535 return -EPERM;
538 /* Try to claim this stream. */
539 if (cx18_claim_stream(id, s->type))
540 return -EBUSY;
542 /* If capture is already in progress, then we also have to
543 do nothing extra. */
544 if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
545 test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
546 set_bit(CX18_F_S_APPL_IO, &s->s_flags);
547 return 0;
550 /* Start associated VBI or IDX stream capture if required */
551 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
552 s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
553 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
555 * The VBI and IDX streams should have been claimed
556 * automatically, if for internal use, when the MPG stream was
557 * claimed. We only need to start these streams capturing.
559 if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
560 !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
561 if (cx18_start_v4l2_encode_stream(s_idx)) {
562 CX18_DEBUG_WARN("IDX capture start failed\n");
563 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
564 goto start_failed;
566 CX18_DEBUG_INFO("IDX capture started\n");
568 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
569 !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
570 if (cx18_start_v4l2_encode_stream(s_vbi)) {
571 CX18_DEBUG_WARN("VBI capture start failed\n");
572 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
573 goto start_failed;
575 CX18_DEBUG_INFO("VBI insertion started\n");
579 /* Tell the card to start capturing */
580 if (!cx18_start_v4l2_encode_stream(s)) {
581 /* We're done */
582 set_bit(CX18_F_S_APPL_IO, &s->s_flags);
583 /* Resume a possibly paused encoder */
584 if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
585 cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
586 return 0;
589 start_failed:
590 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
593 * The associated VBI and IDX streams for internal use are released
594 * automatically when the MPG stream is released. We only need to stop
595 * the associated stream.
597 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
598 /* Stop the IDX stream which is always for internal use */
599 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
600 cx18_stop_v4l2_encode_stream(s_idx, 0);
601 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
603 /* Stop the VBI stream, if only running for internal use */
604 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
605 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
606 cx18_stop_v4l2_encode_stream(s_vbi, 0);
607 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
610 clear_bit(CX18_F_S_STREAMING, &s->s_flags);
611 cx18_release_stream(s); /* Also releases associated streams */
612 return -EIO;
615 ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
616 loff_t *pos)
618 struct cx18_open_id *id = filp->private_data;
619 struct cx18 *cx = id->cx;
620 struct cx18_stream *s = &cx->streams[id->type];
621 int rc;
623 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
625 mutex_lock(&cx->serialize_lock);
626 rc = cx18_start_capture(id);
627 mutex_unlock(&cx->serialize_lock);
628 if (rc)
629 return rc;
630 return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
633 unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
635 struct cx18_open_id *id = filp->private_data;
636 struct cx18 *cx = id->cx;
637 struct cx18_stream *s = &cx->streams[id->type];
638 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
640 /* Start a capture if there is none */
641 if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
642 int rc;
644 mutex_lock(&cx->serialize_lock);
645 rc = cx18_start_capture(id);
646 mutex_unlock(&cx->serialize_lock);
647 if (rc) {
648 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
649 s->name, rc);
650 return POLLERR;
652 CX18_DEBUG_FILE("Encoder poll started capture\n");
655 /* add stream's waitq to the poll list */
656 CX18_DEBUG_HI_FILE("Encoder poll\n");
657 poll_wait(filp, &s->waitq, wait);
659 if (atomic_read(&s->q_full.depth))
660 return POLLIN | POLLRDNORM;
661 if (eof)
662 return POLLHUP;
663 return 0;
666 void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
668 struct cx18 *cx = id->cx;
669 struct cx18_stream *s = &cx->streams[id->type];
670 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
671 struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
673 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
675 /* 'Unclaim' this stream */
677 /* Stop capturing */
678 if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
679 CX18_DEBUG_INFO("close stopping capture\n");
680 if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
681 /* Stop internal use associated VBI and IDX streams */
682 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
683 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
684 CX18_DEBUG_INFO("close stopping embedded VBI "
685 "capture\n");
686 cx18_stop_v4l2_encode_stream(s_vbi, 0);
688 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
689 CX18_DEBUG_INFO("close stopping IDX capture\n");
690 cx18_stop_v4l2_encode_stream(s_idx, 0);
693 if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
694 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
695 /* Also used internally, don't stop capturing */
696 s->id = -1;
697 else
698 cx18_stop_v4l2_encode_stream(s, gop_end);
700 if (!gop_end) {
701 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
702 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
703 cx18_release_stream(s);
707 int cx18_v4l2_close(struct file *filp)
709 struct cx18_open_id *id = filp->private_data;
710 struct cx18 *cx = id->cx;
711 struct cx18_stream *s = &cx->streams[id->type];
713 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
715 v4l2_prio_close(&cx->prio, &id->prio);
717 /* Easy case first: this stream was never claimed by us */
718 if (s->id != id->open_id) {
719 kfree(id);
720 return 0;
723 /* 'Unclaim' this stream */
725 /* Stop radio */
726 mutex_lock(&cx->serialize_lock);
727 if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
728 /* Closing radio device, return to TV mode */
729 cx18_mute(cx);
730 /* Mark that the radio is no longer in use */
731 clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
732 /* Switch tuner to TV */
733 cx18_call_all(cx, core, s_std, cx->std);
734 /* Select correct audio input (i.e. TV tuner or Line in) */
735 cx18_audio_set_io(cx);
736 if (atomic_read(&cx->ana_capturing) > 0) {
737 /* Undo video mute */
738 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
739 cx->params.video_mute |
740 (cx->params.video_mute_yuv << 8));
742 /* Done! Unmute and continue. */
743 cx18_unmute(cx);
744 cx18_release_stream(s);
745 } else {
746 cx18_stop_capture(id, 0);
748 kfree(id);
749 mutex_unlock(&cx->serialize_lock);
750 return 0;
753 static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
755 struct cx18 *cx = s->cx;
756 struct cx18_open_id *item;
758 CX18_DEBUG_FILE("open %s\n", s->name);
760 /* Allocate memory */
761 item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
762 if (NULL == item) {
763 CX18_DEBUG_WARN("nomem on v4l2 open\n");
764 return -ENOMEM;
766 item->cx = cx;
767 item->type = s->type;
768 v4l2_prio_open(&cx->prio, &item->prio);
770 item->open_id = cx->open_id++;
771 filp->private_data = item;
773 if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
774 /* Try to claim this stream */
775 if (cx18_claim_stream(item, item->type)) {
776 /* No, it's already in use */
777 kfree(item);
778 return -EBUSY;
781 if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
782 if (atomic_read(&cx->ana_capturing) > 0) {
783 /* switching to radio while capture is
784 in progress is not polite */
785 cx18_release_stream(s);
786 kfree(item);
787 return -EBUSY;
791 /* Mark that the radio is being used. */
792 set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
793 /* We have the radio */
794 cx18_mute(cx);
795 /* Switch tuner to radio */
796 cx18_call_all(cx, tuner, s_radio);
797 /* Select the correct audio input (i.e. radio tuner) */
798 cx18_audio_set_io(cx);
799 /* Done! Unmute and continue. */
800 cx18_unmute(cx);
802 return 0;
805 int cx18_v4l2_open(struct file *filp)
807 int res;
808 struct video_device *video_dev = video_devdata(filp);
809 struct cx18_stream *s = video_get_drvdata(video_dev);
810 struct cx18 *cx = s->cx;
812 mutex_lock(&cx->serialize_lock);
813 if (cx18_init_on_first_open(cx)) {
814 CX18_ERR("Failed to initialize on %s\n",
815 video_device_node_name(video_dev));
816 mutex_unlock(&cx->serialize_lock);
817 return -ENXIO;
819 res = cx18_serialized_open(s, filp);
820 mutex_unlock(&cx->serialize_lock);
821 return res;
824 void cx18_mute(struct cx18 *cx)
826 u32 h;
827 if (atomic_read(&cx->ana_capturing)) {
828 h = cx18_find_handle(cx);
829 if (h != CX18_INVALID_TASK_HANDLE)
830 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
831 else
832 CX18_ERR("Can't find valid task handle for mute\n");
834 CX18_DEBUG_INFO("Mute\n");
837 void cx18_unmute(struct cx18 *cx)
839 u32 h;
840 if (atomic_read(&cx->ana_capturing)) {
841 h = cx18_find_handle(cx);
842 if (h != CX18_INVALID_TASK_HANDLE) {
843 cx18_msleep_timeout(100, 0);
844 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
845 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
846 } else
847 CX18_ERR("Can't find valid task handle for unmute\n");
849 CX18_DEBUG_INFO("Unmute\n");