]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/media/video/cx18/cx18-fileops.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[net-next-2.6.git] / drivers / media / video / cx18 / cx18-fileops.c
CommitLineData
1c1e45d1
HV
1/*
2 * cx18 file operation functions
3 *
4 * Derived from ivtv-fileops.c
5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
6afdeaf8 7 * Copyright (C) 2008 Andy Walls <awalls@md.metrocast.net>
1c1e45d1
HV
8 *
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.
13 *
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.
18 *
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
23 */
24
25#include "cx18-driver.h"
26#include "cx18-fileops.h"
27#include "cx18-i2c.h"
28#include "cx18-queue.h"
29#include "cx18-vbi.h"
30#include "cx18-audio.h"
31#include "cx18-mailbox.h"
32#include "cx18-scb.h"
33#include "cx18-streams.h"
34#include "cx18-controls.h"
35#include "cx18-ioctl.h"
36#include "cx18-cards.h"
37
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
79f3e960 40 associated VBI and IDX streams are also automatically claimed.
1c1e45d1
HV
41 Possible error returns: -EBUSY if someone else has claimed
42 the stream or 0 on success. */
8ef22f79 43int cx18_claim_stream(struct cx18_open_id *id, int type)
1c1e45d1
HV
44{
45 struct cx18 *cx = id->cx;
46 struct cx18_stream *s = &cx->streams[type];
79f3e960
AW
47 struct cx18_stream *s_assoc;
48
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;
54 }
1c1e45d1
HV
55
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;
61 }
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;
69 }
70 /* someone else is using this stream already */
71 CX18_DEBUG_INFO("Stream %d is busy\n", type);
72 return -EBUSY;
73 }
74 s->id = id->open_id;
75
79f3e960
AW
76 /*
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).
81 *
82 * For all other streams we're done.
83 */
84 if (type != CX18_ENC_STREAM_TYPE_MPG)
85 return 0;
86
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))
1c1e45d1 91 return 0;
1c1e45d1 92
79f3e960 93 set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
1c1e45d1
HV
94
95 /* mark that it is used internally */
79f3e960 96 set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
1c1e45d1
HV
97 return 0;
98}
8ef22f79 99EXPORT_SYMBOL(cx18_claim_stream);
1c1e45d1
HV
100
101/* This function releases a previously claimed stream. It will take into
102 account associated VBI streams. */
8ef22f79 103void cx18_release_stream(struct cx18_stream *s)
1c1e45d1
HV
104{
105 struct cx18 *cx = s->cx;
79f3e960 106 struct cx18_stream *s_assoc;
1c1e45d1
HV
107
108 s->id = -1;
79f3e960
AW
109 if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
110 /*
111 * The IDX stream is only used internally, and can
112 * only be indirectly unclaimed by unclaiming the MPG stream.
113 */
114 return;
115 }
116
1c1e45d1
HV
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 */
120 return;
121 }
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);
124 return;
125 }
126
127 cx18_flush_queues(s);
128
79f3e960
AW
129 /*
130 * CX18_ENC_STREAM_TYPE_MPG needs to release the
131 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
132 *
133 * For all other streams we're done.
134 */
135 if (s->type != CX18_ENC_STREAM_TYPE_MPG)
1c1e45d1
HV
136 return;
137
79f3e960
AW
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);
1c1e45d1 143 }
79f3e960
AW
144
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) {
149 /*
150 * The VBI stream is not still claimed by a file
151 * descriptor, so completely unclaim it.
152 */
153 clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
154 cx18_flush_queues(s_assoc);
155 }
1c1e45d1 156 }
1c1e45d1 157}
8ef22f79 158EXPORT_SYMBOL(cx18_release_stream);
1c1e45d1
HV
159
160static void cx18_dualwatch(struct cx18 *cx)
161{
162 struct v4l2_tuner vt;
0d82fe80
AW
163 u32 new_bitmap;
164 u32 new_stereo_mode;
165 const u32 stereo_mask = 0x0300;
166 const u32 dual = 0x0200;
d3c5e707 167 u32 h;
1c1e45d1
HV
168
169 new_stereo_mode = cx->params.audio_properties & stereo_mask;
170 memset(&vt, 0, sizeof(vt));
ff2a2001 171 cx18_call_all(cx, tuner, g_tuner, &vt);
1c1e45d1
HV
172 if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
173 (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
174 new_stereo_mode = dual;
175
176 if (new_stereo_mode == cx->dualwatch_stereo_mode)
177 return;
178
d3c5e707
AW
179 new_bitmap = new_stereo_mode
180 | (cx->params.audio_properties & ~stereo_mask);
1c1e45d1 181
d3c5e707
AW
182 CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
183 "new audio_bitmask=0x%ux\n",
184 cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
1c1e45d1 185
d3c5e707
AW
186 h = cx18_find_handle(cx);
187 if (h == CX18_INVALID_TASK_HANDLE) {
188 CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
189 return;
190 }
191
192 if (cx18_vapi(cx,
193 CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
1c1e45d1
HV
194 cx->dualwatch_stereo_mode = new_stereo_mode;
195 return;
196 }
197 CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
198}
199
200
52fcb3ec
AW
201static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
202 int *err)
1c1e45d1
HV
203{
204 struct cx18 *cx = s->cx;
205 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
52fcb3ec 206 struct cx18_mdl *mdl;
1c1e45d1
HV
207 DEFINE_WAIT(wait);
208
209 *err = 0;
210 while (1) {
211 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
9bff2d61 212 /* Process pending program updates and VBI data */
1c1e45d1
HV
213 if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
214 cx->dualwatch_jiffies = jiffies;
215 cx18_dualwatch(cx);
216 }
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)) {
52fcb3ec
AW
219 while ((mdl = cx18_dequeue(s_vbi,
220 &s_vbi->q_full))) {
1c1e45d1 221 /* byteswap and process VBI data */
52fcb3ec 222 cx18_process_vbi_data(cx, mdl,
af009cf6 223 s_vbi->type);
52fcb3ec 224 cx18_stream_put_mdl_fw(s_vbi, mdl);
1c1e45d1
HV
225 }
226 }
52fcb3ec
AW
227 mdl = &cx->vbi.sliced_mpeg_mdl;
228 if (mdl->readpos != mdl->bytesused)
229 return mdl;
1c1e45d1
HV
230 }
231
1c1e45d1 232 /* do we have new data? */
52fcb3ec
AW
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;
1c1e45d1
HV
238 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
239 /* byteswap MPG data */
52fcb3ec 240 cx18_mdl_swap(mdl);
1c1e45d1
HV
241 else {
242 /* byteswap and process VBI data */
52fcb3ec 243 cx18_process_vbi_data(cx, mdl, s->type);
1c1e45d1 244 }
52fcb3ec 245 return mdl;
1c1e45d1
HV
246 }
247
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;
252 }
253
254 /* return if file was opened with O_NONBLOCK */
255 if (non_block) {
256 *err = -EAGAIN;
257 return NULL;
258 }
259
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 */
c37b11bf 264 if (!atomic_read(&s->q_full.depth))
1c1e45d1
HV
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;
272 }
273 }
274}
275
52fcb3ec 276static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
1c1e45d1 277{
52fcb3ec
AW
278 struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
279 struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
1c1e45d1
HV
280 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
281
52fcb3ec
AW
282 buf->buf = cx->vbi.sliced_mpeg_data[idx];
283 buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
284 buf->readpos = 0;
285
286 mdl->curr_buf = NULL;
287 mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
288 mdl->readpos = 0;
1c1e45d1
HV
289}
290
291static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
52fcb3ec 292 struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
1c1e45d1
HV
293{
294 struct cx18 *cx = s->cx;
295 size_t len = buf->bytesused - buf->readpos;
296
52fcb3ec 297 *stop = false;
1c1e45d1
HV
298 if (len > ucount)
299 len = ucount;
300 if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
dd073434 301 !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
302df970
AW
302 /*
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.
0c629252
AW
307 *
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.
302df970 313 */
302df970
AW
314 /*
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
320 */
1c1e45d1
HV
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;
326
327 while (start + len > p) {
302df970 328 /* Scan for a 0 to find a potential MPEG-2 start code */
1c1e45d1
HV
329 q = memchr(p, 0, start + len - p);
330 if (q == NULL)
331 break;
332 p = q + 1;
302df970
AW
333 /*
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
337 */
1c1e45d1
HV
338 if ((char *)q + 15 >= buf->buf + buf->bytesused ||
339 q[1] != 0 || q[2] != 1 || q[3] != ch)
340 continue;
302df970
AW
341
342 /* If expecting the primary video PES */
1c1e45d1 343 if (!cx->search_pack_header) {
302df970 344 /* Continue if it couldn't be a PES packet */
1c1e45d1
HV
345 if ((q[6] & 0xc0) != 0x80)
346 continue;
302df970
AW
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*/
1c1e45d1 354 cx->search_pack_header = 1;
302df970 355 p = q + 9; /* Skip this video PES hdr */
1c1e45d1
HV
356 }
357 continue;
358 }
302df970
AW
359
360 /* We may have found a Program Pack start code */
361
362 /* Get the count of stuffing bytes & verify them */
1c1e45d1
HV
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;
302df970
AW
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 */
1c1e45d1
HV
372 q[15 + stuffing] == 0 &&
373 q[16 + stuffing] == 1) {
302df970
AW
374 /* We declare we actually found a Program Pack*/
375 cx->search_pack_header = 0; /* expect vid PES */
1c1e45d1 376 len = (char *)q - start;
52fcb3ec
AW
377 cx18_setup_sliced_vbi_mdl(cx);
378 *stop = true;
1c1e45d1
HV
379 break;
380 }
381 }
382 }
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;
387 }
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;
393}
394
52fcb3ec
AW
395static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
396 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
397{
398 size_t tot_written = 0;
399 int rc;
400 bool stop = false;
401
402 if (mdl->curr_buf == NULL)
403 mdl->curr_buf = list_first_entry(&mdl->buf_list,
404 struct cx18_buffer, list);
405
406 if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
407 /*
408 * For some reason we've exhausted the buffers, but the MDL
409 * object still said some data was unread.
410 * Fix that and bail out.
411 */
412 mdl->readpos = mdl->bytesused;
413 return 0;
414 }
415
416 list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
417
418 if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
419 continue;
420
421 rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
422 ucount - tot_written, &stop);
423 if (rc < 0)
424 return rc;
425 mdl->readpos += rc;
426 tot_written += rc;
427
428 if (stop || /* Forced stopping point for VBI insertion */
429 tot_written >= ucount || /* Reader request statisfied */
430 mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
431 mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
432 break;
433 }
434 return tot_written;
435}
436
1c1e45d1
HV
437static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
438 size_t tot_count, int non_block)
439{
440 struct cx18 *cx = s->cx;
441 size_t tot_written = 0;
442 int single_frame = 0;
443
31554ae5 444 if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
1c1e45d1
HV
445 /* shouldn't happen */
446 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
447 s->name);
448 return -EIO;
449 }
450
451 /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
452 frames should arrive one-by-one, so make sure we never output more
453 than one VBI frame at a time */
dd073434 454 if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
1c1e45d1
HV
455 single_frame = 1;
456
457 for (;;) {
52fcb3ec 458 struct cx18_mdl *mdl;
1c1e45d1
HV
459 int rc;
460
52fcb3ec 461 mdl = cx18_get_mdl(s, non_block, &rc);
1c1e45d1 462 /* if there is no data available... */
52fcb3ec 463 if (mdl == NULL) {
1c1e45d1
HV
464 /* if we got data, then return that regardless */
465 if (tot_written)
466 break;
467 /* EOS condition */
468 if (rc == 0) {
469 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
470 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
471 cx18_release_stream(s);
472 }
473 /* set errno */
474 return rc;
475 }
476
52fcb3ec 477 rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
1c1e45d1
HV
478 tot_count - tot_written);
479
52fcb3ec
AW
480 if (mdl != &cx->vbi.sliced_mpeg_mdl) {
481 if (mdl->readpos == mdl->bytesused)
482 cx18_stream_put_mdl_fw(s, mdl);
66c2a6b0 483 else
52fcb3ec
AW
484 cx18_push(s, mdl, &s->q_full);
485 } else if (mdl->readpos == mdl->bytesused) {
1c1e45d1
HV
486 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
487
488 cx->vbi.sliced_mpeg_size[idx] = 0;
489 cx->vbi.inserted_frame++;
52fcb3ec 490 cx->vbi_data_inserted += mdl->bytesused;
1c1e45d1
HV
491 }
492 if (rc < 0)
493 return rc;
494 tot_written += rc;
495
496 if (tot_written == tot_count || single_frame)
497 break;
498 }
499 return tot_written;
500}
501
502static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
503 size_t count, loff_t *pos, int non_block)
504{
505 ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
506 struct cx18 *cx = s->cx;
507
508 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
509 if (rc > 0)
510 pos += rc;
511 return rc;
512}
513
514int cx18_start_capture(struct cx18_open_id *id)
515{
516 struct cx18 *cx = id->cx;
517 struct cx18_stream *s = &cx->streams[id->type];
518 struct cx18_stream *s_vbi;
79f3e960 519 struct cx18_stream *s_idx;
1c1e45d1
HV
520
521 if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
522 /* you cannot read from these stream types. */
523 return -EPERM;
524 }
525
526 /* Try to claim this stream. */
527 if (cx18_claim_stream(id, s->type))
528 return -EBUSY;
529
530 /* If capture is already in progress, then we also have to
531 do nothing extra. */
532 if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
533 test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
534 set_bit(CX18_F_S_APPL_IO, &s->s_flags);
535 return 0;
536 }
537
79f3e960 538 /* Start associated VBI or IDX stream capture if required */
1c1e45d1 539 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
79f3e960
AW
540 s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
541 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
542 /*
543 * The VBI and IDX streams should have been claimed
544 * automatically, if for internal use, when the MPG stream was
545 * claimed. We only need to start these streams capturing.
546 */
547 if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
548 !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
549 if (cx18_start_v4l2_encode_stream(s_idx)) {
550 CX18_DEBUG_WARN("IDX capture start failed\n");
551 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
552 goto start_failed;
553 }
554 CX18_DEBUG_INFO("IDX capture started\n");
555 }
556 if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
557 !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
558 if (cx18_start_v4l2_encode_stream(s_vbi)) {
559 CX18_DEBUG_WARN("VBI capture start failed\n");
560 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
561 goto start_failed;
562 }
563 CX18_DEBUG_INFO("VBI insertion started\n");
1c1e45d1 564 }
1c1e45d1
HV
565 }
566
567 /* Tell the card to start capturing */
568 if (!cx18_start_v4l2_encode_stream(s)) {
569 /* We're done */
570 set_bit(CX18_F_S_APPL_IO, &s->s_flags);
571 /* Resume a possibly paused encoder */
572 if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
573 cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
574 return 0;
575 }
576
79f3e960 577start_failed:
1c1e45d1
HV
578 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
579
79f3e960
AW
580 /*
581 * The associated VBI and IDX streams for internal use are released
582 * automatically when the MPG stream is released. We only need to stop
583 * the associated stream.
584 */
585 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
586 /* Stop the IDX stream which is always for internal use */
587 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
588 cx18_stop_v4l2_encode_stream(s_idx, 0);
589 clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
590 }
591 /* Stop the VBI stream, if only running for internal use */
592 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
593 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
594 cx18_stop_v4l2_encode_stream(s_vbi, 0);
595 clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
596 }
1c1e45d1
HV
597 }
598 clear_bit(CX18_F_S_STREAMING, &s->s_flags);
79f3e960 599 cx18_release_stream(s); /* Also releases associated streams */
1c1e45d1
HV
600 return -EIO;
601}
602
603ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
604 loff_t *pos)
605{
606 struct cx18_open_id *id = filp->private_data;
607 struct cx18 *cx = id->cx;
608 struct cx18_stream *s = &cx->streams[id->type];
609 int rc;
610
611 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
612
613 mutex_lock(&cx->serialize_lock);
614 rc = cx18_start_capture(id);
615 mutex_unlock(&cx->serialize_lock);
616 if (rc)
617 return rc;
618 return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
619}
620
621unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
622{
623 struct cx18_open_id *id = filp->private_data;
624 struct cx18 *cx = id->cx;
625 struct cx18_stream *s = &cx->streams[id->type];
626 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
627
628 /* Start a capture if there is none */
629 if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
630 int rc;
631
632 mutex_lock(&cx->serialize_lock);
633 rc = cx18_start_capture(id);
634 mutex_unlock(&cx->serialize_lock);
635 if (rc) {
636 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
637 s->name, rc);
638 return POLLERR;
639 }
640 CX18_DEBUG_FILE("Encoder poll started capture\n");
641 }
642
643 /* add stream's waitq to the poll list */
644 CX18_DEBUG_HI_FILE("Encoder poll\n");
645 poll_wait(filp, &s->waitq, wait);
646
c37b11bf 647 if (atomic_read(&s->q_full.depth))
1c1e45d1
HV
648 return POLLIN | POLLRDNORM;
649 if (eof)
650 return POLLHUP;
651 return 0;
652}
653
654void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
655{
656 struct cx18 *cx = id->cx;
657 struct cx18_stream *s = &cx->streams[id->type];
79f3e960
AW
658 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
659 struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
1c1e45d1
HV
660
661 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
662
663 /* 'Unclaim' this stream */
664
665 /* Stop capturing */
666 if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
1c1e45d1 667 CX18_DEBUG_INFO("close stopping capture\n");
79f3e960
AW
668 if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
669 /* Stop internal use associated VBI and IDX streams */
670 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
671 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
672 CX18_DEBUG_INFO("close stopping embedded VBI "
673 "capture\n");
674 cx18_stop_v4l2_encode_stream(s_vbi, 0);
675 }
676 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
677 CX18_DEBUG_INFO("close stopping IDX capture\n");
678 cx18_stop_v4l2_encode_stream(s_idx, 0);
679 }
1c1e45d1
HV
680 }
681 if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
682 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
683 /* Also used internally, don't stop capturing */
684 s->id = -1;
685 else
686 cx18_stop_v4l2_encode_stream(s, gop_end);
687 }
688 if (!gop_end) {
689 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
690 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
691 cx18_release_stream(s);
692 }
693}
694
bec43661 695int cx18_v4l2_close(struct file *filp)
1c1e45d1
HV
696{
697 struct cx18_open_id *id = filp->private_data;
698 struct cx18 *cx = id->cx;
699 struct cx18_stream *s = &cx->streams[id->type];
700
701 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
702
ffb4877b 703 v4l2_prio_close(&cx->prio, id->prio);
1c1e45d1
HV
704
705 /* Easy case first: this stream was never claimed by us */
706 if (s->id != id->open_id) {
707 kfree(id);
708 return 0;
709 }
710
711 /* 'Unclaim' this stream */
712
713 /* Stop radio */
714 mutex_lock(&cx->serialize_lock);
715 if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
716 /* Closing radio device, return to TV mode */
717 cx18_mute(cx);
718 /* Mark that the radio is no longer in use */
719 clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
720 /* Switch tuner to TV */
f41737ec 721 cx18_call_all(cx, core, s_std, cx->std);
1c1e45d1
HV
722 /* Select correct audio input (i.e. TV tuner or Line in) */
723 cx18_audio_set_io(cx);
31554ae5 724 if (atomic_read(&cx->ana_capturing) > 0) {
1c1e45d1
HV
725 /* Undo video mute */
726 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
727 cx->params.video_mute |
728 (cx->params.video_mute_yuv << 8));
729 }
730 /* Done! Unmute and continue. */
731 cx18_unmute(cx);
732 cx18_release_stream(s);
733 } else {
734 cx18_stop_capture(id, 0);
735 }
736 kfree(id);
737 mutex_unlock(&cx->serialize_lock);
738 return 0;
739}
740
741static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
742{
743 struct cx18 *cx = s->cx;
744 struct cx18_open_id *item;
745
746 CX18_DEBUG_FILE("open %s\n", s->name);
747
748 /* Allocate memory */
749 item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
750 if (NULL == item) {
751 CX18_DEBUG_WARN("nomem on v4l2 open\n");
752 return -ENOMEM;
753 }
754 item->cx = cx;
755 item->type = s->type;
756 v4l2_prio_open(&cx->prio, &item->prio);
757
758 item->open_id = cx->open_id++;
759 filp->private_data = item;
760
761 if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
762 /* Try to claim this stream */
763 if (cx18_claim_stream(item, item->type)) {
764 /* No, it's already in use */
765 kfree(item);
766 return -EBUSY;
767 }
768
769 if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
31554ae5 770 if (atomic_read(&cx->ana_capturing) > 0) {
1c1e45d1
HV
771 /* switching to radio while capture is
772 in progress is not polite */
773 cx18_release_stream(s);
774 kfree(item);
775 return -EBUSY;
776 }
777 }
778
779 /* Mark that the radio is being used. */
780 set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
781 /* We have the radio */
782 cx18_mute(cx);
783 /* Switch tuner to radio */
ff2a2001 784 cx18_call_all(cx, tuner, s_radio);
1c1e45d1
HV
785 /* Select the correct audio input (i.e. radio tuner) */
786 cx18_audio_set_io(cx);
787 /* Done! Unmute and continue. */
788 cx18_unmute(cx);
789 }
790 return 0;
791}
792
bec43661 793int cx18_v4l2_open(struct file *filp)
1c1e45d1 794{
5811cf99
AW
795 int res;
796 struct video_device *video_dev = video_devdata(filp);
797 struct cx18_stream *s = video_get_drvdata(video_dev);
32a60955 798 struct cx18 *cx = s->cx;
1c1e45d1
HV
799
800 mutex_lock(&cx->serialize_lock);
801 if (cx18_init_on_first_open(cx)) {
50462eb0
LP
802 CX18_ERR("Failed to initialize on %s\n",
803 video_device_node_name(video_dev));
1c1e45d1
HV
804 mutex_unlock(&cx->serialize_lock);
805 return -ENXIO;
806 }
807 res = cx18_serialized_open(s, filp);
808 mutex_unlock(&cx->serialize_lock);
809 return res;
810}
811
812void cx18_mute(struct cx18 *cx)
813{
d3c5e707
AW
814 u32 h;
815 if (atomic_read(&cx->ana_capturing)) {
816 h = cx18_find_handle(cx);
817 if (h != CX18_INVALID_TASK_HANDLE)
818 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
819 else
820 CX18_ERR("Can't find valid task handle for mute\n");
821 }
1c1e45d1
HV
822 CX18_DEBUG_INFO("Mute\n");
823}
824
825void cx18_unmute(struct cx18 *cx)
826{
d3c5e707 827 u32 h;
31554ae5 828 if (atomic_read(&cx->ana_capturing)) {
d3c5e707
AW
829 h = cx18_find_handle(cx);
830 if (h != CX18_INVALID_TASK_HANDLE) {
831 cx18_msleep_timeout(100, 0);
832 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
833 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
834 } else
835 CX18_ERR("Can't find valid task handle for unmute\n");
1c1e45d1
HV
836 }
837 CX18_DEBUG_INFO("Unmute\n");
838}