• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/media/video/cx18/
1/*
2 *  cx18 file operation functions
3 *
4 *  Derived from ivtv-fileops.c
5 *
6 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
7 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
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
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. */
43int cx18_claim_stream(struct cx18_open_id *id, int type)
44{
45	struct cx18 *cx = id->cx;
46	struct cx18_stream *s = &cx->streams[type];
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	}
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
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))
91		return 0;
92
93	set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
94
95	/* mark that it is used internally */
96	set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
97	return 0;
98}
99EXPORT_SYMBOL(cx18_claim_stream);
100
101/* This function releases a previously claimed stream. It will take into
102   account associated VBI streams. */
103void cx18_release_stream(struct cx18_stream *s)
104{
105	struct cx18 *cx = s->cx;
106	struct cx18_stream *s_assoc;
107
108	s->id = -1;
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
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
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)
136		return;
137
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);
143	}
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		}
156	}
157}
158EXPORT_SYMBOL(cx18_release_stream);
159
160static void cx18_dualwatch(struct cx18 *cx)
161{
162	struct v4l2_tuner vt;
163	u32 new_bitmap;
164	u32 new_stereo_mode;
165	const u32 stereo_mask = 0x0300;
166	const u32 dual = 0x0200;
167	u32 h;
168
169	new_stereo_mode = cx->params.audio_properties & stereo_mask;
170	memset(&vt, 0, sizeof(vt));
171	cx18_call_all(cx, tuner, g_tuner, &vt);
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
179	new_bitmap = new_stereo_mode
180			| (cx->params.audio_properties & ~stereo_mask);
181
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);
185
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) {
194		cx->dualwatch_stereo_mode = new_stereo_mode;
195		return;
196	}
197	CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
198}
199
200
201static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
202				     int *err)
203{
204	struct cx18 *cx = s->cx;
205	struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
206	struct cx18_mdl *mdl;
207	DEFINE_WAIT(wait);
208
209	*err = 0;
210	while (1) {
211		if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
212			/* Process pending program updates and VBI data */
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)) {
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);
225				}
226			}
227			mdl = &cx->vbi.sliced_mpeg_mdl;
228			if (mdl->readpos != mdl->bytesused)
229				return mdl;
230		}
231
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);
244			}
245			return mdl;
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 */
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;
272		}
273	}
274}
275
276static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
277{
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;
281
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;
289}
290
291static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
292	struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
293{
294	struct cx18 *cx = s->cx;
295	size_t len = buf->bytesused - buf->readpos;
296
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) {
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.
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.
313		 */
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		 */
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) {
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;
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			 */
338			if ((char *)q + 15 >= buf->buf + buf->bytesused ||
339			    q[1] != 0 || q[2] != 1 || q[3] != ch)
340				continue;
341
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 */
356				}
357				continue;
358			}
359
360			/* We may have found a Program Pack start code */
361
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;
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
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
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
444	if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
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 */
454	if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
455		single_frame = 1;
456
457	for (;;) {
458		struct cx18_mdl *mdl;
459		int rc;
460
461		mdl = cx18_get_mdl(s, non_block, &rc);
462		/* if there is no data available... */
463		if (mdl == NULL) {
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
477		rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
478				tot_count - tot_written);
479
480		if (mdl != &cx->vbi.sliced_mpeg_mdl) {
481			if (mdl->readpos == mdl->bytesused)
482				cx18_stream_put_mdl_fw(s, mdl);
483			else
484				cx18_push(s, mdl, &s->q_full);
485		} else if (mdl->readpos == mdl->bytesused) {
486			int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
487
488			cx->vbi.sliced_mpeg_size[idx] = 0;
489			cx->vbi.inserted_frame++;
490			cx->vbi_data_inserted += mdl->bytesused;
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;
519	struct cx18_stream *s_idx;
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
538	/* Start associated VBI or IDX stream capture if required */
539	s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
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");
564		}
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
577start_failed:
578	CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
579
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		}
597	}
598	clear_bit(CX18_F_S_STREAMING, &s->s_flags);
599	cx18_release_stream(s); /* Also releases associated streams */
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
647	if (atomic_read(&s->q_full.depth))
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];
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];
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)) {
667		CX18_DEBUG_INFO("close stopping capture\n");
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			}
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
695int cx18_v4l2_close(struct file *filp)
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
703	v4l2_prio_close(&cx->prio, id->prio);
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 */
721		cx18_call_all(cx, core, s_std, cx->std);
722		/* Select correct audio input (i.e. TV tuner or Line in) */
723		cx18_audio_set_io(cx);
724		if (atomic_read(&cx->ana_capturing) > 0) {
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)) {
770			if (atomic_read(&cx->ana_capturing) > 0) {
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 */
784		cx18_call_all(cx, tuner, s_radio);
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
793int cx18_v4l2_open(struct file *filp)
794{
795	int res;
796	struct video_device *video_dev = video_devdata(filp);
797	struct cx18_stream *s = video_get_drvdata(video_dev);
798	struct cx18 *cx = s->cx;
799
800	mutex_lock(&cx->serialize_lock);
801	if (cx18_init_on_first_open(cx)) {
802		CX18_ERR("Failed to initialize on %s\n",
803			 video_device_node_name(video_dev));
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{
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	}
822	CX18_DEBUG_INFO("Mute\n");
823}
824
825void cx18_unmute(struct cx18 *cx)
826{
827	u32 h;
828	if (atomic_read(&cx->ana_capturing)) {
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");
836	}
837	CX18_DEBUG_INFO("Unmute\n");
838}
839