11c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil/*
21c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  cx18 file operation functions
31c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
41c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Derived from ivtv-fileops.c
51c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
61c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
76afdeaf865b729287e02aafc61d8d013b89996efAndy Walls *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
81c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
91c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  This program is free software; you can redistribute it and/or modify
101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  it under the terms of the GNU General Public License as published by
111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  the Free Software Foundation; either version 2 of the License, or
121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  (at your option) any later version.
131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  This program is distributed in the hope that it will be useful,
151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  but WITHOUT ANY WARRANTY; without even the implied warranty of
161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  GNU General Public License for more details.
181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *
191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  You should have received a copy of the GNU General Public License
201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  along with this program; if not, write to the Free Software
211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil *  02111-1307  USA
231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil */
241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-driver.h"
261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-fileops.h"
271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-i2c.h"
281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-queue.h"
291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-vbi.h"
301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-audio.h"
311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-mailbox.h"
321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-scb.h"
331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-streams.h"
341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-controls.h"
351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-ioctl.h"
361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil#include "cx18-cards.h"
371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil/* This function tries to claim the stream for a specific file descriptor.
391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil   If no one else is using this stream then the stream is claimed and
4079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls   associated VBI and IDX streams are also automatically claimed.
411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil   Possible error returns: -EBUSY if someone else has claimed
421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil   the stream or 0 on success. */
438ef22f794ea5577505bc71e468183585f429afdeDevin Heitmuellerint cx18_claim_stream(struct cx18_open_id *id, int type)
441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = id->cx;
461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[type];
4779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	struct cx18_stream *s_assoc;
4879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls
4979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/* Nothing should ever try to directly claim the IDX stream */
5079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (type == CX18_ENC_STREAM_TYPE_IDX) {
5179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		CX18_WARN("MPEG Index stream cannot be claimed "
5279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			  "directly, but something tried.\n");
5379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		return -EINVAL;
5479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	}
551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* someone already claimed this stream */
581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (s->id == id->open_id) {
591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* yes, this file descriptor did. So that's OK. */
601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return 0;
611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* VBI is handled already internally, now also assign
641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			   the file descriptor to this stream for external
651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			   reading of the stream. */
661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			s->id = id->open_id;
671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			CX18_DEBUG_INFO("Start Read VBI\n");
681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return 0;
691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* someone else is using this stream already */
711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_INFO("Stream %d is busy\n", type);
721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EBUSY;
731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	s->id = id->open_id;
751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/*
7779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * CX18_ENC_STREAM_TYPE_MPG needs to claim:
7879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
7979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
8079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * (We don't yet fix up MPEG Index entries for our inserted packets).
8179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 *
8279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * For all other streams we're done.
8379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 */
8479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (type != CX18_ENC_STREAM_TYPE_MPG)
8579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		return 0;
8679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls
8779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
8879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
8979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
9079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	else if (!cx18_stream_enabled(s_assoc))
911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return 0;
921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
9379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
941c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
951c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* mark that it is used internally */
9679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return 0;
981c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
998ef22f794ea5577505bc71e468183585f429afdeDevin HeitmuellerEXPORT_SYMBOL(cx18_claim_stream);
1001c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1011c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil/* This function releases a previously claimed stream. It will take into
1021c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil   account associated VBI streams. */
1038ef22f794ea5577505bc71e468183585f429afdeDevin Heitmuellervoid cx18_release_stream(struct cx18_stream *s)
1041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
1051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
10679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	struct cx18_stream *s_assoc;
1071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	s->id = -1;
10979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
11079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		/*
11179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 * The IDX stream is only used internally, and can
11279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 * only be indirectly unclaimed by unclaiming the MPG stream.
11379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 */
11479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		return;
11579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	}
11679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls
1171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
1181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
1191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* this stream is still in use internally */
1201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return;
1211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
1231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
1241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return;
1251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	cx18_flush_queues(s);
1281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
12979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/*
13079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * CX18_ENC_STREAM_TYPE_MPG needs to release the
13179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
13279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 *
13379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * For all other streams we're done.
13479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 */
13579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (s->type != CX18_ENC_STREAM_TYPE_MPG)
1361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return;
1371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
13879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/* Unclaim the associated MPEG Index stream */
13979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
14079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
14179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
14279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		cx18_flush_queues(s_assoc);
1431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
14479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls
14579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/* Unclaim the associated VBI stream */
14679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
14779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
14879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		if (s_assoc->id == -1) {
14979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			/*
15079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			 * The VBI stream is not still claimed by a file
15179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			 * descriptor, so completely unclaim it.
15279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			 */
15379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
15479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			cx18_flush_queues(s_assoc);
15579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		}
1561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
1571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
1588ef22f794ea5577505bc71e468183585f429afdeDevin HeitmuellerEXPORT_SYMBOL(cx18_release_stream);
1591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic void cx18_dualwatch(struct cx18 *cx)
1611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
1621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct v4l2_tuner vt;
1630d82fe801d7c6d8cb8987e66b570f6decde9e235Andy Walls	u32 new_stereo_mode;
1640d82fe801d7c6d8cb8987e66b570f6decde9e235Andy Walls	const u32 dual = 0x0200;
1651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
166a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil	new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
1671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	memset(&vt, 0, sizeof(vt));
168ff2a20018094c593a35f4887bbdabf8926ddb6e6Andy Walls	cx18_call_all(cx, tuner, g_tuner, &vt);
1691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
1701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			(vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
1711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		new_stereo_mode = dual;
1721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (new_stereo_mode == cx->dualwatch_stereo_mode)
1741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return;
1751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
176a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil	CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
177a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil			   cx->dualwatch_stereo_mode, new_stereo_mode);
178a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil	if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
179a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil		CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
1801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
1811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
18352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Wallsstatic struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
18452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				     int *err)
1851c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
1861c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
1871c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
18852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	struct cx18_mdl *mdl;
1891c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	DEFINE_WAIT(wait);
1901c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
1911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	*err = 0;
1921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	while (1) {
1931c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
1949bff2d61716bffe5e1d58de9eb940c62bb020fcfAndy Walls			/* Process pending program updates and VBI data */
1951c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
1961c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				cx->dualwatch_jiffies = jiffies;
1971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				cx18_dualwatch(cx);
1981c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
1991c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
2001c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
20152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				while ((mdl = cx18_dequeue(s_vbi,
20252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls							   &s_vbi->q_full))) {
2031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil					/* byteswap and process VBI data */
20452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls					cx18_process_vbi_data(cx, mdl,
205af009cf635141858642864a26602e379e97bf7d6Andy Walls							      s_vbi->type);
20652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls					cx18_stream_put_mdl_fw(s_vbi, mdl);
2071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				}
2081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
20952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			mdl = &cx->vbi.sliced_mpeg_mdl;
21052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			if (mdl->readpos != mdl->bytesused)
21152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				return mdl;
2121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
2131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* do we have new data? */
21552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		mdl = cx18_dequeue(s, &s->q_full);
21652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		if (mdl) {
21752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
21852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls						&mdl->m_flags))
21952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				return mdl;
2201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (s->type == CX18_ENC_STREAM_TYPE_MPG)
2211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				/* byteswap MPG data */
22252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				cx18_mdl_swap(mdl);
2231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			else {
2241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				/* byteswap and process VBI data */
22552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				cx18_process_vbi_data(cx, mdl, s->type);
2261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
22752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			return mdl;
2281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
2291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* return if end of stream */
2311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
2321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			CX18_DEBUG_INFO("EOS %s\n", s->name);
2331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return NULL;
2341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
2351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* return if file was opened with O_NONBLOCK */
2371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (non_block) {
2381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			*err = -EAGAIN;
2391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return NULL;
2401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
2411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* wait for more data to arrive */
2431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
2441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* New buffers might have become available before we were added
2451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		   to the waitqueue */
246c37b11bf17b66b960b217c35283aa9c55eacb292Andy Walls		if (!atomic_read(&s->q_full.depth))
2471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			schedule();
2481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		finish_wait(&s->waitq, &wait);
2491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (signal_pending(current)) {
2501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* return if a signal was received */
2511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			CX18_DEBUG_INFO("User stopped %s\n", s->name);
2521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			*err = -EINTR;
2531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return NULL;
2541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
2551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
2561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
2571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
25852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Wallsstatic void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
2591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
26052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
26152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
2621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
2631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
26452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	buf->buf = cx->vbi.sliced_mpeg_data[idx];
26552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
26652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	buf->readpos = 0;
26752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
26852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	mdl->curr_buf = NULL;
26952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
27052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	mdl->readpos = 0;
2711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
2721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
2731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic size_t cx18_copy_buf_to_user(struct cx18_stream *s,
27452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
2751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
2761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
2771c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	size_t len = buf->bytesused - buf->readpos;
2781c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
27952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	*stop = false;
2801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (len > ucount)
2811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		len = ucount;
2821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
283dd073434b5285121007860914a004320d644ee7eAndy Walls	    !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
284302df9702192a68578916ef922c33370cbba350dAndy Walls		/*
285302df9702192a68578916ef922c33370cbba350dAndy Walls		 * Try to find a good splice point in the PS, just before
286302df9702192a68578916ef922c33370cbba350dAndy Walls		 * an MPEG-2 Program Pack start code, and provide only
287302df9702192a68578916ef922c33370cbba350dAndy Walls		 * up to that point to the user, so it's easy to insert VBI data
288302df9702192a68578916ef922c33370cbba350dAndy Walls		 * the next time around.
2890c6292522968427d4f8e01f7c2e4216f04470072Andy Walls		 *
2900c6292522968427d4f8e01f7c2e4216f04470072Andy Walls		 * This will not work for an MPEG-2 TS and has only been
2910c6292522968427d4f8e01f7c2e4216f04470072Andy Walls		 * verified by analysis to work for an MPEG-2 PS.  Helen Buus
2920c6292522968427d4f8e01f7c2e4216f04470072Andy Walls		 * pointed out this works for the CX23416 MPEG-2 DVD compatible
2930c6292522968427d4f8e01f7c2e4216f04470072Andy Walls		 * stream, and research indicates both the MPEG 2 SVCD and DVD
2940c6292522968427d4f8e01f7c2e4216f04470072Andy Walls		 * stream types use an MPEG-2 PS container.
295302df9702192a68578916ef922c33370cbba350dAndy Walls		 */
296302df9702192a68578916ef922c33370cbba350dAndy Walls		/*
297302df9702192a68578916ef922c33370cbba350dAndy Walls		 * An MPEG-2 Program Stream (PS) is a series of
298302df9702192a68578916ef922c33370cbba350dAndy Walls		 * MPEG-2 Program Packs terminated by an
299302df9702192a68578916ef922c33370cbba350dAndy Walls		 * MPEG Program End Code after the last Program Pack.
300302df9702192a68578916ef922c33370cbba350dAndy Walls		 * A Program Pack may hold a PS System Header packet and any
301302df9702192a68578916ef922c33370cbba350dAndy Walls		 * number of Program Elementary Stream (PES) Packets
302302df9702192a68578916ef922c33370cbba350dAndy Walls		 */
3031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		const char *start = buf->buf + buf->readpos;
3041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		const char *p = start + 1;
3051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		const u8 *q;
3061c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		u8 ch = cx->search_pack_header ? 0xba : 0xe0;
3071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		int stuffing, i;
3081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
3091c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		while (start + len > p) {
310302df9702192a68578916ef922c33370cbba350dAndy Walls			/* Scan for a 0 to find a potential MPEG-2 start code */
3111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			q = memchr(p, 0, start + len - p);
3121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (q == NULL)
3131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				break;
3141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			p = q + 1;
315302df9702192a68578916ef922c33370cbba350dAndy Walls			/*
316302df9702192a68578916ef922c33370cbba350dAndy Walls			 * Keep looking if not a
317302df9702192a68578916ef922c33370cbba350dAndy Walls			 * MPEG-2 Pack header start code:  0x00 0x00 0x01 0xba
318302df9702192a68578916ef922c33370cbba350dAndy Walls			 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
319302df9702192a68578916ef922c33370cbba350dAndy Walls			 */
3201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if ((char *)q + 15 >= buf->buf + buf->bytesused ||
3211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			    q[1] != 0 || q[2] != 1 || q[3] != ch)
3221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				continue;
323302df9702192a68578916ef922c33370cbba350dAndy Walls
324302df9702192a68578916ef922c33370cbba350dAndy Walls			/* If expecting the primary video PES */
3251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (!cx->search_pack_header) {
326302df9702192a68578916ef922c33370cbba350dAndy Walls				/* Continue if it couldn't be a PES packet */
3271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				if ((q[6] & 0xc0) != 0x80)
3281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil					continue;
329302df9702192a68578916ef922c33370cbba350dAndy Walls				/* Check if a PTS or PTS & DTS follow */
330302df9702192a68578916ef922c33370cbba350dAndy Walls				if (((q[7] & 0xc0) == 0x80 &&  /* PTS only */
331302df9702192a68578916ef922c33370cbba350dAndy Walls				     (q[9] & 0xf0) == 0x20) || /* PTS only */
332302df9702192a68578916ef922c33370cbba350dAndy Walls				    ((q[7] & 0xc0) == 0xc0 &&  /* PTS & DTS */
333302df9702192a68578916ef922c33370cbba350dAndy Walls				     (q[9] & 0xf0) == 0x30)) { /* DTS follows */
334302df9702192a68578916ef922c33370cbba350dAndy Walls					/* Assume we found the video PES hdr */
335302df9702192a68578916ef922c33370cbba350dAndy Walls					ch = 0xba; /* next want a Program Pack*/
3361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil					cx->search_pack_header = 1;
337302df9702192a68578916ef922c33370cbba350dAndy Walls					p = q + 9; /* Skip this video PES hdr */
3381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				}
3391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				continue;
3401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
341302df9702192a68578916ef922c33370cbba350dAndy Walls
342302df9702192a68578916ef922c33370cbba350dAndy Walls			/* We may have found a Program Pack start code */
343302df9702192a68578916ef922c33370cbba350dAndy Walls
344302df9702192a68578916ef922c33370cbba350dAndy Walls			/* Get the count of stuffing bytes & verify them */
3451c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			stuffing = q[13] & 7;
3461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* all stuffing bytes must be 0xff */
3471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			for (i = 0; i < stuffing; i++)
3481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				if (q[14 + i] != 0xff)
3491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil					break;
350302df9702192a68578916ef922c33370cbba350dAndy Walls			if (i == stuffing && /* right number of stuffing bytes*/
351302df9702192a68578916ef922c33370cbba350dAndy Walls			    (q[4] & 0xc4) == 0x44 && /* marker check */
352302df9702192a68578916ef922c33370cbba350dAndy Walls			    (q[12] & 3) == 3 &&  /* marker check */
353302df9702192a68578916ef922c33370cbba350dAndy Walls			    q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
3541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			    q[15 + stuffing] == 0 &&
3551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			    q[16 + stuffing] == 1) {
356302df9702192a68578916ef922c33370cbba350dAndy Walls				/* We declare we actually found a Program Pack*/
357302df9702192a68578916ef922c33370cbba350dAndy Walls				cx->search_pack_header = 0; /* expect vid PES */
3581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				len = (char *)q - start;
35952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				cx18_setup_sliced_vbi_mdl(cx);
36052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				*stop = true;
3611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				break;
3621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
3631c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
3641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
3651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
3661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
3671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				len, s->name);
3681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EFAULT;
3691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
3701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	buf->readpos += len;
3711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
3721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	    buf != &cx->vbi.sliced_mpeg_buf)
3731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx->mpg_data_received += len;
3741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return len;
3751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
3761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
37752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Wallsstatic size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
37852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
37952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls{
38052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	size_t tot_written = 0;
38152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	int rc;
38252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	bool stop = false;
38352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
38452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	if (mdl->curr_buf == NULL)
38552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		mdl->curr_buf = list_first_entry(&mdl->buf_list,
38652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls						 struct cx18_buffer, list);
38752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
38852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
38952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		/*
39052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		 * For some reason we've exhausted the buffers, but the MDL
39152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		 * object still said some data was unread.
39252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		 * Fix that and bail out.
39352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		 */
39452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		mdl->readpos = mdl->bytesused;
39552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		return 0;
39652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	}
39752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
39852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
39952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
40052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
40152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			continue;
40252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
40352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
40452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls					   ucount - tot_written, &stop);
40552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		if (rc < 0)
40652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			return rc;
40752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		mdl->readpos += rc;
40852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		tot_written += rc;
40952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
41052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		if (stop ||	/* Forced stopping point for VBI insertion */
41152fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		    tot_written >= ucount ||	/* Reader request statisfied */
41252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		    mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
41352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		    mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
41452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			break;
41552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	}
41652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls	return tot_written;
41752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls}
41852fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls
4191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
4201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		size_t tot_count, int non_block)
4211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
4221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
4231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	size_t tot_written = 0;
4241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int single_frame = 0;
4251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
42631554ae599a8ff6854bf8ecbedc1946c64854388Hans Verkuil	if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
4271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* shouldn't happen */
4281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_WARN("Stream %s not initialized before read\n",
4291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				s->name);
4301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EIO;
4311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
4321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Each VBI buffer is one frame, the v4l2 API says that for VBI the
4341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	   frames should arrive one-by-one, so make sure we never output more
4351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	   than one VBI frame at a time */
436dd073434b5285121007860914a004320d644ee7eAndy Walls	if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
4371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		single_frame = 1;
4381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	for (;;) {
44052fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		struct cx18_mdl *mdl;
4411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		int rc;
4421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
44352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		mdl = cx18_get_mdl(s, non_block, &rc);
4441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* if there is no data available... */
44552fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		if (mdl == NULL) {
4461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* if we got data, then return that regardless */
4471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (tot_written)
4481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				break;
4491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* EOS condition */
4501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			if (rc == 0) {
4511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
4521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
4531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				cx18_release_stream(s);
4541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
4551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* set errno */
4561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return rc;
4571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
4581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
45952fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
4601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				tot_count - tot_written);
4611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
46252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		if (mdl != &cx->vbi.sliced_mpeg_mdl) {
46352fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			if (mdl->readpos == mdl->bytesused)
46452fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				cx18_stream_put_mdl_fw(s, mdl);
46566c2a6b0bc0b394d215768610d96f44cf97052acAndy Walls			else
46652fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls				cx18_push(s, mdl, &s->q_full);
46752fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls		} else if (mdl->readpos == mdl->bytesused) {
4681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
4691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4701c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			cx->vbi.sliced_mpeg_size[idx] = 0;
4711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			cx->vbi.inserted_frame++;
47252fcb3ecc6707f52dfe4297f96b7609d4ba517fbAndy Walls			cx->vbi_data_inserted += mdl->bytesused;
4731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
4741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (rc < 0)
4751c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return rc;
4761c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		tot_written += rc;
4771c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4781c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (tot_written == tot_count || single_frame)
4791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			break;
4801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
4811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return tot_written;
4821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
4831c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4841c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
4851c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		size_t count, loff_t *pos, int non_block)
4861c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
4871c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
4881c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
4891c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4901c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
4911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (rc > 0)
4921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		pos += rc;
4931c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return rc;
4941c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
4951c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
4961c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilint cx18_start_capture(struct cx18_open_id *id)
4971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
4981c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = id->cx;
4991c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[id->type];
5001c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s_vbi;
50179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	struct cx18_stream *s_idx;
5021c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
5041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* you cannot read from these stream types. */
5051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EPERM;
5061c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
5071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Try to claim this stream. */
5091c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (cx18_claim_stream(id, s->type))
5101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -EBUSY;
5111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* If capture is already in progress, then we also have to
5131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	   do nothing extra. */
5141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
5151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	    test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
5161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		set_bit(CX18_F_S_APPL_IO, &s->s_flags);
5171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return 0;
5181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
5191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
52079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/* Start associated VBI or IDX stream capture if required */
5211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
52279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
52379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
52479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		/*
52579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 * The VBI and IDX streams should have been claimed
52679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 * automatically, if for internal use, when the MPG stream was
52779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 * claimed.  We only need to start these streams capturing.
52879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		 */
52979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
53079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		    !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
53179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			if (cx18_start_v4l2_encode_stream(s_idx)) {
53279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				CX18_DEBUG_WARN("IDX capture start failed\n");
53379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
53479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				goto start_failed;
53579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			}
53679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			CX18_DEBUG_INFO("IDX capture started\n");
53779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		}
53879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
53979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		    !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
54079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			if (cx18_start_v4l2_encode_stream(s_vbi)) {
54179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				CX18_DEBUG_WARN("VBI capture start failed\n");
54279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
54379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				goto start_failed;
54479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			}
54579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			CX18_DEBUG_INFO("VBI insertion started\n");
5461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
5471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
5481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Tell the card to start capturing */
5501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (!cx18_start_v4l2_encode_stream(s)) {
5511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* We're done */
5521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		set_bit(CX18_F_S_APPL_IO, &s->s_flags);
5531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Resume a possibly paused encoder */
5541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
5551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
5561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return 0;
5571c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
5581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
55979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Wallsstart_failed:
5601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
5611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
56279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	/*
56379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * The associated VBI and IDX streams for internal use are released
56479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * automatically when the MPG stream is released.  We only need to stop
56579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 * the associated stream.
56679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	 */
56779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
56879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		/* Stop the IDX stream which is always for internal use */
56979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
57079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			cx18_stop_v4l2_encode_stream(s_idx, 0);
57179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
57279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		}
57379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		/* Stop the VBI stream, if only running for internal use */
57479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
57579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
57679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			cx18_stop_v4l2_encode_stream(s_vbi, 0);
57779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
57879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		}
5791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
5801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	clear_bit(CX18_F_S_STREAMING, &s->s_flags);
58179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	cx18_release_stream(s); /* Also releases associated streams */
5821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return -EIO;
5831c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
5841c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5851c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
5861c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		loff_t *pos)
5871c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
5880b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	struct cx18_open_id *id = file2id(filp);
5891c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = id->cx;
5901c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[id->type];
5911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int rc;
5921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5931c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
5941c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
5951c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mutex_lock(&cx->serialize_lock);
5961c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	rc = cx18_start_capture(id);
5971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mutex_unlock(&cx->serialize_lock);
5981c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (rc)
5991c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return rc;
600b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
6011bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth	if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
602b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
6031bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth		return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
604b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			filp->f_flags & O_NONBLOCK);
605b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	}
606b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
6071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
6081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
6091c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
6101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilunsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
6111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
6120b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	struct cx18_open_id *id = file2id(filp);
6131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = id->cx;
6141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[id->type];
6151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
6161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
6171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Start a capture if there is none */
6181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
6191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		int rc;
6201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
6211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		mutex_lock(&cx->serialize_lock);
6221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		rc = cx18_start_capture(id);
6231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		mutex_unlock(&cx->serialize_lock);
6241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (rc) {
6251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
6261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil					s->name, rc);
6271c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			return POLLERR;
6281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
6291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_FILE("Encoder poll started capture\n");
6301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
6311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
6321bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth	if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
633b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
6341bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth		int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
6351bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth                if (eof && videobuf_poll == POLLERR)
6361bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth                        return POLLHUP;
6371bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth                else
6381bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth                        return videobuf_poll;
639b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	}
640b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
6411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* add stream's waitq to the poll list */
6421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_HI_FILE("Encoder poll\n");
6431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	poll_wait(filp, &s->waitq, wait);
6441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
645c37b11bf17b66b960b217c35283aa9c55eacb292Andy Walls	if (atomic_read(&s->q_full.depth))
6461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return POLLIN | POLLRDNORM;
6471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (eof)
6481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return POLLHUP;
6491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return 0;
6501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
6511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
652b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Tothint cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
653b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth{
654b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	struct cx18_open_id *id = file->private_data;
655b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	struct cx18 *cx = id->cx;
656b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	struct cx18_stream *s = &cx->streams[id->type];
657b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
658b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
6591bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth	if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
660b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
661b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
662b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		/* Start a capture if there is none */
663b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
664b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			int rc;
665b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
666b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			mutex_lock(&cx->serialize_lock);
667b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			rc = cx18_start_capture(id);
668b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			mutex_unlock(&cx->serialize_lock);
669b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			if (rc) {
670b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth				CX18_DEBUG_INFO(
671b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth					"Could not start capture for %s (%d)\n",
672b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth					s->name, rc);
673b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth				return -EINVAL;
674b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			}
6751bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth			CX18_DEBUG_FILE("Encoder mmap started capture\n");
676b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		}
677b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
6781bf5842fe3b61d2dbbced96dbd27ad26fe93444aSimon Farnsworth		return videobuf_mmap_mapper(&s->vbuf_q, vma);
679b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	}
680b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
681b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	return -EINVAL;
682b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth}
683b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
684b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Tothvoid cx18_vb_timeout(unsigned long data)
685b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth{
686b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	struct cx18_stream *s = (struct cx18_stream *)data;
687b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	struct cx18_videobuf_buffer *buf;
688b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	unsigned long flags;
689b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
690b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	/* Return all of the buffers in error state, so the vbi/vid inode
691b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	 * can return from blocking.
692b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	 */
693b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	spin_lock_irqsave(&s->vb_lock, flags);
694b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	while (!list_empty(&s->vb_capture)) {
695b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		buf = list_entry(s->vb_capture.next,
696b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth			struct cx18_videobuf_buffer, vb.queue);
697b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		list_del(&buf->vb.queue);
698b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		buf->vb.state = VIDEOBUF_ERROR;
699b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth		wake_up(&buf->vb.done);
700b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	}
701b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth	spin_unlock_irqrestore(&s->vb_lock, flags);
702b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth}
703b7101de3fff596b35e45cd9fb7007caa07e97c9aSteven Toth
7041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilvoid cx18_stop_capture(struct cx18_open_id *id, int gop_end)
7051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
7061c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = id->cx;
7071c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[id->type];
70879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
70979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls	struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
7101c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_IOCTL("close() of %s\n", s->name);
7121c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* 'Unclaim' this stream */
7141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7151c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Stop capturing */
7161c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
7171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_INFO("close stopping capture\n");
71879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls		if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
71979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			/* Stop internal use associated VBI and IDX streams */
72079f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
72179f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
72279f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				CX18_DEBUG_INFO("close stopping embedded VBI "
72379f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls						"capture\n");
72479f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				cx18_stop_v4l2_encode_stream(s_vbi, 0);
72579f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			}
72679f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
72779f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				CX18_DEBUG_INFO("close stopping IDX capture\n");
72879f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls				cx18_stop_v4l2_encode_stream(s_idx, 0);
72979f3e96018dc55ff7819a6a1ac3740a1d7103589Andy Walls			}
7301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
7311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
7321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		    test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
7331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* Also used internally, don't stop capturing */
7341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			s->id = -1;
7351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		else
7361c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			cx18_stop_v4l2_encode_stream(s, gop_end);
7371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
7381c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (!gop_end) {
7391c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
7401c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
7411c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_release_stream(s);
7421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
7431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
7441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
745bec43661b1dc0075b7445223ba775674133b164dHans Verkuilint cx18_v4l2_close(struct file *filp)
7461c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
7470b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	struct v4l2_fh *fh = filp->private_data;
7480b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	struct cx18_open_id *id = fh2id(fh);
7491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = id->cx;
7501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_stream *s = &cx->streams[id->type];
7511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_IOCTL("close() of %s\n", s->name);
7531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mutex_lock(&cx->serialize_lock);
7554d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	/* Stop radio */
7564d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
7574d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil			v4l2_fh_is_singular_file(filp)) {
7581c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Closing radio device, return to TV mode */
7591c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_mute(cx);
7601c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Mark that the radio is no longer in use */
7611c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
7621c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Switch tuner to TV */
763f41737ece472cd803ffb24ac9f5d6fdd1d871341Hans Verkuil		cx18_call_all(cx, core, s_std, cx->std);
7641c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Select correct audio input (i.e. TV tuner or Line in) */
7651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_audio_set_io(cx);
76631554ae599a8ff6854bf8ecbedc1946c64854388Hans Verkuil		if (atomic_read(&cx->ana_capturing) > 0) {
7671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			/* Undo video mute */
7681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
769a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil			    (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
770a75b9be1c2fb52dee765d35f29031dd788d522ebHans Verkuil			    (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
7711c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
7721c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Done! Unmute and continue. */
7731c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_unmute(cx);
7741c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
7754d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil
7764d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	v4l2_fh_del(fh);
7774d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	v4l2_fh_exit(fh);
7784d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil
7794d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	/* 'Unclaim' this stream */
7804d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	if (s->id == id->open_id)
7814d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil		cx18_stop_capture(id, 0);
7821c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	kfree(id);
7831c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mutex_unlock(&cx->serialize_lock);
7841c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return 0;
7851c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
7861c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7871c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilstatic int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
7881c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
7891c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18 *cx = s->cx;
7901c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	struct cx18_open_id *item;
7911c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7921c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_FILE("open %s\n", s->name);
7931c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
7941c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	/* Allocate memory */
7950b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
7961c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (NULL == item) {
7971c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		CX18_DEBUG_WARN("nomem on v4l2 open\n");
7981c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -ENOMEM;
7991c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
8000b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	v4l2_fh_init(&item->fh, s->video_dev);
8010b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil
8021c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	item->cx = cx;
8031c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	item->type = s->type;
8041c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
8051c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	item->open_id = cx->open_id++;
8060b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil	filp->private_data = &item->fh;
8074d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	v4l2_fh_add(&item->fh);
8081c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
8094d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil	if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
8104d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil			v4l2_fh_is_singular_file(filp)) {
8111c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
81231554ae599a8ff6854bf8ecbedc1946c64854388Hans Verkuil			if (atomic_read(&cx->ana_capturing) > 0) {
8131c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				/* switching to radio while capture is
8141c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				   in progress is not polite */
8154d68e700d6a192a5a8b394b26ac056a1c0fa6ebcHans Verkuil				v4l2_fh_del(&item->fh);
8160b5f265a88d89cbbf8abc42ca3311cb3219162abHans Verkuil				v4l2_fh_exit(&item->fh);
8171c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				kfree(item);
8181c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil				return -EBUSY;
8191c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil			}
8201c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		}
8211c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
8221c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Mark that the radio is being used. */
8231c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
8241c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* We have the radio */
8251c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_mute(cx);
8261c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Switch tuner to radio */
827ff2a20018094c593a35f4887bbdabf8926ddb6e6Andy Walls		cx18_call_all(cx, tuner, s_radio);
8281c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Select the correct audio input (i.e. radio tuner) */
8291c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_audio_set_io(cx);
8301c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		/* Done! Unmute and continue. */
8311c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		cx18_unmute(cx);
8321c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
8331c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return 0;
8341c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
8351c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
836bec43661b1dc0075b7445223ba775674133b164dHans Verkuilint cx18_v4l2_open(struct file *filp)
8371c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
8385811cf99df2e3c102055be3ea77508e56c9f77c6Andy Walls	int res;
8395811cf99df2e3c102055be3ea77508e56c9f77c6Andy Walls	struct video_device *video_dev = video_devdata(filp);
8405811cf99df2e3c102055be3ea77508e56c9f77c6Andy Walls	struct cx18_stream *s = video_get_drvdata(video_dev);
84132a60955fb6312f19ea4856e66b894bfb6c4e949Joe Perches	struct cx18 *cx = s->cx;
8421c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
8431c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mutex_lock(&cx->serialize_lock);
8441c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	if (cx18_init_on_first_open(cx)) {
84550462eb065e12f45851a9959a90d46b758944552Laurent Pinchart		CX18_ERR("Failed to initialize on %s\n",
84650462eb065e12f45851a9959a90d46b758944552Laurent Pinchart			 video_device_node_name(video_dev));
8471c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		mutex_unlock(&cx->serialize_lock);
8481c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil		return -ENXIO;
8491c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
8501c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	res = cx18_serialized_open(s, filp);
8511c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	mutex_unlock(&cx->serialize_lock);
8521c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	return res;
8531c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
8541c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
8551c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilvoid cx18_mute(struct cx18 *cx)
8561c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
857d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls	u32 h;
858d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls	if (atomic_read(&cx->ana_capturing)) {
859d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls		h = cx18_find_handle(cx);
860d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls		if (h != CX18_INVALID_TASK_HANDLE)
861d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls			cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
862d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls		else
863d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls			CX18_ERR("Can't find valid task handle for mute\n");
864d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls	}
8651c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_INFO("Mute\n");
8661c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
8671c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil
8681c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuilvoid cx18_unmute(struct cx18 *cx)
8691c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil{
870d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls	u32 h;
87131554ae599a8ff6854bf8ecbedc1946c64854388Hans Verkuil	if (atomic_read(&cx->ana_capturing)) {
872d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls		h = cx18_find_handle(cx);
873d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls		if (h != CX18_INVALID_TASK_HANDLE) {
874d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls			cx18_msleep_timeout(100, 0);
875d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls			cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
876d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls			cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
877d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls		} else
878d3c5e7075508a6874d1a53d0a409b0bbbe3a9fbeAndy Walls			CX18_ERR("Can't find valid task handle for unmute\n");
8791c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	}
8801c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil	CX18_DEBUG_INFO("Unmute\n");
8811c1e45d17b663d4749af456ab7c2fc1f36405ef8Hans Verkuil}
882