saa7164-encoder.c revision 46eeb8dd30d3651e6ea55c2e60594206cd591d79
19b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth/*
29b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  Driver for the NXP SAA7164 PCIe bridge
39b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *
49b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
59b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *
69b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  This program is free software; you can redistribute it and/or modify
79b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  it under the terms of the GNU General Public License as published by
89b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  the Free Software Foundation; either version 2 of the License, or
99b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  (at your option) any later version.
109b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *
119b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  This program is distributed in the hope that it will be useful,
129b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  but WITHOUT ANY WARRANTY; without even the implied warranty of
139b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
149b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *
159b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  GNU General Public License for more details.
169b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *
179b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  You should have received a copy of the GNU General Public License
189b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  along with this program; if not, write to the Free Software
199b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
209b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth */
219b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth
229b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth#include "saa7164.h"
239b8b0199b86eaa595e3ccacb413e955a193f1962Steven Toth
247615e434aefd95181eae099c4f019e021b024eb6Steven Toth#define ENCODER_MAX_BITRATE 6500000
257615e434aefd95181eae099c4f019e021b024eb6Steven Toth#define ENCODER_MIN_BITRATE 1000000
267615e434aefd95181eae099c4f019e021b024eb6Steven Toth#define ENCODER_DEF_BITRATE 5000000
277615e434aefd95181eae099c4f019e021b024eb6Steven Toth
287615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic struct saa7164_tvnorm saa7164_tvnorms[] = {
297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	{
307615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.name      = "NTSC-M",
317615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.id        = V4L2_STD_NTSC_M,
327615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}, {
337615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.name      = "NTSC-JP",
347615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.id        = V4L2_STD_NTSC_M_JP,
357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
367615e434aefd95181eae099c4f019e021b024eb6Steven Toth};
377615e434aefd95181eae099c4f019e021b024eb6Steven Toth
387615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic const u32 saa7164_v4l2_ctrls[] = {
397615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_BRIGHTNESS,
407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_CONTRAST,
417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_SATURATION,
427615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_HUE,
437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_AUDIO_VOLUME,
447615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_SHARPNESS,
455fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth	V4L2_CID_MPEG_STREAM_TYPE,
467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_MPEG_VIDEO_ASPECT,
475fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth	V4L2_CID_MPEG_VIDEO_B_FRAMES,
48f91d095c92e8fdcb6bd8cb35e8fa9c87d9c10768Steven Toth	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
497615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_MPEG_AUDIO_MUTE,
502600d71cc535907e5d95cd31751c587afc370065Steven Toth	V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
517615e434aefd95181eae099c4f019e021b024eb6Steven Toth	V4L2_CID_MPEG_VIDEO_BITRATE,
52968b11b20143036098a7013817a15615a54383d3Steven Toth	V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
537615e434aefd95181eae099c4f019e021b024eb6Steven Toth	0
547615e434aefd95181eae099c4f019e021b024eb6Steven Toth};
557615e434aefd95181eae099c4f019e021b024eb6Steven Toth
567615e434aefd95181eae099c4f019e021b024eb6Steven Toth/* Take the encoder configuration form the port struct and
577615e434aefd95181eae099c4f019e021b024eb6Steven Toth * flush it to the hardware.
587615e434aefd95181eae099c4f019e021b024eb6Steven Toth */
597615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic void saa7164_encoder_configure(struct saa7164_port *port)
607615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
627615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
637615e434aefd95181eae099c4f019e021b024eb6Steven Toth
647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.width = port->width;
657615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.height = port->height;
667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.is_50hz =
677615e434aefd95181eae099c4f019e021b024eb6Steven Toth		(port->encodernorm.id & V4L2_STD_625_50) != 0;
687615e434aefd95181eae099c4f019e021b024eb6Steven Toth
697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Set up the DIF (enable it) for analog mode by default */
707615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_initialize_dif(port);
717615e434aefd95181eae099c4f019e021b024eb6Steven Toth
727615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Configure the correct video standard */
737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_configure_dif(port, port->encodernorm.id);
747615e434aefd95181eae099c4f019e021b024eb6Steven Toth
757615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Ensure the audio decoder is correct configured */
767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_audio_std(port);
777615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
787615e434aefd95181eae099c4f019e021b024eb6Steven Toth
797615e434aefd95181eae099c4f019e021b024eb6Steven Toth/* One time configuration at registration time */
807615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_encoder_initialize(struct saa7164_port *port)
817615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
827615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
837615e434aefd95181eae099c4f019e021b024eb6Steven Toth
847615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
857615e434aefd95181eae099c4f019e021b024eb6Steven Toth
867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_encoder_configure(port);
877615e434aefd95181eae099c4f019e021b024eb6Steven Toth
887615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
897615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
907615e434aefd95181eae099c4f019e021b024eb6Steven Toth
917615e434aefd95181eae099c4f019e021b024eb6Steven Toth/* -- V4L2 --------------------------------------------------------- */
927615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
937615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
947615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
957615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
967615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
977615e434aefd95181eae099c4f019e021b024eb6Steven Toth	unsigned int i;
987615e434aefd95181eae099c4f019e021b024eb6Steven Toth
997615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)*id);
1007615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1017615e434aefd95181eae099c4f019e021b024eb6Steven Toth	for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
1027615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (*id & saa7164_tvnorms[i].id)
1037615e434aefd95181eae099c4f019e021b024eb6Steven Toth			break;
1047615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
1057615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (i == ARRAY_SIZE(saa7164_tvnorms))
1067615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
1077615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encodernorm = saa7164_tvnorms[i];
1097615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1107615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Update the audio decoder while is not running in
1117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	 * auto detect mode.
1127615e434aefd95181eae099c4f019e021b024eb6Steven Toth	 */
1137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_audio_std(port);
1147615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1157615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)*id);
1167615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1177615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
1187615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
1197615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1207615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_enum_input(struct file *file, void *priv,
1217615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_input *i)
1227615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
1237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int n;
1247615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	char *inputs[] = { "tuner", "composite", "svideo", "aux",
1267615e434aefd95181eae099c4f019e021b024eb6Steven Toth		"composite", "svideo", "aux" };
1277615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1287615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (i->index >= 7)
1297615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
1307615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	strcpy(i->name, inputs[ i->index ]);
1327615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (i->index == 0)
1347615e434aefd95181eae099c4f019e021b024eb6Steven Toth		i->type = V4L2_INPUT_TYPE_TUNER;
1357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	else
1367615e434aefd95181eae099c4f019e021b024eb6Steven Toth		i->type  = V4L2_INPUT_TYPE_CAMERA;
1377615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1387615e434aefd95181eae099c4f019e021b024eb6Steven Toth	for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
1397615e434aefd95181eae099c4f019e021b024eb6Steven Toth		i->std |= saa7164_tvnorms[n].id;
1407615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
1427615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
1437615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1447615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1457615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
1467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
1477615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
1487615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
1497615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1507615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (saa7164_api_get_videomux(port) != SAA_OK)
1517615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EIO;
1527615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1537615e434aefd95181eae099c4f019e021b024eb6Steven Toth	*i = (port->mux_input - 1);
1547615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1557615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, *i);
1567615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1577615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
1587615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
1597615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1607615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1617615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
1627615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
1637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
1647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
1657615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
1677615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1687615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (i >= 7)
1697615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
1707615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->mux_input = i + 1;
1727615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (saa7164_api_set_videomux(port) != SAA_OK)
1747615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EIO;
1757615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
1777615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
1787615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1797615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_g_tuner(struct file *file, void *priv,
1807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_tuner *t)
1817615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
1827615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
1837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
1847615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
1857615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (0 != t->index)
1877615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
1887615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	strcpy(t->name, "tuner");
1907615e434aefd95181eae099c4f019e021b024eb6Steven Toth	t->type = V4L2_TUNER_ANALOG_TV;
1917615e434aefd95181eae099c4f019e021b024eb6Steven Toth	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
1927615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1937615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
1947615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1957615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
1967615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
1977615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1987615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_tuner(struct file *file, void *priv,
1997615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_tuner *t)
2007615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
2017615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Update the A/V core */
2037615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2047615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
2057615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
2067615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2077615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_g_frequency(struct file *file, void *priv,
2087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_frequency *f)
2097615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
2107615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
2117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
2127615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->type = V4L2_TUNER_ANALOG_TV;
2147615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->frequency = port->freq;
2157615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2167615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
2177615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
2187615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2197615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_frequency(struct file *file, void *priv,
2207615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_frequency *f)
2217615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
2227615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
2237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
2247615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
2257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *tsport;
2267615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct dvb_frontend *fe;
2277615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2287615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* TODO: Pull this for the std */
2297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct analog_parameters params = {
2307615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.mode      = V4L2_TUNER_ANALOG_TV,
2317615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.audmode   = V4L2_TUNER_MODE_STEREO,
2327615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.std       = port->encodernorm.id,
2337615e434aefd95181eae099c4f019e021b024eb6Steven Toth		.frequency = f->frequency
2347615e434aefd95181eae099c4f019e021b024eb6Steven Toth	};
2357615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2367615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Stop the encoder */
2377615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s() frequency=%d tuner=%d\n", __func__,
2387615e434aefd95181eae099c4f019e021b024eb6Steven Toth		f->frequency, f->tuner);
2397615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (f->tuner != 0)
2417615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
2427615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (f->type != V4L2_TUNER_ANALOG_TV)
2447615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
2457615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->freq = f->frequency;
2477615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2487615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Update the hardware */
2497615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->nr == SAA7164_PORT_ENC1)
2507615e434aefd95181eae099c4f019e021b024eb6Steven Toth		tsport = &dev->ports[ SAA7164_PORT_TS1 ];
2517615e434aefd95181eae099c4f019e021b024eb6Steven Toth	else
2527615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->nr == SAA7164_PORT_ENC2)
2537615e434aefd95181eae099c4f019e021b024eb6Steven Toth		tsport = &dev->ports[ SAA7164_PORT_TS2 ];
2547615e434aefd95181eae099c4f019e021b024eb6Steven Toth	else
2557615e434aefd95181eae099c4f019e021b024eb6Steven Toth		BUG();
2567615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2577615e434aefd95181eae099c4f019e021b024eb6Steven Toth	fe = tsport->dvb.frontend;
2587615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2597615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (fe && fe->ops.tuner_ops.set_analog_params)
2607615e434aefd95181eae099c4f019e021b024eb6Steven Toth		fe->ops.tuner_ops.set_analog_params(fe, &params);
2617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	else
2627615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
2637615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_encoder_initialize(port);
2657615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
2677615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
2687615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2697615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_g_ctrl(struct file *file, void *priv,
2707615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_control *ctl)
2717615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
2727615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
2737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
2747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
2757615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
2777615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->id, ctl->value);
2787615e434aefd95181eae099c4f019e021b024eb6Steven Toth
2797615e434aefd95181eae099c4f019e021b024eb6Steven Toth	switch (ctl->id) {
2807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_BRIGHTNESS:
2817615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->value = port->ctl_brightness;
2827615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
2837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_CONTRAST:
2847615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->value = port->ctl_contrast;
2857615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
2867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_SATURATION:
2877615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->value = port->ctl_saturation;
2887615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
2897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_HUE:
2907615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->value = port->ctl_hue;
2917615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
2927615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_SHARPNESS:
2937615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->value = port->ctl_sharpness;
2947615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
2957615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_AUDIO_VOLUME:
2967615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->value = port->ctl_volume;
2977615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
2987615e434aefd95181eae099c4f019e021b024eb6Steven Toth	default:
2997615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
3007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
3017615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
3037615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
3047615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3057615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_ctrl(struct file *file, void *priv,
3067615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_control *ctl)
3077615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
3087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
3097615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
3107615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
3117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret = 0;
3127615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
3147615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctl->id, ctl->value);
3157615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3167615e434aefd95181eae099c4f019e021b024eb6Steven Toth	switch (ctl->id) {
3177615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_BRIGHTNESS:
3187615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctl->value >= 0) && (ctl->value <= 255)) {
3197615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->ctl_brightness = ctl->value;
3207615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_api_set_usercontrol(port,
3217615e434aefd95181eae099c4f019e021b024eb6Steven Toth				PU_BRIGHTNESS_CONTROL);
3227615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else
3237615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EINVAL;
3247615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_CONTRAST:
3267615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctl->value >= 0) && (ctl->value <= 255)) {
3277615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->ctl_contrast = ctl->value;
3287615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
3297615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else
3307615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EINVAL;
3317615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3327615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_SATURATION:
3337615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctl->value >= 0) && (ctl->value <= 255)) {
3347615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->ctl_saturation = ctl->value;
3357615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_api_set_usercontrol(port,
3367615e434aefd95181eae099c4f019e021b024eb6Steven Toth				PU_SATURATION_CONTROL);
3377615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else
3387615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EINVAL;
3397615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_HUE:
3417615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctl->value >= 0) && (ctl->value <= 255)) {
3427615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->ctl_hue = ctl->value;
3437615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
3447615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else
3457615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EINVAL;
3467615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3477615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_SHARPNESS:
3487615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctl->value >= 0) && (ctl->value <= 255)) {
3497615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->ctl_sharpness = ctl->value;
3507615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
3517615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else
3527615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EINVAL;
3537615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3547615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_AUDIO_VOLUME:
3557615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctl->value >= -83) && (ctl->value <= 24)) {
3567615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->ctl_volume = ctl->value;
3577615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_api_set_audio_volume(port, port->ctl_volume);
3587615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else
3597615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EINVAL;
3607615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	default:
3627615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EINVAL;
3637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
3647615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3657615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
3667615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
3677615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3687615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_get_ctrl(struct saa7164_port *port,
3697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_ext_control *ctrl)
3707615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
3717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_encoder_params *params = &port->encoder_params;
3727615e434aefd95181eae099c4f019e021b024eb6Steven Toth
3737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	switch (ctrl->id) {
3747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE:
3757615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctrl->value = params->bitrate;
3767615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3777615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_STREAM_TYPE:
3787615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctrl->value = params->stream_type;
3797615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_AUDIO_MUTE:
3817615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctrl->value = params->ctl_mute;
3827615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_ASPECT:
3847615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ctrl->value = params->ctl_aspect;
3857615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
3862600d71cc535907e5d95cd31751c587afc370065Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
3872600d71cc535907e5d95cd31751c587afc370065Steven Toth		ctrl->value = params->bitrate_mode;
3882600d71cc535907e5d95cd31751c587afc370065Steven Toth		break;
3893ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
3903ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		ctrl->value = params->refdist;
3913ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		break;
392968b11b20143036098a7013817a15615a54383d3Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
393968b11b20143036098a7013817a15615a54383d3Steven Toth		ctrl->value = params->bitrate_peak;
394968b11b20143036098a7013817a15615a54383d3Steven Toth		break;
3955fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
3965fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth		ctrl->value = params->gop_size;
3975fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth		break;
3987615e434aefd95181eae099c4f019e021b024eb6Steven Toth	default:
3997615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
4007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
4017615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
4027615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
4037615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4047615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_g_ext_ctrls(struct file *file, void *priv,
4057615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_ext_controls *ctrls)
4067615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
4077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
4087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
4097615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int i, err = 0;
4107615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
4127615e434aefd95181eae099c4f019e021b024eb6Steven Toth		for (i = 0; i < ctrls->count; i++) {
4137615e434aefd95181eae099c4f019e021b024eb6Steven Toth			struct v4l2_ext_control *ctrl = ctrls->controls + i;
4147615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4157615e434aefd95181eae099c4f019e021b024eb6Steven Toth			err = saa7164_get_ctrl(port, ctrl);
4167615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if (err) {
4177615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ctrls->error_idx = i;
4187615e434aefd95181eae099c4f019e021b024eb6Steven Toth				break;
4197615e434aefd95181eae099c4f019e021b024eb6Steven Toth			}
4207615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
4217615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return err;
4227615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
4247615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return -EINVAL;
4267615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
4277615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4287615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
4297615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
4307615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret = -EINVAL;
4317615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4327615e434aefd95181eae099c4f019e021b024eb6Steven Toth	switch (ctrl->id) {
4337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE:
4347615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
4357615e434aefd95181eae099c4f019e021b024eb6Steven Toth			(ctrl->value <= ENCODER_MAX_BITRATE))
4367615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = 0;
4377615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
4387615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_STREAM_TYPE:
439f91d095c92e8fdcb6bd8cb35e8fa9c87d9c10768Steven Toth		if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
440f91d095c92e8fdcb6bd8cb35e8fa9c87d9c10768Steven Toth			(ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
4417615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = 0;
4427615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
4437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_AUDIO_MUTE:
4447615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctrl->value >= 0) &&
4457615e434aefd95181eae099c4f019e021b024eb6Steven Toth			(ctrl->value <= 1))
4467615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = 0;
4477615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
4487615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_ASPECT:
4497615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
4507615e434aefd95181eae099c4f019e021b024eb6Steven Toth			(ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
4517615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = 0;
4527615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
4537615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
4547615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((ctrl->value >= 0) &&
4557615e434aefd95181eae099c4f019e021b024eb6Steven Toth			(ctrl->value <= 255))
4567615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = 0;
4577615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
4582600d71cc535907e5d95cd31751c587afc370065Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
4592600d71cc535907e5d95cd31751c587afc370065Steven Toth		if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ||
4602600d71cc535907e5d95cd31751c587afc370065Steven Toth			(ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
4612600d71cc535907e5d95cd31751c587afc370065Steven Toth			ret = 0;
4622600d71cc535907e5d95cd31751c587afc370065Steven Toth		break;
4633ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
4643ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		if ((ctrl->value >= 1) &&
4653ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth			(ctrl->value <= 3))
4663ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth			ret = 0;
4673ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		break;
468968b11b20143036098a7013817a15615a54383d3Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
469968b11b20143036098a7013817a15615a54383d3Steven Toth		if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
470968b11b20143036098a7013817a15615a54383d3Steven Toth			(ctrl->value <= ENCODER_MAX_BITRATE))
471968b11b20143036098a7013817a15615a54383d3Steven Toth			ret = 0;
472968b11b20143036098a7013817a15615a54383d3Steven Toth		break;
4737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	default:
4747615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EINVAL;
4757615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
4767615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4777615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
4787615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
4797615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4807615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_try_ext_ctrls(struct file *file, void *priv,
4817615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_ext_controls *ctrls)
4827615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
4837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int i, err = 0;
4847615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4857615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
4867615e434aefd95181eae099c4f019e021b024eb6Steven Toth		for (i = 0; i < ctrls->count; i++) {
4877615e434aefd95181eae099c4f019e021b024eb6Steven Toth			struct v4l2_ext_control *ctrl = ctrls->controls + i;
4887615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4897615e434aefd95181eae099c4f019e021b024eb6Steven Toth			err = saa7164_try_ctrl(ctrl, 0);
4907615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if (err) {
4917615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ctrls->error_idx = i;
4927615e434aefd95181eae099c4f019e021b024eb6Steven Toth				break;
4937615e434aefd95181eae099c4f019e021b024eb6Steven Toth			}
4947615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
4957615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return err;
4967615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
4977615e434aefd95181eae099c4f019e021b024eb6Steven Toth
4987615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return -EINVAL;
4997615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
5007615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5017615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_set_ctrl(struct saa7164_port *port,
5027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_ext_control *ctrl)
5037615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
5047615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_encoder_params *params = &port->encoder_params;
5057615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret = 0;
5067615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	switch (ctrl->id) {
5087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE:
5097615e434aefd95181eae099c4f019e021b024eb6Steven Toth		params->bitrate = ctrl->value;
5107615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
5117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_STREAM_TYPE:
5127615e434aefd95181eae099c4f019e021b024eb6Steven Toth		params->stream_type = ctrl->value;
5137615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
5147615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_AUDIO_MUTE:
5157615e434aefd95181eae099c4f019e021b024eb6Steven Toth		params->ctl_mute = ctrl->value;
5167615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = saa7164_api_audio_mute(port, params->ctl_mute);
5177615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (ret != SAA_OK) {
5187615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
5197615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ret);
5207615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EIO;
5217615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
5227615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
5237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_ASPECT:
5247615e434aefd95181eae099c4f019e021b024eb6Steven Toth		params->ctl_aspect = ctrl->value;
5257615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = saa7164_api_set_aspect_ratio(port);
5267615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (ret != SAA_OK) {
5277615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
5287615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ret);
5297615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ret = -EIO;
5307615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
5317615e434aefd95181eae099c4f019e021b024eb6Steven Toth		break;
5322600d71cc535907e5d95cd31751c587afc370065Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
5332600d71cc535907e5d95cd31751c587afc370065Steven Toth		params->bitrate_mode = ctrl->value;
5342600d71cc535907e5d95cd31751c587afc370065Steven Toth		break;
5353ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
5363ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		params->refdist = ctrl->value;
5373ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		break;
538968b11b20143036098a7013817a15615a54383d3Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
539968b11b20143036098a7013817a15615a54383d3Steven Toth		params->bitrate_peak = ctrl->value;
540968b11b20143036098a7013817a15615a54383d3Steven Toth		break;
5415fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
5425fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth		params->gop_size = ctrl->value;
5435fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth		break;
5447615e434aefd95181eae099c4f019e021b024eb6Steven Toth	default:
5457615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
5467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
5477615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5487615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* TODO: Update the hardware */
5497615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5507615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
5517615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
5527615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5537615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_ext_ctrls(struct file *file, void *priv,
5547615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_ext_controls *ctrls)
5557615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
5567615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
5577615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
5587615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int i, err = 0;
5597615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5607615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
5617615e434aefd95181eae099c4f019e021b024eb6Steven Toth		for (i = 0; i < ctrls->count; i++) {
5627615e434aefd95181eae099c4f019e021b024eb6Steven Toth			struct v4l2_ext_control *ctrl = ctrls->controls + i;
5637615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5647615e434aefd95181eae099c4f019e021b024eb6Steven Toth			err = saa7164_try_ctrl(ctrl, 0);
5657615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if (err) {
5667615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ctrls->error_idx = i;
5677615e434aefd95181eae099c4f019e021b024eb6Steven Toth				break;
5687615e434aefd95181eae099c4f019e021b024eb6Steven Toth			}
5697615e434aefd95181eae099c4f019e021b024eb6Steven Toth			err = saa7164_set_ctrl(port, ctrl);
5707615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if (err) {
5717615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ctrls->error_idx = i;
5727615e434aefd95181eae099c4f019e021b024eb6Steven Toth				break;
5737615e434aefd95181eae099c4f019e021b024eb6Steven Toth			}
5747615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
5757615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return err;
5767615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5777615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
5787615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5797615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return -EINVAL;
5807615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
5817615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5827615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_querycap(struct file *file, void  *priv,
5837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_capability *cap)
5847615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
5857615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
5867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
5877615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
5887615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	strcpy(cap->driver, dev->name);
5907615e434aefd95181eae099c4f019e021b024eb6Steven Toth	strlcpy(cap->card, saa7164_boards[dev->board].name,
5917615e434aefd95181eae099c4f019e021b024eb6Steven Toth		sizeof(cap->card));
5927615e434aefd95181eae099c4f019e021b024eb6Steven Toth	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
5937615e434aefd95181eae099c4f019e021b024eb6Steven Toth
5947615e434aefd95181eae099c4f019e021b024eb6Steven Toth	cap->capabilities =
5957615e434aefd95181eae099c4f019e021b024eb6Steven Toth		V4L2_CAP_VIDEO_CAPTURE |
5967615e434aefd95181eae099c4f019e021b024eb6Steven Toth		V4L2_CAP_READWRITE     |
5977615e434aefd95181eae099c4f019e021b024eb6Steven Toth		V4L2_CAP_STREAMING     |
5987615e434aefd95181eae099c4f019e021b024eb6Steven Toth		0;
5997615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	cap->capabilities |= V4L2_CAP_TUNER;
6017615e434aefd95181eae099c4f019e021b024eb6Steven Toth	cap->version = 0;
6027615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6037615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
6047615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
6057615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6067615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
6077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_fmtdesc *f)
6087615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
6097615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (f->index != 0)
6107615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
6117615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6127615e434aefd95181eae099c4f019e021b024eb6Steven Toth	strlcpy(f->description, "MPEG", sizeof(f->description));
6137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->pixelformat = V4L2_PIX_FMT_MPEG;
6147615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6157615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
6167615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
6177615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6187615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
6197615e434aefd95181eae099c4f019e021b024eb6Steven Toth				struct v4l2_format *f)
6207615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
6217615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
6227615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
6237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
6247615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
6267615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.bytesperline = 0;
6277615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.sizeimage    =
6287615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->ts_packet_size * port->ts_packet_count;
6297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.colorspace   = 0;
6307615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.width        = port->width;
6317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.height       = port->height;
6327615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n",
6347615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->width, port->height);
6357615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6367615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
6377615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
6387615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6397615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
6407615e434aefd95181eae099c4f019e021b024eb6Steven Toth				struct v4l2_format *f)
6417615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
6427615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
6437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
6447615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
6457615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
6477615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.bytesperline = 0;
6487615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.sizeimage    =
6497615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->ts_packet_size * port->ts_packet_count;
6507615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.colorspace   = 0;
6517615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
6527615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->width, port->height);
6537615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
6547615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
6557615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6567615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
6577615e434aefd95181eae099c4f019e021b024eb6Steven Toth				struct v4l2_format *f)
6587615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
6597615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
6607615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
6617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
6627615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
6647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.bytesperline = 0;
6657615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.sizeimage    =
6667615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->ts_packet_size * port->ts_packet_count;
6677615e434aefd95181eae099c4f019e021b024eb6Steven Toth	f->fmt.pix.colorspace   = 0;
6687615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
6707615e434aefd95181eae099c4f019e021b024eb6Steven Toth		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
6717615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6727615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
6737615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
6747615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6757615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_log_status(struct file *file, void *priv)
6767615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
6777615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
6787615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
6797615e434aefd95181eae099c4f019e021b024eb6Steven Toth
6807615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int fill_queryctrl(struct saa7164_encoder_params *params,
6817615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_queryctrl *c)
6827615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
6837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	switch (c->id) {
6847615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_BRIGHTNESS:
6857615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
6867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_CONTRAST:
6877615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
6887615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_SATURATION:
6897615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
6907615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_HUE:
6917615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
6927615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_SHARPNESS:
6937615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
6947615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_AUDIO_MUTE:
6957615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
6967615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_AUDIO_VOLUME:
6977615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
6987615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE:
6997615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c,
7007615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
7017615e434aefd95181eae099c4f019e021b024eb6Steven Toth			100000, ENCODER_DEF_BITRATE);
7027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_STREAM_TYPE:
7037615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c,
7047615e434aefd95181eae099c4f019e021b024eb6Steven Toth			V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
705f91d095c92e8fdcb6bd8cb35e8fa9c87d9c10768Steven Toth			V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
706f91d095c92e8fdcb6bd8cb35e8fa9c87d9c10768Steven Toth			1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
7077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_ASPECT:
7087615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c,
7097615e434aefd95181eae099c4f019e021b024eb6Steven Toth			V4L2_MPEG_VIDEO_ASPECT_1x1,
7107615e434aefd95181eae099c4f019e021b024eb6Steven Toth			V4L2_MPEG_VIDEO_ASPECT_221x100,
7117615e434aefd95181eae099c4f019e021b024eb6Steven Toth			1, V4L2_MPEG_VIDEO_ASPECT_4x3);
7127615e434aefd95181eae099c4f019e021b024eb6Steven Toth	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
7137615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
7142600d71cc535907e5d95cd31751c587afc370065Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
7152600d71cc535907e5d95cd31751c587afc370065Steven Toth		return v4l2_ctrl_query_fill(c,
7162600d71cc535907e5d95cd31751c587afc370065Steven Toth			V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
7172600d71cc535907e5d95cd31751c587afc370065Steven Toth			1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
7183ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
7193ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth		return v4l2_ctrl_query_fill(c,
7203ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth			1, 3, 1, 1);
721968b11b20143036098a7013817a15615a54383d3Steven Toth	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
722968b11b20143036098a7013817a15615a54383d3Steven Toth		return v4l2_ctrl_query_fill(c,
723968b11b20143036098a7013817a15615a54383d3Steven Toth			ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
724968b11b20143036098a7013817a15615a54383d3Steven Toth			100000, ENCODER_DEF_BITRATE);
7257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	default:
7267615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EINVAL;
7277615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
7287615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
7297615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7307615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int vidioc_queryctrl(struct file *file, void *priv,
7317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_queryctrl *c)
7327615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
7337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = priv;
7347615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
7357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int i, next;
7367615e434aefd95181eae099c4f019e021b024eb6Steven Toth	u32 id = c->id;
7377615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7387615e434aefd95181eae099c4f019e021b024eb6Steven Toth	memset(c, 0, sizeof(*c));
7397615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
7417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
7427615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
7447615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (next) {
7457615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if (c->id < saa7164_v4l2_ctrls[i])
7467615e434aefd95181eae099c4f019e021b024eb6Steven Toth				c->id = saa7164_v4l2_ctrls[i];
7477615e434aefd95181eae099c4f019e021b024eb6Steven Toth			else
7487615e434aefd95181eae099c4f019e021b024eb6Steven Toth				continue;
7497615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
7507615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7517615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (c->id == saa7164_v4l2_ctrls[i])
7527615e434aefd95181eae099c4f019e021b024eb6Steven Toth			return fill_queryctrl(&port->encoder_params, c);
7537615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7547615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (c->id < saa7164_v4l2_ctrls[i])
7557615e434aefd95181eae099c4f019e021b024eb6Steven Toth			break;
7567615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
7577615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7587615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return -EINVAL;
7597615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
7607615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7617615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_encoder_stop_port(struct saa7164_port *port)
7627615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
7637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
7647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret;
7657615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
7677615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
7687615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
7697615e434aefd95181eae099c4f019e021b024eb6Steven Toth			__func__, ret);
7707615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EIO;
7717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	} else {
7727615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC, "%s()    Stopped\n", __func__);
7737615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = 0;
7747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
7757615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
7777615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
7787615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7797615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_encoder_acquire_port(struct saa7164_port *port)
7807615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
7817615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
7827615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret;
7837615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7847615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
7857615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
7867615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
7877615e434aefd95181eae099c4f019e021b024eb6Steven Toth			__func__, ret);
7887615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EIO;
7897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	} else {
7907615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
7917615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = 0;
7927615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
7937615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7947615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
7957615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
7967615e434aefd95181eae099c4f019e021b024eb6Steven Toth
7977615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_encoder_pause_port(struct saa7164_port *port)
7987615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
7997615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
8007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret;
8017615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
8037615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
8047615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
8057615e434aefd95181eae099c4f019e021b024eb6Steven Toth			__func__, ret);
8067615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EIO;
8077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	} else {
8087615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC, "%s()   Paused\n", __func__);
8097615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = 0;
8107615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
8117615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8127615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
8137615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
8147615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8157615e434aefd95181eae099c4f019e021b024eb6Steven Toth/* Firmware is very windows centric, meaning you have to transition
8167615e434aefd95181eae099c4f019e021b024eb6Steven Toth * the part through AVStream / KS Windows stages, forwards or backwards.
8177615e434aefd95181eae099c4f019e021b024eb6Steven Toth * States are: stopped, acquired (h/w), paused, started.
8187615e434aefd95181eae099c4f019e021b024eb6Steven Toth * We have to leave here will all of the soft buffers on the free list,
8197615e434aefd95181eae099c4f019e021b024eb6Steven Toth * else the cfg_post() func won't have soft buffers to correctly configure.
8207615e434aefd95181eae099c4f019e021b024eb6Steven Toth */
8217615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_encoder_stop_streaming(struct saa7164_port *port)
8227615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
8237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
8247615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_buffer *buf;
8257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_user_buffer *ubuf;
8267615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct list_head *c, *n;
8277615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int ret;
8287615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
8307615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ret = saa7164_encoder_pause_port(port);
8327615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ret = saa7164_encoder_acquire_port(port);
8337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ret = saa7164_encoder_stop_port(port);
8347615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__,
8367615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->nr);
8377615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8387615e434aefd95181eae099c4f019e021b024eb6Steven Toth	mutex_lock(&port->dmaqueue_lock);
8397615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Reset the hard and soft buffer state */
8417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	list_for_each_safe(c, n, &port->dmaqueue.list) {
8427615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buf = list_entry(c, struct saa7164_buffer, list);
8437615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buf->flags = SAA7164_BUFFER_FREE;
8447615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buf->pos = 0;
8457615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
8467615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8477615e434aefd95181eae099c4f019e021b024eb6Steven Toth	list_for_each_safe(c, n, &port->list_buf_used.list) {
8487615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ubuf = list_entry(c, struct saa7164_user_buffer, list);
8497615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ubuf->pos = 0;
8507615e434aefd95181eae099c4f019e021b024eb6Steven Toth		list_move_tail(&ubuf->list, &port->list_buf_free.list);
8517615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
8527615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8537615e434aefd95181eae099c4f019e021b024eb6Steven Toth	mutex_unlock(&port->dmaqueue_lock);
8547615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr);
8557615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8567615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
8577615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
8587615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8597615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int saa7164_encoder_start_streaming(struct saa7164_port *port)
8607615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
8617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
8627615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int result, ret = 0;
8637615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
8657615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Configure the encoder with any cache values */
8677615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_encoder(port);
8687615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_buffer_cfg_port(port);
8707615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Acquire the hardware */
8727615e434aefd95181eae099c4f019e021b024eb6Steven Toth	result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
8737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
8747615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
8757615e434aefd95181eae099c4f019e021b024eb6Steven Toth			__func__, result);
8767615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8777615e434aefd95181eae099c4f019e021b024eb6Steven Toth		/* Stop the hardware, regardless */
8787615e434aefd95181eae099c4f019e021b024eb6Steven Toth		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
8797615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
8807615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() acquire/forced stop transition "
8817615e434aefd95181eae099c4f019e021b024eb6Steven Toth				"failed, res = 0x%x\n", __func__, result);
8827615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
8837615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EIO;
8847615e434aefd95181eae099c4f019e021b024eb6Steven Toth		goto out;
8857615e434aefd95181eae099c4f019e021b024eb6Steven Toth	} else
8867615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC, "%s()   Acquired\n", __func__);
8877615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8887615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Pause the hardware */
8897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
8907615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
8917615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
8927615e434aefd95181eae099c4f019e021b024eb6Steven Toth				__func__, result);
8937615e434aefd95181eae099c4f019e021b024eb6Steven Toth
8947615e434aefd95181eae099c4f019e021b024eb6Steven Toth		/* Stop the hardware, regardless */
8957615e434aefd95181eae099c4f019e021b024eb6Steven Toth		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
8967615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
8977615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() pause/forced stop transition "
8987615e434aefd95181eae099c4f019e021b024eb6Steven Toth				"failed, res = 0x%x\n", __func__, result);
8997615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
9007615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9017615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EIO;
9027615e434aefd95181eae099c4f019e021b024eb6Steven Toth		goto out;
9037615e434aefd95181eae099c4f019e021b024eb6Steven Toth	} else
9047615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC, "%s()   Paused\n", __func__);
9057615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9067615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Start the hardware */
9077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
9087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
9097615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
9107615e434aefd95181eae099c4f019e021b024eb6Steven Toth				__func__, result);
9117615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9127615e434aefd95181eae099c4f019e021b024eb6Steven Toth		/* Stop the hardware, regardless */
9137615e434aefd95181eae099c4f019e021b024eb6Steven Toth		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
9147615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
9157615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() run/forced stop transition "
9167615e434aefd95181eae099c4f019e021b024eb6Steven Toth				"failed, res = 0x%x\n", __func__, result);
9177615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
9187615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9197615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EIO;
9207615e434aefd95181eae099c4f019e021b024eb6Steven Toth	} else
9217615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC, "%s()   Running\n", __func__);
9227615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9237615e434aefd95181eae099c4f019e021b024eb6Steven Tothout:
9247615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
9257615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
9267615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9277615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int fops_open(struct file *file)
9287615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
9297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *h, *dev = NULL;
9307615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = NULL;
9317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *portc = NULL;
9327615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *portd = NULL;
9337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh;
9347615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct list_head *list;
9357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int minor = video_devdata(file)->minor;
9367615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9377615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
9387615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9397615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* TODO: Really, the BKL? - remove this */
9407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	lock_kernel();
9417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	list_for_each(list, &saa7164_devlist) {
9427615e434aefd95181eae099c4f019e021b024eb6Steven Toth		h = list_entry(list, struct saa7164_dev, devlist);
9437615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9447615e434aefd95181eae099c4f019e021b024eb6Steven Toth		portc = &h->ports[ SAA7164_PORT_ENC1 ];
9457615e434aefd95181eae099c4f019e021b024eb6Steven Toth		portd = &h->ports[ SAA7164_PORT_ENC2 ];
9467615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9477615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (portc->v4l_device &&
9487615e434aefd95181eae099c4f019e021b024eb6Steven Toth		    portc->v4l_device->minor == minor) {
9497615e434aefd95181eae099c4f019e021b024eb6Steven Toth			dev = h;
9507615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port = portc;
9517615e434aefd95181eae099c4f019e021b024eb6Steven Toth			break;
9527615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
9537615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9547615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (portd->v4l_device &&
9557615e434aefd95181eae099c4f019e021b024eb6Steven Toth		    portd->v4l_device->minor == minor) {
9567615e434aefd95181eae099c4f019e021b024eb6Steven Toth			dev = h;
9577615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port = portd;
9587615e434aefd95181eae099c4f019e021b024eb6Steven Toth			break;
9597615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
9607615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
9627615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port == NULL) {
9647615e434aefd95181eae099c4f019e021b024eb6Steven Toth		unlock_kernel();
9657615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -ENODEV;
9667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
9677615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9687615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* allocate + initialize per filehandle data */
9697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
9707615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (NULL == fh) {
9717615e434aefd95181eae099c4f019e021b024eb6Steven Toth		unlock_kernel();
9727615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -ENOMEM;
9737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
9747615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9757615e434aefd95181eae099c4f019e021b024eb6Steven Toth	file->private_data = fh;
9767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	fh->port = port;
9777615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9787615e434aefd95181eae099c4f019e021b024eb6Steven Toth	unlock_kernel();
9797615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
9817615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
9827615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9837615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic int fops_release(struct file *file)
9847615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
9857615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
9867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
9877615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
9887615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
9907615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9917615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Shut device down on last close */
9927615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
9937615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (atomic_dec_return(&port->v4l_reader_count) == 0) {
9947615e434aefd95181eae099c4f019e021b024eb6Steven Toth			/* stop mpeg capture then cancel buffers */
9957615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_encoder_stop_streaming(port);
9967615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
9977615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
9987615e434aefd95181eae099c4f019e021b024eb6Steven Toth
9997615e434aefd95181eae099c4f019e021b024eb6Steven Toth	file->private_data = NULL;
10007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	kfree(fh);
10017615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
10037615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
10047615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10057615e434aefd95181eae099c4f019e021b024eb6Steven Tothstruct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
10067615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
10077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_user_buffer *buf = 0;
10087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
10097615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10107615e434aefd95181eae099c4f019e021b024eb6Steven Toth	mutex_lock(&port->dmaqueue_lock);
10117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (!list_empty(&port->list_buf_used.list)) {
10127615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buf = list_first_entry(&port->list_buf_used.list,
10137615e434aefd95181eae099c4f019e021b024eb6Steven Toth			struct saa7164_user_buffer, list);
10147615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
10157615e434aefd95181eae099c4f019e021b024eb6Steven Toth	mutex_unlock(&port->dmaqueue_lock);
10167615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10177615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, buf);
10187615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10197615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return buf;
10207615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
10217615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10227615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic ssize_t fops_read(struct file *file, char __user *buffer,
10237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	size_t count, loff_t *pos)
10247615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
10257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = file->private_data;
10267615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
10277615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_user_buffer *ubuf = NULL;
10287615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
10297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	unsigned int ret = 0;
10307615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int rem, cnt;
10317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	u8 *p;
10327615e434aefd95181eae099c4f019e021b024eb6Steven Toth
103358acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	port->last_read_msecs_diff = port->last_read_msecs;
103458acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	port->last_read_msecs = jiffies_to_msecs(jiffies);
103558acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	port->last_read_msecs_diff = port->last_read_msecs -
103658acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth		port->last_read_msecs_diff;
103758acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth
103858acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	saa7164_histogram_update(&port->read_interval,
103958acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth		port->last_read_msecs_diff);
104058acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth
104146eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth	if (*pos) {
104246eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth		printk(KERN_ERR "%s() ESPIPE\n", __func__);
10437615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -ESPIPE;
104446eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth	}
10457615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
10477615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (atomic_inc_return(&port->v4l_reader_count) == 1) {
10487615e434aefd95181eae099c4f019e021b024eb6Steven Toth
104946eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth			if (saa7164_encoder_initialize(port) < 0) {
105046eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth				printk(KERN_ERR "%s() EINVAL\n", __func__);
10517615e434aefd95181eae099c4f019e021b024eb6Steven Toth				return -EINVAL;
105246eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth			}
10537615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10547615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_encoder_start_streaming(port);
10557615e434aefd95181eae099c4f019e021b024eb6Steven Toth			msleep(200);
10567615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
10577615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
10587615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10597615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* blocking wait for buffer */
10607615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((file->f_flags & O_NONBLOCK) == 0) {
10617615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (wait_event_interruptible(port->wait_read,
10627615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_enc_next_buf(port))) {
106346eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth				printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
10647615e434aefd95181eae099c4f019e021b024eb6Steven Toth				return -ERESTARTSYS;
10657615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
10667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
10677615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10687615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Pull the first buffer from the used list */
10697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ubuf = saa7164_enc_next_buf(port);
10707615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	while ((count > 0) && ubuf) {
10727615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10737615e434aefd95181eae099c4f019e021b024eb6Steven Toth		/* set remaining bytes to copy */
10747615e434aefd95181eae099c4f019e021b024eb6Steven Toth		rem = ubuf->actual_size - ubuf->pos;
10757615e434aefd95181eae099c4f019e021b024eb6Steven Toth		cnt = rem > count ? count : rem;
10767615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10777615e434aefd95181eae099c4f019e021b024eb6Steven Toth		p = ubuf->data + ubuf->pos;
10787615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10797615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dprintk(DBGLVL_ENC,
10807615e434aefd95181eae099c4f019e021b024eb6Steven Toth			"%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
10817615e434aefd95181eae099c4f019e021b024eb6Steven Toth			__func__, (int)count, cnt, rem, ubuf, ubuf->pos);
10827615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10837615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (copy_to_user(buffer, p, cnt)) {
10847615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
108546eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth			if (!ret) {
108646eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth				printk(KERN_ERR "%s() EFAULT\n", __func__);
10877615e434aefd95181eae099c4f019e021b024eb6Steven Toth				ret = -EFAULT;
108846eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth			}
10897615e434aefd95181eae099c4f019e021b024eb6Steven Toth			goto err;
10907615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
10917615e434aefd95181eae099c4f019e021b024eb6Steven Toth
10927615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ubuf->pos += cnt;
10937615e434aefd95181eae099c4f019e021b024eb6Steven Toth		count -= cnt;
10947615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buffer += cnt;
10957615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret += cnt;
10967615e434aefd95181eae099c4f019e021b024eb6Steven Toth
109746eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth		if (ubuf->pos > ubuf->actual_size) {
109846eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth			printk(KERN_ERR "read() pos > actual, huh?\n");
109946eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth		}
110046eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth
11017615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (ubuf->pos == ubuf->actual_size) {
11027615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11037615e434aefd95181eae099c4f019e021b024eb6Steven Toth			/* finished with current buffer, take next buffer */
11047615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11057615e434aefd95181eae099c4f019e021b024eb6Steven Toth			/* Requeue the buffer on the free list */
11067615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ubuf->pos = 0;
11077615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11087615e434aefd95181eae099c4f019e021b024eb6Steven Toth			mutex_lock(&port->dmaqueue_lock);
11097615e434aefd95181eae099c4f019e021b024eb6Steven Toth			list_move_tail(&ubuf->list, &port->list_buf_free.list);
11107615e434aefd95181eae099c4f019e021b024eb6Steven Toth			mutex_unlock(&port->dmaqueue_lock);
11117615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11127615e434aefd95181eae099c4f019e021b024eb6Steven Toth			/* Dequeue next */
11137615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if ((file->f_flags & O_NONBLOCK) == 0) {
11147615e434aefd95181eae099c4f019e021b024eb6Steven Toth				if (wait_event_interruptible(port->wait_read,
11157615e434aefd95181eae099c4f019e021b024eb6Steven Toth					saa7164_enc_next_buf(port))) {
11167615e434aefd95181eae099c4f019e021b024eb6Steven Toth						break;
11177615e434aefd95181eae099c4f019e021b024eb6Steven Toth				}
11187615e434aefd95181eae099c4f019e021b024eb6Steven Toth			}
11197615e434aefd95181eae099c4f019e021b024eb6Steven Toth			ubuf = saa7164_enc_next_buf(port);
11207615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
11217615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
11227615e434aefd95181eae099c4f019e021b024eb6Steven Totherr:
112346eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth	if (!ret && !ubuf) {
112446eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth		printk(KERN_ERR "%s() EAGAIN\n", __func__);
11257615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ret = -EAGAIN;
112646eeb8dd30d3651e6ea55c2e60594206cd591d79Steven Toth	}
11277615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11287615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return ret;
11297615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
11307615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11317615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic unsigned int fops_poll(struct file *file, poll_table *wait)
11327615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
11337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_fh *fh = (struct saa7164_fh *)file->private_data;
11347615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = fh->port;
11357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_user_buffer *ubuf;
11367615e434aefd95181eae099c4f019e021b024eb6Steven Toth	unsigned int mask = 0;
11377615e434aefd95181eae099c4f019e021b024eb6Steven Toth
113858acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	port->last_poll_msecs_diff = port->last_poll_msecs;
113958acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	port->last_poll_msecs = jiffies_to_msecs(jiffies);
114058acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	port->last_poll_msecs_diff = port->last_poll_msecs -
114158acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth		port->last_poll_msecs_diff;
114258acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth
114358acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth	saa7164_histogram_update(&port->poll_interval,
114458acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth		port->last_poll_msecs_diff);
114558acca1056434dbbbcb3f1aacd759f1039a3169dSteven Toth
11467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (!video_is_registered(port->v4l_device)) {
11477615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EIO;
11487615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
11497615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11507615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
11517615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (atomic_inc_return(&port->v4l_reader_count) == 1) {
11527615e434aefd95181eae099c4f019e021b024eb6Steven Toth			if (saa7164_encoder_initialize(port) < 0)
11537615e434aefd95181eae099c4f019e021b024eb6Steven Toth				return -EINVAL;
11547615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_encoder_start_streaming(port);
11557615e434aefd95181eae099c4f019e021b024eb6Steven Toth			msleep(200);
11567615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
11577615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
11587615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11597615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* blocking wait for buffer */
11607615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if ((file->f_flags & O_NONBLOCK) == 0) {
11617615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (wait_event_interruptible(port->wait_read,
11627615e434aefd95181eae099c4f019e021b024eb6Steven Toth			saa7164_enc_next_buf(port))) {
11637615e434aefd95181eae099c4f019e021b024eb6Steven Toth				return -ERESTARTSYS;
11647615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
11657615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
11667615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11677615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Pull the first buffer from the used list */
11687615e434aefd95181eae099c4f019e021b024eb6Steven Toth	ubuf = list_first_entry(&port->list_buf_used.list,
11697615e434aefd95181eae099c4f019e021b024eb6Steven Toth		struct saa7164_user_buffer, list);
11707615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (ubuf)
11727615e434aefd95181eae099c4f019e021b024eb6Steven Toth		mask |= POLLIN | POLLRDNORM;
11737615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return mask;
11757615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
11767615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11777615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic const struct v4l2_file_operations mpeg_fops = {
11787615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.owner		= THIS_MODULE,
11797615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.open		= fops_open,
11807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.release	= fops_release,
11817615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.read		= fops_read,
11827615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.poll		= fops_poll,
11837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.unlocked_ioctl	= video_ioctl2,
11847615e434aefd95181eae099c4f019e021b024eb6Steven Toth};
11857615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11867615e434aefd95181eae099c4f019e021b024eb6Steven Tothint saa7164_g_chip_ident(struct file *file, void *fh,
11877615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_dbg_chip_ident *chip)
11887615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
11897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = ((struct saa7164_fh *)fh)->port;
11907615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
11917615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
11927615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11937615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
11947615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
11957615e434aefd95181eae099c4f019e021b024eb6Steven Toth
11967615e434aefd95181eae099c4f019e021b024eb6Steven Tothint saa7164_g_register(struct file *file, void *fh,
11977615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_dbg_register *reg)
11987615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
11997615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = ((struct saa7164_fh *)fh)->port;
12007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
12017615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
12027615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12037615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (!capable(CAP_SYS_ADMIN))
12047615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EPERM;
12057615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12067615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
12077615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
12087615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12097615e434aefd95181eae099c4f019e021b024eb6Steven Tothint saa7164_s_register(struct file *file, void *fh,
12107615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct v4l2_dbg_register *reg)
12117615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
12127615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port = ((struct saa7164_fh *)fh)->port;
12137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
12147615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
12157615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12167615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (!capable(CAP_SYS_ADMIN))
12177615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return -EPERM;
12187615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12197615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return 0;
12207615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
12217615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12227615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
12237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_std		 = vidioc_s_std,
12247615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_enum_input	 = vidioc_enum_input,
12257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_input		 = vidioc_g_input,
12267615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_input		 = vidioc_s_input,
12277615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_tuner		 = vidioc_g_tuner,
12287615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_tuner		 = vidioc_s_tuner,
12297615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_frequency	 = vidioc_g_frequency,
12307615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_frequency	 = vidioc_s_frequency,
12317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_ctrl		 = vidioc_s_ctrl,
12327615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_ctrl		 = vidioc_g_ctrl,
12337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_querycap	 = vidioc_querycap,
12347615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
12357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_fmt_vid_cap	 = vidioc_g_fmt_vid_cap,
12367615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_try_fmt_vid_cap	 = vidioc_try_fmt_vid_cap,
12377615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_fmt_vid_cap	 = vidioc_s_fmt_vid_cap,
12387615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_ext_ctrls	 = vidioc_g_ext_ctrls,
12397615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_ext_ctrls	 = vidioc_s_ext_ctrls,
12407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_try_ext_ctrls	 = vidioc_try_ext_ctrls,
12417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_log_status	 = vidioc_log_status,
12427615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_queryctrl	 = vidioc_queryctrl,
12437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_chip_ident	 = saa7164_g_chip_ident,
12447615e434aefd95181eae099c4f019e021b024eb6Steven Toth#ifdef CONFIG_VIDEO_ADV_DEBUG
12457615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_g_register	 = saa7164_g_register,
12467615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.vidioc_s_register	 = saa7164_s_register,
12477615e434aefd95181eae099c4f019e021b024eb6Steven Toth#endif
12487615e434aefd95181eae099c4f019e021b024eb6Steven Toth};
12497615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12507615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic struct video_device saa7164_mpeg_template = {
12517615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.name          = "saa7164",
12527615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.fops          = &mpeg_fops,
12537615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.ioctl_ops     = &mpeg_ioctl_ops,
12547615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.minor         = -1,
12557615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.tvnorms       = SAA7164_NORMS,
12567615e434aefd95181eae099c4f019e021b024eb6Steven Toth	.current_norm  = V4L2_STD_NTSC_M,
12577615e434aefd95181eae099c4f019e021b024eb6Steven Toth};
12587615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12597615e434aefd95181eae099c4f019e021b024eb6Steven Tothstatic struct video_device *saa7164_encoder_alloc(
12607615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_port *port,
12617615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct pci_dev *pci,
12627615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct video_device *template,
12637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	char *type)
12647615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
12657615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct video_device *vfd;
12667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
12677615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12687615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
12697615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12707615e434aefd95181eae099c4f019e021b024eb6Steven Toth	vfd = video_device_alloc();
12717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (NULL == vfd)
12727615e434aefd95181eae099c4f019e021b024eb6Steven Toth		return NULL;
12737615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	*vfd = *template;
12757615e434aefd95181eae099c4f019e021b024eb6Steven Toth	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
12767615e434aefd95181eae099c4f019e021b024eb6Steven Toth		type, saa7164_boards[dev->board].name);
12777615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12787615e434aefd95181eae099c4f019e021b024eb6Steven Toth	vfd->parent  = &pci->dev;
12797615e434aefd95181eae099c4f019e021b024eb6Steven Toth	vfd->release = video_device_release;
12807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return vfd;
12817615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
12827615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12837615e434aefd95181eae099c4f019e021b024eb6Steven Tothint saa7164_encoder_register(struct saa7164_port *port)
12847615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
12857615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
12867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_buffer *buf;
12877615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_user_buffer *ubuf;
12887615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int result = -ENODEV, i;
12897615e434aefd95181eae099c4f019e021b024eb6Steven Toth	int len = 0;
12907615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12917615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s()\n", __func__);
12927615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12937615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->type != SAA7164_MPEG_ENCODER)
12947615e434aefd95181eae099c4f019e021b024eb6Steven Toth		BUG();
12957615e434aefd95181eae099c4f019e021b024eb6Steven Toth
12967615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Sanity check that the PCI configuration space is active */
12977615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->hwcfg.BARLocation == 0) {
12987615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_ERR "%s() failed "
12997615e434aefd95181eae099c4f019e021b024eb6Steven Toth		       "(errno = %d), NO PCI configuration\n",
13007615e434aefd95181eae099c4f019e021b024eb6Steven Toth			__func__, result);
13017615e434aefd95181eae099c4f019e021b024eb6Steven Toth		result = -ENOMEM;
13027615e434aefd95181eae099c4f019e021b024eb6Steven Toth		goto failed;
13037615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
13047615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13057615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Init and establish defaults */
13067615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* TODO: Check the umber of lines for PS */
13077615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.bitspersample = 8;
13087615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.samplesperline = 188;
13097615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.numberoflines =
13107615e434aefd95181eae099c4f019e021b024eb6Steven Toth		(SAA7164_TS_NUMBER_OF_LINES * 188) / 188;
13117615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13127615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.pitch = 188;
13137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.linethreshold = 0;
13147615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.pagetablelistvirt = 0;
13157615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.pagetablelistphys = 0;
13167615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.numpagetables = 2 +
13177615e434aefd95181eae099c4f019e021b024eb6Steven Toth		((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
13187615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13197615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount;
13207615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13217615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Allocate the PCI resources, buffers (hard) */
13227615e434aefd95181eae099c4f019e021b024eb6Steven Toth	for (i = 0; i < port->hwcfg.buffercount; i++) {
13237615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buf = saa7164_buffer_alloc(port,
13247615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->hw_streamingparams.numberoflines *
13257615e434aefd95181eae099c4f019e021b024eb6Steven Toth			port->hw_streamingparams.pitch);
13267615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13277615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (!buf) {
13287615e434aefd95181eae099c4f019e021b024eb6Steven Toth			printk(KERN_ERR "%s() failed "
13297615e434aefd95181eae099c4f019e021b024eb6Steven Toth			       "(errno = %d), unable to allocate buffer\n",
13307615e434aefd95181eae099c4f019e021b024eb6Steven Toth				__func__, result);
13317615e434aefd95181eae099c4f019e021b024eb6Steven Toth			result = -ENOMEM;
13327615e434aefd95181eae099c4f019e021b024eb6Steven Toth			goto failed;
13337615e434aefd95181eae099c4f019e021b024eb6Steven Toth		} else {
13347615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13357615e434aefd95181eae099c4f019e021b024eb6Steven Toth			mutex_lock(&port->dmaqueue_lock);
13367615e434aefd95181eae099c4f019e021b024eb6Steven Toth			list_add_tail(&buf->list, &port->dmaqueue.list);
13377615e434aefd95181eae099c4f019e021b024eb6Steven Toth			mutex_unlock(&port->dmaqueue_lock);
13387615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13397615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
13407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
13417615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13427615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Allocate some kenrel kernel buffers for copying
13437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	 * to userpsace.
13447615e434aefd95181eae099c4f019e021b024eb6Steven Toth	 */
13457615e434aefd95181eae099c4f019e021b024eb6Steven Toth	len = port->hw_streamingparams.numberoflines *
13467615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->hw_streamingparams.pitch;
13477615e434aefd95181eae099c4f019e021b024eb6Steven Toth
134866e1d37884eb43214292ed433fcffb72692c4838Steven Toth	if (encoder_buffers < 16)
134966e1d37884eb43214292ed433fcffb72692c4838Steven Toth		encoder_buffers = 16;
135066e1d37884eb43214292ed433fcffb72692c4838Steven Toth	if (encoder_buffers > 512)
135166e1d37884eb43214292ed433fcffb72692c4838Steven Toth		encoder_buffers = 512;
135266e1d37884eb43214292ed433fcffb72692c4838Steven Toth
135366e1d37884eb43214292ed433fcffb72692c4838Steven Toth	for (i = 0; i < encoder_buffers; i++) {
13547615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13557615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ubuf = saa7164_buffer_alloc_user(dev, len);
13567615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (ubuf) {
13577615e434aefd95181eae099c4f019e021b024eb6Steven Toth			mutex_lock(&port->dmaqueue_lock);
13587615e434aefd95181eae099c4f019e021b024eb6Steven Toth			list_add_tail(&ubuf->list, &port->list_buf_free.list);
13597615e434aefd95181eae099c4f019e021b024eb6Steven Toth			mutex_unlock(&port->dmaqueue_lock);
13607615e434aefd95181eae099c4f019e021b024eb6Steven Toth		}
13617615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13627615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
13637615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13647615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Establish encoder defaults here */
13657615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Set default TV standard */
13667615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encodernorm = saa7164_tvnorms[0];
13677615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->width = 720;
13687615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->mux_input = 1; /* Composite */
13697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->video_format = EU_VIDEO_FORMAT_MPEG_2;
13707615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->audio_format = 0;
13717615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->video_resolution = 0;
13727615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->ctl_brightness = 127;
13737615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->ctl_contrast = 66;
13747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->ctl_hue = 128;
13757615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->ctl_saturation = 62;
13767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->ctl_sharpness = 8;
13777615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.bitrate = ENCODER_DEF_BITRATE;
1378968b11b20143036098a7013817a15615a54383d3Steven Toth	port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE;
13795fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth	port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
13807615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
13817615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.ctl_mute = 0;
13827615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
13833ed43cf96aa9fc565d74855649d8cee0def67f38Steven Toth	port->encoder_params.refdist = 1;
13845fa56ccdacc54f5f694141c1a74f781cf77874bbSteven Toth	port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE;
13857615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13867615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->encodernorm.id & V4L2_STD_525_60)
13877615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->height = 480;
13887615e434aefd95181eae099c4f019e021b024eb6Steven Toth	else
13897615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->height = 576;
13907615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13917615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Allocate and register the video device node */
13927615e434aefd95181eae099c4f019e021b024eb6Steven Toth	port->v4l_device = saa7164_encoder_alloc(port,
13937615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dev->pci, &saa7164_mpeg_template, "mpeg");
13947615e434aefd95181eae099c4f019e021b024eb6Steven Toth
13957615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->v4l_device == NULL) {
13967615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_INFO "%s: can't allocate mpeg device\n",
13977615e434aefd95181eae099c4f019e021b024eb6Steven Toth			dev->name);
13987615e434aefd95181eae099c4f019e021b024eb6Steven Toth		result = -ENOMEM;
13997615e434aefd95181eae099c4f019e021b024eb6Steven Toth		goto failed;
14007615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
14017615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14027615e434aefd95181eae099c4f019e021b024eb6Steven Toth	result = video_register_device(port->v4l_device,
14037615e434aefd95181eae099c4f019e021b024eb6Steven Toth		VFL_TYPE_GRABBER, -1);
14047615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (result < 0) {
14057615e434aefd95181eae099c4f019e021b024eb6Steven Toth		printk(KERN_INFO "%s: can't register mpeg device\n",
14067615e434aefd95181eae099c4f019e021b024eb6Steven Toth			dev->name);
14077615e434aefd95181eae099c4f019e021b024eb6Steven Toth		/* TODO: We're going to leak here if we don't dealloc
14087615e434aefd95181eae099c4f019e021b024eb6Steven Toth		 The buffers above. The unreg function can't deal wit it.
14097615e434aefd95181eae099c4f019e021b024eb6Steven Toth		*/
14107615e434aefd95181eae099c4f019e021b024eb6Steven Toth		goto failed;
14117615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
14127615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14137615e434aefd95181eae099c4f019e021b024eb6Steven Toth	printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
14147615e434aefd95181eae099c4f019e021b024eb6Steven Toth		dev->name, port->v4l_device->num);
14157615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14167615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Configure the hardware defaults */
14177615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_videomux(port);
14187615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
14197615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
14207615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
14217615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
14227615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
14237615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_audio_mute(port, 0);
14247615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_audio_volume(port, 20);
14257615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_aspect_ratio(port);
14267615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14277615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Disable audio standard detection, it's buggy */
14287615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_audio_detection(port, 0);
14297615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14307615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_set_encoder(port);
14317615e434aefd95181eae099c4f019e021b024eb6Steven Toth	saa7164_api_get_encoder(port);
14327615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14337615e434aefd95181eae099c4f019e021b024eb6Steven Toth	result = 0;
14347615e434aefd95181eae099c4f019e021b024eb6Steven Tothfailed:
14357615e434aefd95181eae099c4f019e021b024eb6Steven Toth	return result;
14367615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
14377615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14387615e434aefd95181eae099c4f019e021b024eb6Steven Tothvoid saa7164_encoder_unregister(struct saa7164_port *port)
14397615e434aefd95181eae099c4f019e021b024eb6Steven Toth{
14407615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_dev *dev = port->dev;
14417615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_buffer *buf;
14427615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct saa7164_user_buffer *ubuf;
14437615e434aefd95181eae099c4f019e021b024eb6Steven Toth	struct list_head *c, *n, *p, *q, *l, *v;
14447615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14457615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
14467615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14477615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->type != SAA7164_MPEG_ENCODER)
14487615e434aefd95181eae099c4f019e021b024eb6Steven Toth		BUG();
14497615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14507615e434aefd95181eae099c4f019e021b024eb6Steven Toth	if (port->v4l_device) {
14517615e434aefd95181eae099c4f019e021b024eb6Steven Toth		if (port->v4l_device->minor != -1)
14527615e434aefd95181eae099c4f019e021b024eb6Steven Toth			video_unregister_device(port->v4l_device);
14537615e434aefd95181eae099c4f019e021b024eb6Steven Toth		else
14547615e434aefd95181eae099c4f019e021b024eb6Steven Toth			video_device_release(port->v4l_device);
14557615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14567615e434aefd95181eae099c4f019e021b024eb6Steven Toth		port->v4l_device = NULL;
14577615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
14587615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14597615e434aefd95181eae099c4f019e021b024eb6Steven Toth	/* Remove any allocated buffers */
14607615e434aefd95181eae099c4f019e021b024eb6Steven Toth	mutex_lock(&port->dmaqueue_lock);
14617615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14627615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr);
14637615e434aefd95181eae099c4f019e021b024eb6Steven Toth	list_for_each_safe(c, n, &port->dmaqueue.list) {
14647615e434aefd95181eae099c4f019e021b024eb6Steven Toth		buf = list_entry(c, struct saa7164_buffer, list);
14657615e434aefd95181eae099c4f019e021b024eb6Steven Toth		list_del(c);
14667615e434aefd95181eae099c4f019e021b024eb6Steven Toth		saa7164_buffer_dealloc(buf);
14677615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
14687615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14697615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr);
14707615e434aefd95181eae099c4f019e021b024eb6Steven Toth	list_for_each_safe(p, q, &port->list_buf_used.list) {
14717615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ubuf = list_entry(p, struct saa7164_user_buffer, list);
14727615e434aefd95181eae099c4f019e021b024eb6Steven Toth		list_del(p);
14737615e434aefd95181eae099c4f019e021b024eb6Steven Toth		saa7164_buffer_dealloc_user(ubuf);
14747615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
14757615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14767615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr);
14777615e434aefd95181eae099c4f019e021b024eb6Steven Toth	list_for_each_safe(l, v, &port->list_buf_free.list) {
14787615e434aefd95181eae099c4f019e021b024eb6Steven Toth		ubuf = list_entry(l, struct saa7164_user_buffer, list);
14797615e434aefd95181eae099c4f019e021b024eb6Steven Toth		list_del(l);
14807615e434aefd95181eae099c4f019e021b024eb6Steven Toth		saa7164_buffer_dealloc_user(ubuf);
14817615e434aefd95181eae099c4f019e021b024eb6Steven Toth	}
14827615e434aefd95181eae099c4f019e021b024eb6Steven Toth
14837615e434aefd95181eae099c4f019e021b024eb6Steven Toth	mutex_unlock(&port->dmaqueue_lock);
14847615e434aefd95181eae099c4f019e021b024eb6Steven Toth	dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
14857615e434aefd95181eae099c4f019e021b024eb6Steven Toth}
14867615e434aefd95181eae099c4f019e021b024eb6Steven Toth
1487