[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    mxb - v4l2 driver for the Multimedia eXtension Board
3a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
46acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold    Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6631dd1a885b6d7e9f6f51b4e5b311c2bb04c323cJustin P. Mattock    Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    for further details about this card.
8a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is free software; you can redistribute it and/or modify
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    it under the terms of the GNU General Public License as published by
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    the Free Software Foundation; either version 2 of the License, or
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    (at your option) any later version.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    This program is distributed in the hope that it will be useful,
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    but WITHOUT ANY WARRANTY; without even the implied warranty of
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    GNU General Public License for more details.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    You should have received a copy of the GNU General Public License
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    along with this program; if not, write to the Free Software
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_VARIABLE debug
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <media/saa7146_vv.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <media/tuner.h>
305e453dc757385ec892a818e4e3b5de027987ced9Michael Krufky#include <media/v4l2-common.h>
31707ecf4603a9439dcf409e13c5e9ed4e164ddfffHans Verkuil#include <media/saa7115.h>
327a707b89202f905bd9f9fbde326933c59a81214cPaul Gortmaker#include <linux/module.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tea6415c.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tea6420.h"
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
376680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil#define MXB_AUDIOS	6
386680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil
391b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define I2C_SAA7111A  0x24
401b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TDA9840   0x42
411b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TEA6415C  0x43
421b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TEA6420_1 0x4c
431b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TEA6420_2 0x4d
441b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TUNER     0x60
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab#define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* global variable */
49ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int mxb_num;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab/* initial frequence the tuner will be tuned to.
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   in verden (lower saxony, germany) 4148 is a
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   channel called "phoenix" */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int freq = 4148;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(freq, int, 0644);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int debug;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0644);
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MXB_INPUTS 4
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { TUNER, AUX1, AUX3, AUX3_YC };
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct v4l2_input mxb_inputs[MXB_INPUTS] = {
664894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	{ TUNER,   "Tuner",          V4L2_INPUT_TYPE_TUNER,  0x3f, 0,
676680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
684894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	{ AUX1,	   "AUX1",           V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
696680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
704894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	{ AUX3,	   "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
716680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
724894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	{ AUX3_YC, "AUX3 S-Video",   V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
736680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this array holds the information, which port of the saa7146 each
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   input actually uses. the mxb uses port 0 for every input */
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct {
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hps_source;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hps_sync;
81a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab} input_port_selection[MXB_INPUTS] = {
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this array holds the information of the audio source (mxb_audios),
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   which has to be switched corresponding to the video source (mxb_channels) */
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int video_audio_connect[MXB_INPUTS] =
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 1, 3, 3 };
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
935325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstruct mxb_routing {
945325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	u32 input;
955325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	u32 output;
965325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil};
975325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
986e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil/* these are the available audio sources, which can switched
996e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil   to the line- and cd-output individually */
1006e65ca942b9664a987866ac0c62e7e450777056bHans Verkuilstatic struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
1016e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	    {
1026e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.index	= 0,
1036e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.name	= "Tuner",
1046e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.capability = V4L2_AUDCAP_STEREO,
1056e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	} , {
1066e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.index	= 1,
1076e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.name	= "AUX1",
1086e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.capability = V4L2_AUDCAP_STEREO,
1096e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	} , {
1106e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.index	= 2,
1116e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.name	= "AUX2",
1126e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.capability = V4L2_AUDCAP_STEREO,
1136e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	} , {
1146e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.index	= 3,
1156e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.name	= "AUX3",
1166e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.capability = V4L2_AUDCAP_STEREO,
1176e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	} , {
1186e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.index	= 4,
1196e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.name	= "Radio (X9)",
1206e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.capability = V4L2_AUDCAP_STEREO,
1216e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	} , {
1226e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.index	= 5,
1236e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.name	= "CD-ROM (X10)",
1246e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		.capability = V4L2_AUDCAP_STEREO,
1256e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	}
1266e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil};
1276e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
1281b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil/* These are the necessary input-output-pins for bringing one audio source
1291b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil   (see above) to the CD-output. Note that gain is set to 0 in this table. */
1305325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
1311b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 1, 1 }, { 1, 1 } },	/* Tuner */
1321b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 5, 1 }, { 6, 1 } },	/* AUX 1 */
1331b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 4, 1 }, { 6, 1 } },	/* AUX 2 */
1341b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 3, 1 }, { 6, 1 } },	/* AUX 3 */
1351b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 1, 1 }, { 3, 1 } },	/* Radio */
1361b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 1, 1 }, { 2, 1 } },	/* CD-Rom */
1371b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 6, 1 }, { 6, 1 } }	/* Mute */
1381b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil};
1391b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil
1401b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil/* These are the necessary input-output-pins for bringing one audio source
1411b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil   (see above) to the line-output. Note that gain is set to 0 in this table. */
1425325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
1431b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 2, 3 }, { 1, 2 } },
1441b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 5, 3 }, { 6, 2 } },
1451b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 4, 3 }, { 6, 2 } },
1461b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 3, 3 }, { 6, 2 } },
1471b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 2, 3 }, { 3, 2 } },
1481b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 2, 3 }, { 2, 2 } },
1491b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 6, 3 }, { 6, 2 } }	/* Mute */
1501b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil};
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mxb
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct video_device	*video_dev;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct video_device	*vbi_dev;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
157a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	struct i2c_adapter	i2c_adapter;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*saa7111a;
1601b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tda9840;
1611b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tea6415c;
1621b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tuner;
1631b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tea6420_1;
1641b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tea6420_2;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	cur_mode;	/* current audio mode (mono, stereo, ...) */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	cur_input;	/* current input */
1686680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	int	cur_audinput;	/* current audio input */
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	cur_mute;	/* current mute status */
1709d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	struct v4l2_frequency	cur_freq;	/* current frequency the tuner is tuned to */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define saa7111a_call(mxb, o, f, args...) \
1741b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
1751b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define tda9840_call(mxb, o, f, args...) \
1761b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->tda9840, o, f, ##args)
1771b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define tea6415c_call(mxb, o, f, args...) \
1781b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
1791b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define tuner_call(mxb, o, f, args...) \
1801b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->tuner, o, f, ##args)
1811b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define call_all(dev, o, f, args...) \
1821b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
183961f80f9c0c0f7c45d7818f9c9969dfaa9e4463dJean Delvare
1844894b709d14c593466cc05e55ee493af931205e8Hans Verkuilstatic void mxb_update_audmode(struct mxb *mxb)
1854894b709d14c593466cc05e55ee493af931205e8Hans Verkuil{
1864894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	struct v4l2_tuner t = {
1874894b709d14c593466cc05e55ee493af931205e8Hans Verkuil		.audmode = mxb->cur_mode,
1884894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	};
1894894b709d14c593466cc05e55ee493af931205e8Hans Verkuil
1904894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	tda9840_call(mxb, tuner, s_tuner, &t);
1914894b709d14c593466cc05e55ee493af931205e8Hans Verkuil}
1924894b709d14c593466cc05e55ee493af931205e8Hans Verkuil
1936680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuilstatic inline void tea6420_route(struct mxb *mxb, int idx)
1945325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil{
1955325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
1965325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
1975325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
1985325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
1995325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
2005325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
2015325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
2025325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
2035325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil}
2045325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
2051b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuilstatic struct saa7146_extension extension;
206961f80f9c0c0f7c45d7818f9c9969dfaa9e4463dJean Delvare
2076e65ca942b9664a987866ac0c62e7e450777056bHans Verkuilstatic int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
2086e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil{
2096e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	struct saa7146_dev *dev = container_of(ctrl->handler,
2106e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil				struct saa7146_dev, ctrl_handler);
2116e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	struct mxb *mxb = dev->ext_priv;
2126e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
2136e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	switch (ctrl->id) {
2146e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	case V4L2_CID_AUDIO_MUTE:
2156e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		mxb->cur_mute = ctrl->val;
2166e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		/* switch the audio-source */
2176680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		tea6420_route(mxb, ctrl->val ? 6 :
2186e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil				video_audio_connect[mxb->cur_input]);
2196e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		break;
2206e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	default:
2216e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		return -EINVAL;
2226e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	}
2236e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	return 0;
2246e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil}
2256e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
2266e65ca942b9664a987866ac0c62e7e450777056bHans Verkuilstatic const struct v4l2_ctrl_ops mxb_ctrl_ops = {
2276e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	.s_ctrl = mxb_s_ctrl,
2286e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil};
2296e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
2301b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuilstatic int mxb_probe(struct saa7146_dev *dev)
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2326e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
2331b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct mxb *mxb = NULL;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2356e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
2364894b709d14c593466cc05e55ee493af931205e8Hans Verkuil			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
2376e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	if (hdl->error)
2386e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		return hdl->error;
2397408187d223f63d46a13b6a35b8f96b032c2f623Panagiotis Issaris	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
2401b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	if (mxb == NULL) {
24144d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("not enough kernel memory\n");
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2456e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
2469ebeae5641b141a71ed442e9fcb4993f6c0cd04fHans Verkuil	snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
2479ebeae5641b141a71ed442e9fcb4993f6c0cd04fHans Verkuil
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
2491b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
25044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_S("cannot register i2c-device. skipping.\n");
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(mxb);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
255e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2569a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"saa7111", I2C_SAA7111A, NULL);
257e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2589a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tea6420", I2C_TEA6420_1, NULL);
259e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2609a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tea6420", I2C_TEA6420_2, NULL);
261e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2629a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tea6415c", I2C_TEA6415C, NULL);
263e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2649a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tda9840", I2C_TDA9840, NULL);
265e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2669a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tuner", I2C_TUNER, NULL);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if all devices are present */
2695fa1247a2b56f33f88432c24e109deaf91ef8281Al Viro	if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
2705fa1247a2b56f33f88432c24e109deaf91ef8281Al Viro	    !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
27144d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		pr_err("did not find all i2c devices. aborting\n");
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_del_adapter(&mxb->i2c_adapter);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(mxb);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
277a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	/* all devices are present, probe was successful */
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* we store the pointer in our private data field */
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->ext_priv = mxb;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
282d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil	v4l2_ctrl_handler_setup(hdl);
283d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
287a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab/* some init data for the saa7740, the so-called 'sound arena module'.
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   there are no specs available, so we simply use some init values */
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct {
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	length;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char	data[9];
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} mxb_saa7740_init[] = {
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x48, 0x00, 0x01 } },
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x80, 0xb3, 0x0a } },
3402633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	{-1, { 0 } }
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* bring hardware to a sane state. this has to be done, just in case someone
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   wants to capture from this device before it has been properly initialized.
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   the capture engine would badly fail, because no valid signal arrives on the
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   saa7146, thus leading to timeouts and stuff. */
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mxb_init_done(struct saa7146_dev* dev)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mxb* mxb = (struct mxb*)dev->ext_priv;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_msg msg;
35185369df350b138f26eac779da33de0960635ca4dMauro Carvalho Chehab	struct tuner_setup tun_setup;
3526acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold	v4l2_std_id std = V4L2_STD_PAL_BG;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, err = 0;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3564894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	/* mute audio on tea6420s */
3574894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	tea6420_route(mxb, 6);
3584894b709d14c593466cc05e55ee493af931205e8Hans Verkuil
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* select video mode in saa7111a */
3608774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart	saa7111a_call(mxb, video, s_std, std);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* select tuner-output on saa7111a */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = 0;
3645325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
365340dde817a4f68af79453ed295ca0e8de7232669Hans Verkuil		SAA7111_FMT_CCIR, 0);
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* select a tuner type */
36885369df350b138f26eac779da33de0960635ca4dMauro Carvalho Chehab	tun_setup.mode_mask = T_ANALOG_TV;
36985369df350b138f26eac779da33de0960635ca4dMauro Carvalho Chehab	tun_setup.addr = ADDR_UNSET;
3709d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	tun_setup.type = TUNER_PHILIPS_PAL;
3711b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	tuner_call(mxb, tuner, s_type_addr, &tun_setup);
3729d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	/* tune in some frequency on tuner */
3739d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	mxb->cur_freq.tuner = 0;
3749d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
3759d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	mxb->cur_freq.frequency = freq;
3761b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
3779d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold
3786acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold	/* set a default video standard */
3794894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	/* These two gpio calls set the GPIO pins that control the tda9820 */
3804894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	saa7146_write(dev, GPIO_CTRL, 0x00404050);
3814894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	saa7111a_call(mxb, core, s_gpio, 1);
3828774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart	saa7111a_call(mxb, video, s_std, std);
3838774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart	tuner_call(mxb, video, s_std, std);
3846acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold
3851b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	/* switch to tuner-channel on tea6415c */
3865325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	tea6415c_call(mxb, video, s_routing, 3, 17, 0);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	/* select tuner-output on multicable on tea6415c */
3895325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	tea6415c_call(mxb, video, s_routing, 3, 13, 0);
390a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the rest for mxb */
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mxb->cur_input = 0;
3936680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	mxb->cur_audinput = video_audio_connect[mxb->cur_input];
3944894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	mxb->cur_mute = 1;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
3974894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	mxb_update_audmode(mxb);
398a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the saa7740 (aka 'sound arena module') is present
400a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	   on the mxb. if so, we must initialize it. due to lack of
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   informations about the saa7740, the values were reverse
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   engineered. */
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.addr = 0x1b;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.flags = 0;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.len = mxb_saa7740_init[0].length;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.buf = &mxb_saa7740_init[0].data[0];
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4082633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
4092633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	if (err == 1) {
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* the sound arena module is a pos, that's probably the reason
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   philips refuses to hand out a datasheet for the saa7740...
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   it seems to screw up the i2c bus, so we disable fast irq
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   based i2c transactions here and rely on the slow and safe
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   polling method ... */
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		extension.flags &= ~SAA7146_USE_I2C_IRQ;
4162633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil		for (i = 1; ; i++) {
4172633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			if (-1 == mxb_saa7740_init[i].length)
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
420a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab			msg.len = mxb_saa7740_init[i].length;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msg.buf = &mxb_saa7740_init[i].data[0];
4222633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
4232633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			if (err != 1) {
42444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches				DEB_D("failed to initialize 'sound arena module'\n");
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
42844d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		pr_info("'sound arena module' detected\n");
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
430a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehaberr:
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the rest for saa7146: you should definitely set some basic values
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   for the input-port handling of the saa7146. */
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ext->saa has been filled by the core driver */
435a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* some stuff is done via variables */
4372633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
4382633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			input_port_selection[mxb->cur_input].hps_sync);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* some stuff is done via direct write to the registers */
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* this is ugly, but because of the fact that this is completely
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   hardware dependend, it should be done directly... */
444a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	saa7146_write(dev, DD1_STREAM_B,	0x00000000);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, DD1_INIT,		0x02000200);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* interrupt-handler. this gets called when irq_mask is != 0.
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   it must clear the interrupt-bits in irq_mask it has handled */
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mxb* mxb = (struct mxb*)dev->ext_priv;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
460b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
461b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
46244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
463223ffe5f8270ba9d069f1cbff9acec095a6f58b1Roel Kluin	if (i->index >= MXB_INPUTS)
464b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
465b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
469b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
471b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
4722633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
473b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	*i = mxb->cur_input;
474a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
47544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_INPUT %d\n", *i);
476b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
477b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
478a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
479b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_input(struct file *file, void *fh, unsigned int input)
480b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
481b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
482b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
4835325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	int err = 0;
484b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	int i = 0;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_S_INPUT %d\n", input);
487a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
488f14a2972e40dbfbe7077ec7ab21cc2729f7e7d6dRoel Kluin	if (input >= MXB_INPUTS)
489b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
490a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
491b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb->cur_input = input;
492a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
493b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
494b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			input_port_selection[input].hps_sync);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
496b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* prepare switching of tea6415c and saa7111a;
497b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	   have a look at the 'background'-file for further informations  */
498b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	switch (input) {
499b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case TUNER:
500b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_COMPOSITE0;
501a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
5025325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
5035325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
504b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		/* connect tuner-output always to multicable */
5055325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		if (!err)
5065325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil			err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
507b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
508b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case AUX3_YC:
509b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		/* nothing to be done here. aux3_yc is
510b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		   directly connected to the saa711a */
511b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_SVIDEO1;
512b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
513b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case AUX3:
514b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		/* nothing to be done here. aux3 is
515b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		   directly connected to the saa711a */
516b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_COMPOSITE1;
517b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
518b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case AUX1:
519b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_COMPOSITE0;
5205325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
521b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
522b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
523a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
5245325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	if (err)
5255325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		return err;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
527b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* switch video in saa7111a */
528340dde817a4f68af79453ed295ca0e8de7232669Hans Verkuil	if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
52944d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
530b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
5316680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	mxb->cur_audinput = video_audio_connect[input];
532b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* switch the audio-source only if necessary */
5335325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	if (0 == mxb->cur_mute)
5346680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		tea6420_route(mxb, mxb->cur_audinput);
5354894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	if (mxb->cur_audinput == 0)
5364894b709d14c593466cc05e55ee493af931205e8Hans Verkuil		mxb_update_audmode(mxb);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
538b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
539b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
542b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
543b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
544b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
545a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
546b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (t->index) {
54744d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
54844d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		      t->index);
549b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
550b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
551a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
55244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
553a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
554b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	memset(t, 0, sizeof(*t));
555b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	strlcpy(t->name, "TV Tuner", sizeof(t->name));
556b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	t->type = V4L2_TUNER_ANALOG_TV;
557b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
558b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
559b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	t->audmode = mxb->cur_mode;
5601b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	return call_all(dev, tuner, g_tuner, t);
561b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5632f73c7c582a685b3198b974cd6d964d0338f8ab5Hans Verkuilstatic int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
564b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
565b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
566b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
567a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
568b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (t->index) {
56944d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
57044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		      t->index);
571b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
572b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
574b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb->cur_mode = t->audmode;
5751b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	return call_all(dev, tuner, s_tuner, t);
576b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
578313fce750a073b041526f6e595f755f6233f8e73Hans Verkuilstatic int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
579313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil{
580313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
581313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil
582313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil	return call_all(dev, video, querystd, norm);
583313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil}
584313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil
585b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
586b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
587b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
588b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
589b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
5906e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	if (f->tuner)
591b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
592b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	*f = mxb->cur_freq;
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
595b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
596b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
598b530a447bb588fdf43fdf4eb909e4ee1921d47acHans Verkuilstatic int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
599b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
600b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
601b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
602b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_vv *vv = dev->vv_data;
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
604b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (f->tuner)
605b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
606a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
607b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (V4L2_TUNER_ANALOG_TV != f->type)
608b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
609a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
61044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
612b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* tune in desired frequency */
6136e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	tuner_call(mxb, tuner, s_frequency, f);
6146e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	/* let the tuner subdev clamp the frequency to the tuner range */
6156e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	mxb->cur_freq = *f;
616b530a447bb588fdf43fdf4eb909e4ee1921d47acHans Verkuil	tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
6174894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	if (mxb->cur_audinput == 0)
6184894b709d14c593466cc05e55ee493af931205e8Hans Verkuil		mxb_update_audmode(mxb);
6196e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
6206e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	if (mxb->cur_input)
6216e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		return 0;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
623b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
624b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	spin_lock(&dev->slock);
625b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv->vbi_fieldcount = 0;
626b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	spin_unlock(&dev->slock);
627b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
628b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
629b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
630b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
6316e65ca942b9664a987866ac0c62e7e450777056bHans Verkuilstatic int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
6326e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil{
6336e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	if (a->index >= MXB_AUDIOS)
6346e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		return -EINVAL;
6356e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	*a = mxb_audios[a->index];
6366e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	return 0;
6376e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil}
6386e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
639b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
640b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
641b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
642b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
643b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
6444894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	DEB_EE("VIDIOC_G_AUDIO\n");
6454894b709d14c593466cc05e55ee493af931205e8Hans Verkuil	*a = mxb_audios[mxb->cur_audinput];
646b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
647b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6490e8025b9f6011a6bd69d01080d584bc95a89d02eHans Verkuilstatic int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
650b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
6516e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
6526e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
6536e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil
65444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
6556680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
6566680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		if (mxb->cur_audinput != a->index) {
6576680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil			mxb->cur_audinput = a->index;
6586680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil			tea6420_route(mxb, a->index);
6594894b709d14c593466cc05e55ee493af931205e8Hans Verkuil			if (mxb->cur_audinput == 0)
6604894b709d14c593466cc05e55ee493af931205e8Hans Verkuil				mxb_update_audmode(mxb);
6616680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil		}
6626e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil		return 0;
6636680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	}
6646e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	return -EINVAL;
665b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
666a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
667b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil#ifdef CONFIG_VIDEO_ADV_DEBUG
668b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
669b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
670b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
672d2cac168160aa7afd472d4a04d0da3f146243710Hans Verkuil	if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
673d2cac168160aa7afd472d4a04d0da3f146243710Hans Verkuil		return -EINVAL;
674abca2056dc3dd0d813ba2f8b013e98cf009ba168Hans Verkuil	reg->val = saa7146_read(dev, reg->reg);
675abca2056dc3dd0d813ba2f8b013e98cf009ba168Hans Verkuil	reg->size = 4;
676ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	return 0;
677b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
679977ba3b1b73f24fae2d0c8bd59d7a4696f1e0cccHans Verkuilstatic int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
680b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
681b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
683d2cac168160aa7afd472d4a04d0da3f146243710Hans Verkuil	if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
684d2cac168160aa7afd472d4a04d0da3f146243710Hans Verkuil		return -EINVAL;
685abca2056dc3dd0d813ba2f8b013e98cf009ba168Hans Verkuil	saa7146_write(dev, reg->reg, reg->val);
686abca2056dc3dd0d813ba2f8b013e98cf009ba168Hans Verkuil	return 0;
687b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
688b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil#endif
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
690b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic struct saa7146_ext_vv vv_data;
691b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
692b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil/* this function only gets called when the probing was successful */
693b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
694b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
69503b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	struct mxb *mxb;
696a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
69744d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("dev:%p\n", dev);
698a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
699b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_vv_init(dev, &vv_data);
70003b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	if (mxb_probe(dev)) {
70103b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil		saa7146_vv_release(dev);
70203b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil		return -1;
70303b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	}
70403b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	mxb = (struct mxb *)dev->ext_priv;
70503b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil
706ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
707ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
708ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
709313fce750a073b041526f6e595f755f6233f8e73Hans Verkuil	vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
710ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
711ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
712ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
713ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
714ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
715ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
716ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
7172633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil#ifdef CONFIG_VIDEO_ADV_DEBUG
718ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
719ab49ae0f201f1e7e07250d011fffde8ed2530175Hans Verkuil	vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
7202633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil#endif
721b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
72244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		ERR("cannot register capture v4l2 device. skipping.\n");
72303b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil		saa7146_vv_release(dev);
724b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -1;
725b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
726b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
727b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
728b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (MXB_BOARD_CAN_DO_VBI(dev)) {
729b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
73044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches			ERR("cannot register vbi v4l2 device. skipping.\n");
731b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		}
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
733b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
73444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
735b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
736b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb_num++;
737b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb_init_done(dev);
738b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
739b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
740b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
741b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int mxb_detach(struct saa7146_dev *dev)
742b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
743b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
744b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
74544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("dev:%p\n", dev);
746b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
747d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil	/* mute audio on tea6420s */
7486680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	tea6420_route(mxb, 6);
749d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil
750b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_unregister_device(&mxb->video_dev,dev);
751b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (MXB_BOARD_CAN_DO_VBI(dev))
752b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		saa7146_unregister_device(&mxb->vbi_dev, dev);
753b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_vv_release(dev);
754b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
755b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb_num--;
756b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
757b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	i2c_del_adapter(&mxb->i2c_adapter);
758b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	kfree(mxb);
759b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
763c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuilstatic int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
765c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
767c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil	if (V4L2_STD_PAL_I == standard->id) {
7686acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold		v4l2_std_id std = V4L2_STD_PAL_I;
769c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil
77044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
7714894b709d14c593466cc05e55ee493af931205e8Hans Verkuil		/* These two gpio calls set the GPIO pins that control the tda9820 */
772a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab		saa7146_write(dev, GPIO_CTRL, 0x00404050);
7731b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil		saa7111a_call(mxb, core, s_gpio, 0);
7748774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart		saa7111a_call(mxb, video, s_std, std);
775d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil		if (mxb->cur_input == 0)
7768774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart			tuner_call(mxb, video, s_std, std);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
7786acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold		v4l2_std_id std = V4L2_STD_PAL_BG;
779c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil
780d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil		if (mxb->cur_input)
781d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil			std = standard->id;
78244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
7834894b709d14c593466cc05e55ee493af931205e8Hans Verkuil		/* These two gpio calls set the GPIO pins that control the tda9820 */
784a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab		saa7146_write(dev, GPIO_CTRL, 0x00404050);
7851b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil		saa7111a_call(mxb, core, s_gpio, 1);
7868774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart		saa7111a_call(mxb, video, s_std, std);
787d69f4a517c0a9b0b4795f4604aed8cf96dcd5223Hans Verkuil		if (mxb->cur_input == 0)
7888774bed9ce832d8d9ccb79e92800b808aa2d2ad2Laurent Pinchart			tuner_call(mxb, video, s_std, std);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_standard standard[] = {
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "PAL-BG", 	.id	= V4L2_STD_PAL_BG,
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x17,	.v_field 	= 288,
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x14,	.h_pixels 	= 680,
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 576,	.h_max_out	= 768,
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "PAL-I", 	.id	= V4L2_STD_PAL_I,
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x17,	.v_field 	= 288,
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x14,	.h_pixels 	= 680,
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 576,	.h_max_out	= 768,
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x16,	.v_field 	= 240,
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x06,	.h_pixels 	= 708,
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 480,	.h_max_out	= 640,
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x14,	.v_field 	= 288,
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x14,	.h_pixels 	= 720,
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 576,	.h_max_out	= 768,
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_pci_extension_data mxb = {
818a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	.ext_priv = "Multimedia eXtension Board",
819a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	.ext = &extension,
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id pci_tbl[] = {
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.vendor    = PCI_VENDOR_ID_PHILIPS,
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.subvendor = 0x0000,
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.subdevice = 0x0000,
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.driver_data = (unsigned long)&mxb,
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.vendor	= 0,
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, pci_tbl);
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_ext_vv vv_data = {
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inputs		= MXB_INPUTS,
8386e65ca942b9664a987866ac0c62e7e450777056bHans Verkuil	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stds		= &standard[0],
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
841a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	.std_callback	= &std_callback,
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_extension extension = {
8456680427791c94e611220a6cb34ae47dac9e3aa98Hans Verkuil	.name		= "Multimedia eXtension Board",
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.flags		= SAA7146_USE_I2C_IRQ,
847a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.pci_tbl	= &pci_tbl[0],
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.module		= THIS_MODULE,
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.attach		= mxb_attach,
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.detach		= mxb_detach,
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irq_mask	= 0,
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irq_func	= NULL,
856a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab};
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mxb_init_module(void)
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8602633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	if (saa7146_register_extension(&extension)) {
86144d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_S("failed to register extension\n");
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
864a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mxb_cleanup_module(void)
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_unregister_extension(&extension);
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mxb_init_module);
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mxb_cleanup_module);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
879