[media] cx18: Use the control framework
[deliverable/linux.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 163 u32 new_stereo_mode;
0d82fe80 164 const u32 dual = 0x0200;
1c1e45d1 165
a75b9be1 166 new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
1c1e45d1 167 memset(&vt, 0, sizeof(vt));
ff2a2001 168 cx18_call_all(cx, tuner, g_tuner, &vt);
1c1e45d1
HV
169 if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
170 (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
171 new_stereo_mode = dual;
172
173 if (new_stereo_mode == cx->dualwatch_stereo_mode)
174 return;
175
a75b9be1
HV
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");
1c1e45d1
HV
180}
181
182
52fcb3ec
AW
183static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
184 int *err)
1c1e45d1
HV
185{
186 struct cx18 *cx = s->cx;
187 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
52fcb3ec 188 struct cx18_mdl *mdl;
1c1e45d1
HV
189 DEFINE_WAIT(wait);
190
191 *err = 0;
192 while (1) {
193 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
9bff2d61 194 /* Process pending program updates and VBI data */
1c1e45d1
HV
195 if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
196 cx->dualwatch_jiffies = jiffies;
197 cx18_dualwatch(cx);
198 }
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)) {
52fcb3ec
AW
201 while ((mdl = cx18_dequeue(s_vbi,
202 &s_vbi->q_full))) {
1c1e45d1 203 /* byteswap and process VBI data */
52fcb3ec 204 cx18_process_vbi_data(cx, mdl,
af009cf6 205 s_vbi->type);
52fcb3ec 206 cx18_stream_put_mdl_fw(s_vbi, mdl);
1c1e45d1
HV
207 }
208 }
52fcb3ec
AW
209 mdl = &cx->vbi.sliced_mpeg_mdl;
210 if (mdl->readpos != mdl->bytesused)
211 return mdl;
1c1e45d1
HV
212 }
213
1c1e45d1 214 /* do we have new data? */
52fcb3ec
AW
215 mdl = cx18_dequeue(s, &s->q_full);
216 if (mdl) {
217 if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
218 &mdl->m_flags))
219 return mdl;
1c1e45d1
HV
220 if (s->type == CX18_ENC_STREAM_TYPE_MPG)
221 /* byteswap MPG data */
52fcb3ec 222 cx18_mdl_swap(mdl);
1c1e45d1
HV
223 else {
224 /* byteswap and process VBI data */
52fcb3ec 225 cx18_process_vbi_data(cx, mdl, s->type);
1c1e45d1 226 }
52fcb3ec 227 return mdl;
1c1e45d1
HV
228 }
229
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);
233 return NULL;
234 }
235
236 /* return if file was opened with O_NONBLOCK */
237 if (non_block) {
238 *err = -EAGAIN;
239 return NULL;
240 }
241
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
245 to the waitqueue */
c37b11bf 246 if (!atomic_read(&s->q_full.depth))
1c1e45d1
HV
247 schedule();
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);
252 *err = -EINTR;
253 return NULL;
254 }
255 }
256}
257
52fcb3ec 258static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
1c1e45d1 259{
52fcb3ec
AW
260 struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
261 struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
1c1e45d1
HV
262 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
263
52fcb3ec
AW
264 buf->buf = cx->vbi.sliced_mpeg_data[idx];
265 buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
266 buf->readpos = 0;
267
268 mdl->curr_buf = NULL;
269 mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
270 mdl->readpos = 0;
1c1e45d1
HV
271}
272
273static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
52fcb3ec 274 struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
1c1e45d1
HV
275{
276 struct cx18 *cx = s->cx;
277 size_t len = buf->bytesused - buf->readpos;
278
52fcb3ec 279 *stop = false;
1c1e45d1
HV
280 if (len > ucount)
281 len = ucount;
282 if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
dd073434 283 !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
302df970
AW
284 /*
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.
0c629252
AW
289 *
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.
302df970 295 */
302df970
AW
296 /*
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
302 */
1c1e45d1
HV
303 const char *start = buf->buf + buf->readpos;
304 const char *p = start + 1;
305 const u8 *q;
306 u8 ch = cx->search_pack_header ? 0xba : 0xe0;
307 int stuffing, i;
308
309 while (start + len > p) {
302df970 310 /* Scan for a 0 to find a potential MPEG-2 start code */
1c1e45d1
HV
311 q = memchr(p, 0, start + len - p);
312 if (q == NULL)
313 break;
314 p = q + 1;
302df970
AW
315 /*
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
319 */
1c1e45d1
HV
320 if ((char *)q + 15 >= buf->buf + buf->bytesused ||
321 q[1] != 0 || q[2] != 1 || q[3] != ch)
322 continue;
302df970
AW
323
324 /* If expecting the primary video PES */
1c1e45d1 325 if (!cx->search_pack_header) {
302df970 326 /* Continue if it couldn't be a PES packet */
1c1e45d1
HV
327 if ((q[6] & 0xc0) != 0x80)
328 continue;
302df970
AW
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*/
1c1e45d1 336 cx->search_pack_header = 1;
302df970 337 p = q + 9; /* Skip this video PES hdr */
1c1e45d1
HV
338 }
339 continue;
340 }
302df970
AW
341
342 /* We may have found a Program Pack start code */
343
344 /* Get the count of stuffing bytes & verify them */
1c1e45d1
HV
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)
349 break;
302df970
AW
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 */
1c1e45d1
HV
354 q[15 + stuffing] == 0 &&
355 q[16 + stuffing] == 1) {
302df970
AW
356 /* We declare we actually found a Program Pack*/
357 cx->search_pack_header = 0; /* expect vid PES */
1c1e45d1 358 len = (char *)q - start;
52fcb3ec
AW
359 cx18_setup_sliced_vbi_mdl(cx);
360 *stop = true;
1c1e45d1
HV
361 break;
362 }
363 }
364 }
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",
367 len, s->name);
368 return -EFAULT;
369 }
370 buf->readpos += len;
371 if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
372 buf != &cx->vbi.sliced_mpeg_buf)
373 cx->mpg_data_received += len;
374 return len;
375}
376
52fcb3ec
AW
377static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
378 struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
379{
380 size_t tot_written = 0;
381 int rc;
382 bool stop = false;
383
384 if (mdl->curr_buf == NULL)
385 mdl->curr_buf = list_first_entry(&mdl->buf_list,
386 struct cx18_buffer, list);
387
388 if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
389 /*
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.
393 */
394 mdl->readpos = mdl->bytesused;
395 return 0;
396 }
397
398 list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
399
400 if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
401 continue;
402
403 rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
404 ucount - tot_written, &stop);
405 if (rc < 0)
406 return rc;
407 mdl->readpos += rc;
408 tot_written += rc;
409
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 */
414 break;
415 }
416 return tot_written;
417}
418
1c1e45d1
HV
419static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
420 size_t tot_count, int non_block)
421{
422 struct cx18 *cx = s->cx;
423 size_t tot_written = 0;
424 int single_frame = 0;
425
31554ae5 426 if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
1c1e45d1
HV
427 /* shouldn't happen */
428 CX18_DEBUG_WARN("Stream %s not initialized before read\n",
429 s->name);
430 return -EIO;
431 }
432
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 */
dd073434 436 if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
1c1e45d1
HV
437 single_frame = 1;
438
439 for (;;) {
52fcb3ec 440 struct cx18_mdl *mdl;
1c1e45d1
HV
441 int rc;
442
52fcb3ec 443 mdl = cx18_get_mdl(s, non_block, &rc);
1c1e45d1 444 /* if there is no data available... */
52fcb3ec 445 if (mdl == NULL) {
1c1e45d1
HV
446 /* if we got data, then return that regardless */
447 if (tot_written)
448 break;
449 /* EOS condition */
450 if (rc == 0) {
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);
454 }
455 /* set errno */
456 return rc;
457 }
458
52fcb3ec 459 rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
1c1e45d1
HV
460 tot_count - tot_written);
461
52fcb3ec
AW
462 if (mdl != &cx->vbi.sliced_mpeg_mdl) {
463 if (mdl->readpos == mdl->bytesused)
464 cx18_stream_put_mdl_fw(s, mdl);
66c2a6b0 465 else
52fcb3ec
AW
466 cx18_push(s, mdl, &s->q_full);
467 } else if (mdl->readpos == mdl->bytesused) {
1c1e45d1
HV
468 int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
469
470 cx->vbi.sliced_mpeg_size[idx] = 0;
471 cx->vbi.inserted_frame++;
52fcb3ec 472 cx->vbi_data_inserted += mdl->bytesused;
1c1e45d1
HV
473 }
474 if (rc < 0)
475 return rc;
476 tot_written += rc;
477
478 if (tot_written == tot_count || single_frame)
479 break;
480 }
481 return tot_written;
482}
483
484static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
485 size_t count, loff_t *pos, int non_block)
486{
487 ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
488 struct cx18 *cx = s->cx;
489
490 CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
491 if (rc > 0)
492 pos += rc;
493 return rc;
494}
495
496int cx18_start_capture(struct cx18_open_id *id)
497{
498 struct cx18 *cx = id->cx;
499 struct cx18_stream *s = &cx->streams[id->type];
500 struct cx18_stream *s_vbi;
79f3e960 501 struct cx18_stream *s_idx;
1c1e45d1
HV
502
503 if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
504 /* you cannot read from these stream types. */
505 return -EPERM;
506 }
507
508 /* Try to claim this stream. */
509 if (cx18_claim_stream(id, s->type))
510 return -EBUSY;
511
512 /* If capture is already in progress, then we also have to
513 do nothing extra. */
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);
517 return 0;
518 }
519
79f3e960 520 /* Start associated VBI or IDX stream capture if required */
1c1e45d1 521 s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
79f3e960
AW
522 s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
523 if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
524 /*
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.
528 */
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);
534 goto start_failed;
535 }
536 CX18_DEBUG_INFO("IDX capture started\n");
537 }
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);
543 goto start_failed;
544 }
545 CX18_DEBUG_INFO("VBI insertion started\n");
1c1e45d1 546 }
1c1e45d1
HV
547 }
548
549 /* Tell the card to start capturing */
550 if (!cx18_start_v4l2_encode_stream(s)) {
551 /* We're done */
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);
556 return 0;
557 }
558
79f3e960 559start_failed:
1c1e45d1
HV
560 CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
561
79f3e960
AW
562 /*
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.
566 */
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);
572 }
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);
578 }
1c1e45d1
HV
579 }
580 clear_bit(CX18_F_S_STREAMING, &s->s_flags);
79f3e960 581 cx18_release_stream(s); /* Also releases associated streams */
1c1e45d1
HV
582 return -EIO;
583}
584
585ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
586 loff_t *pos)
587{
588 struct cx18_open_id *id = filp->private_data;
589 struct cx18 *cx = id->cx;
590 struct cx18_stream *s = &cx->streams[id->type];
591 int rc;
592
593 CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
594
595 mutex_lock(&cx->serialize_lock);
596 rc = cx18_start_capture(id);
597 mutex_unlock(&cx->serialize_lock);
598 if (rc)
599 return rc;
600 return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
601}
602
603unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
604{
605 struct cx18_open_id *id = filp->private_data;
606 struct cx18 *cx = id->cx;
607 struct cx18_stream *s = &cx->streams[id->type];
608 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
609
610 /* Start a capture if there is none */
611 if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
612 int rc;
613
614 mutex_lock(&cx->serialize_lock);
615 rc = cx18_start_capture(id);
616 mutex_unlock(&cx->serialize_lock);
617 if (rc) {
618 CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
619 s->name, rc);
620 return POLLERR;
621 }
622 CX18_DEBUG_FILE("Encoder poll started capture\n");
623 }
624
625 /* add stream's waitq to the poll list */
626 CX18_DEBUG_HI_FILE("Encoder poll\n");
627 poll_wait(filp, &s->waitq, wait);
628
c37b11bf 629 if (atomic_read(&s->q_full.depth))
1c1e45d1
HV
630 return POLLIN | POLLRDNORM;
631 if (eof)
632 return POLLHUP;
633 return 0;
634}
635
636void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
637{
638 struct cx18 *cx = id->cx;
639 struct cx18_stream *s = &cx->streams[id->type];
79f3e960
AW
640 struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
641 struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
1c1e45d1
HV
642
643 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
644
645 /* 'Unclaim' this stream */
646
647 /* Stop capturing */
648 if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
1c1e45d1 649 CX18_DEBUG_INFO("close stopping capture\n");
79f3e960
AW
650 if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
651 /* Stop internal use associated VBI and IDX streams */
652 if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
653 !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
654 CX18_DEBUG_INFO("close stopping embedded VBI "
655 "capture\n");
656 cx18_stop_v4l2_encode_stream(s_vbi, 0);
657 }
658 if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
659 CX18_DEBUG_INFO("close stopping IDX capture\n");
660 cx18_stop_v4l2_encode_stream(s_idx, 0);
661 }
1c1e45d1
HV
662 }
663 if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
664 test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
665 /* Also used internally, don't stop capturing */
666 s->id = -1;
667 else
668 cx18_stop_v4l2_encode_stream(s, gop_end);
669 }
670 if (!gop_end) {
671 clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
672 clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
673 cx18_release_stream(s);
674 }
675}
676
bec43661 677int cx18_v4l2_close(struct file *filp)
1c1e45d1
HV
678{
679 struct cx18_open_id *id = filp->private_data;
680 struct cx18 *cx = id->cx;
681 struct cx18_stream *s = &cx->streams[id->type];
682
683 CX18_DEBUG_IOCTL("close() of %s\n", s->name);
684
ffb4877b 685 v4l2_prio_close(&cx->prio, id->prio);
1c1e45d1
HV
686
687 /* Easy case first: this stream was never claimed by us */
688 if (s->id != id->open_id) {
689 kfree(id);
690 return 0;
691 }
692
693 /* 'Unclaim' this stream */
694
695 /* Stop radio */
696 mutex_lock(&cx->serialize_lock);
697 if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
698 /* Closing radio device, return to TV mode */
699 cx18_mute(cx);
700 /* Mark that the radio is no longer in use */
701 clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
702 /* Switch tuner to TV */
f41737ec 703 cx18_call_all(cx, core, s_std, cx->std);
1c1e45d1
HV
704 /* Select correct audio input (i.e. TV tuner or Line in) */
705 cx18_audio_set_io(cx);
31554ae5 706 if (atomic_read(&cx->ana_capturing) > 0) {
1c1e45d1
HV
707 /* Undo video mute */
708 cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
a75b9be1
HV
709 (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
710 (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
1c1e45d1
HV
711 }
712 /* Done! Unmute and continue. */
713 cx18_unmute(cx);
714 cx18_release_stream(s);
715 } else {
716 cx18_stop_capture(id, 0);
717 }
718 kfree(id);
719 mutex_unlock(&cx->serialize_lock);
720 return 0;
721}
722
723static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
724{
725 struct cx18 *cx = s->cx;
726 struct cx18_open_id *item;
727
728 CX18_DEBUG_FILE("open %s\n", s->name);
729
730 /* Allocate memory */
731 item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
732 if (NULL == item) {
733 CX18_DEBUG_WARN("nomem on v4l2 open\n");
734 return -ENOMEM;
735 }
736 item->cx = cx;
737 item->type = s->type;
738 v4l2_prio_open(&cx->prio, &item->prio);
739
740 item->open_id = cx->open_id++;
741 filp->private_data = item;
742
743 if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
744 /* Try to claim this stream */
745 if (cx18_claim_stream(item, item->type)) {
746 /* No, it's already in use */
747 kfree(item);
748 return -EBUSY;
749 }
750
751 if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
31554ae5 752 if (atomic_read(&cx->ana_capturing) > 0) {
1c1e45d1
HV
753 /* switching to radio while capture is
754 in progress is not polite */
755 cx18_release_stream(s);
756 kfree(item);
757 return -EBUSY;
758 }
759 }
760
761 /* Mark that the radio is being used. */
762 set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
763 /* We have the radio */
764 cx18_mute(cx);
765 /* Switch tuner to radio */
ff2a2001 766 cx18_call_all(cx, tuner, s_radio);
1c1e45d1
HV
767 /* Select the correct audio input (i.e. radio tuner) */
768 cx18_audio_set_io(cx);
769 /* Done! Unmute and continue. */
770 cx18_unmute(cx);
771 }
772 return 0;
773}
774
bec43661 775int cx18_v4l2_open(struct file *filp)
1c1e45d1 776{
5811cf99
AW
777 int res;
778 struct video_device *video_dev = video_devdata(filp);
779 struct cx18_stream *s = video_get_drvdata(video_dev);
32a60955 780 struct cx18 *cx = s->cx;
1c1e45d1
HV
781
782 mutex_lock(&cx->serialize_lock);
783 if (cx18_init_on_first_open(cx)) {
50462eb0
LP
784 CX18_ERR("Failed to initialize on %s\n",
785 video_device_node_name(video_dev));
1c1e45d1
HV
786 mutex_unlock(&cx->serialize_lock);
787 return -ENXIO;
788 }
789 res = cx18_serialized_open(s, filp);
790 mutex_unlock(&cx->serialize_lock);
791 return res;
792}
793
794void cx18_mute(struct cx18 *cx)
795{
d3c5e707
AW
796 u32 h;
797 if (atomic_read(&cx->ana_capturing)) {
798 h = cx18_find_handle(cx);
799 if (h != CX18_INVALID_TASK_HANDLE)
800 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
801 else
802 CX18_ERR("Can't find valid task handle for mute\n");
803 }
1c1e45d1
HV
804 CX18_DEBUG_INFO("Mute\n");
805}
806
807void cx18_unmute(struct cx18 *cx)
808{
d3c5e707 809 u32 h;
31554ae5 810 if (atomic_read(&cx->ana_capturing)) {
d3c5e707
AW
811 h = cx18_find_handle(cx);
812 if (h != CX18_INVALID_TASK_HANDLE) {
813 cx18_msleep_timeout(100, 0);
814 cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
815 cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
816 } else
817 CX18_ERR("Can't find valid task handle for unmute\n");
1c1e45d1
HV
818 }
819 CX18_DEBUG_INFO("Unmute\n");
820}
This page took 0.491658 seconds and 5 git commands to generate.