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 "mxb.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tea6415c.h"
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tea6420.h"
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define I2C_SAA7111A  0x24
391b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TDA9840   0x42
401b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TEA6415C  0x43
411b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TEA6420_1 0x4c
421b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TEA6420_2 0x4d
431b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define	I2C_TUNER     0x60
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab#define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* global variable */
48ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int mxb_num;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab/* initial frequence the tuner will be tuned to.
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   in verden (lower saxony, germany) 4148 is a
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   channel called "phoenix" */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int freq = 4148;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(freq, int, 0644);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic int debug;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0644);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MXB_INPUTS 4
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { TUNER, AUX1, AUX3, AUX3_YC };
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct v4l2_input mxb_inputs[MXB_INPUTS] = {
65657f2271050beabe725ba101c1d840f51a41f33dHans Verkuil	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
66657f2271050beabe725ba101c1d840f51a41f33dHans Verkuil	{ AUX1,		"AUX1",			V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
67657f2271050beabe725ba101c1d840f51a41f33dHans Verkuil	{ AUX3,		"AUX3 Composite",	V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
68657f2271050beabe725ba101c1d840f51a41f33dHans Verkuil	{ AUX3_YC,	"AUX3 S-Video",		V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this array holds the information, which port of the saa7146 each
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   input actually uses. the mxb uses port 0 for every input */
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct {
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hps_source;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int hps_sync;
76a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab} input_port_selection[MXB_INPUTS] = {
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this array holds the information of the audio source (mxb_audios),
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   which has to be switched corresponding to the video source (mxb_channels) */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int video_audio_connect[MXB_INPUTS] =
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 1, 3, 3 };
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
885325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstruct mxb_routing {
895325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	u32 input;
905325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	u32 output;
915325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil};
925325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
931b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil/* These are the necessary input-output-pins for bringing one audio source
941b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil   (see above) to the CD-output. Note that gain is set to 0 in this table. */
955325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
961b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 1, 1 }, { 1, 1 } },	/* Tuner */
971b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 5, 1 }, { 6, 1 } },	/* AUX 1 */
981b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 4, 1 }, { 6, 1 } },	/* AUX 2 */
991b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 3, 1 }, { 6, 1 } },	/* AUX 3 */
1001b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 1, 1 }, { 3, 1 } },	/* Radio */
1011b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 1, 1 }, { 2, 1 } },	/* CD-Rom */
1021b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 6, 1 }, { 6, 1 } }	/* Mute */
1031b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil};
1041b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil
1051b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil/* These are the necessary input-output-pins for bringing one audio source
1061b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil   (see above) to the line-output. Note that gain is set to 0 in this table. */
1075325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
1081b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 2, 3 }, { 1, 2 } },
1091b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 5, 3 }, { 6, 2 } },
1101b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 4, 3 }, { 6, 2 } },
1111b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 3, 3 }, { 6, 2 } },
1121b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 2, 3 }, { 3, 2 } },
1131b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 2, 3 }, { 2, 2 } },
1141b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	{ { 6, 3 }, { 6, 2 } }	/* Mute */
1151b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil};
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAXCONTROLS	1
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct v4l2_queryctrl mxb_controls[] = {
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mxb
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct video_device	*video_dev;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct video_device	*vbi_dev;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
127a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	struct i2c_adapter	i2c_adapter;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*saa7111a;
1301b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tda9840;
1311b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tea6415c;
1321b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tuner;
1331b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tea6420_1;
1341b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct v4l2_subdev	*tea6420_2;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	cur_mode;	/* current audio mode (mono, stereo, ...) */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	cur_input;	/* current input */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	cur_mute;	/* current mute status */
1399d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	struct v4l2_frequency	cur_freq;	/* current frequency the tuner is tuned to */
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define saa7111a_call(mxb, o, f, args...) \
1431b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
1441b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define tda9840_call(mxb, o, f, args...) \
1451b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->tda9840, o, f, ##args)
1461b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define tea6415c_call(mxb, o, f, args...) \
1471b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
1481b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define tuner_call(mxb, o, f, args...) \
1491b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_subdev_call(mxb->tuner, o, f, ##args)
1501b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil#define call_all(dev, o, f, args...) \
1511b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
152961f80f9c0c0f7c45d7818f9c9969dfaa9e4463dJean Delvare
1535325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic inline void tea6420_route_cd(struct mxb *mxb, int idx)
1545325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil{
1555325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
1565325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
1575325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
1585325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
1595325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil}
1605325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
1615325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuilstatic inline void tea6420_route_line(struct mxb *mxb, int idx)
1625325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil{
1635325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
1645325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
1655325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
1665325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
1675325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil}
1685325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
1691b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuilstatic struct saa7146_extension extension;
170961f80f9c0c0f7c45d7818f9c9969dfaa9e4463dJean Delvare
1711b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuilstatic int mxb_probe(struct saa7146_dev *dev)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1731b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	struct mxb *mxb = NULL;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1757408187d223f63d46a13b6a35b8f96b032c2f623Panagiotis Issaris	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
1761b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	if (mxb == NULL) {
17744d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("not enough kernel memory\n");
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1819ebeae5641b141a71ed442e9fcb4993f6c0cd04fHans Verkuil	snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
1829ebeae5641b141a71ed442e9fcb4993f6c0cd04fHans Verkuil
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
1841b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
18544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_S("cannot register i2c-device. skipping.\n");
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(mxb);
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EFAULT;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
190e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
1919a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"saa7111", I2C_SAA7111A, NULL);
192e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
1939a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tea6420", I2C_TEA6420_1, NULL);
194e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
1959a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tea6420", I2C_TEA6420_2, NULL);
196e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
1979a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tea6415c", I2C_TEA6415C, NULL);
198e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
1999a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tda9840", I2C_TDA9840, NULL);
200e6574f2fbecdb8af807169d345c10131ae060a88Hans Verkuil	mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
2019a1f8b34aa539000da17a06235e4bec254d0bfb5Laurent Pinchart			"tuner", I2C_TUNER, NULL);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if all devices are present */
2045fa1247a2b56f33f88432c24e109deaf91ef8281Al Viro	if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
2055fa1247a2b56f33f88432c24e109deaf91ef8281Al Viro	    !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
20644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		pr_err("did not find all i2c devices. aborting\n");
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i2c_del_adapter(&mxb->i2c_adapter);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(mxb);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	/* all devices are present, probe was successful */
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* we store the pointer in our private data field */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->ext_priv = mxb;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
220a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab/* some init data for the saa7740, the so-called 'sound arena module'.
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   there are no specs available, so we simply use some init values */
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct {
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	length;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char	data[9];
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} mxb_saa7740_init[] = {
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x48, 0x00, 0x01 } },
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 3, { 0x80, 0xb3, 0x0a } },
2732633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	{-1, { 0 } }
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* bring hardware to a sane state. this has to be done, just in case someone
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   wants to capture from this device before it has been properly initialized.
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   the capture engine would badly fail, because no valid signal arrives on the
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   saa7146, thus leading to timeouts and stuff. */
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mxb_init_done(struct saa7146_dev* dev)
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mxb* mxb = (struct mxb*)dev->ext_priv;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct i2c_msg msg;
28485369df350b138f26eac779da33de0960635ca4dMauro Carvalho Chehab	struct tuner_setup tun_setup;
2856acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold	v4l2_std_id std = V4L2_STD_PAL_BG;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, err = 0;
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* select video mode in saa7111a */
290f41737ece472cd803ffb24ac9f5d6fdd1d871341Hans Verkuil	saa7111a_call(mxb, core, s_std, std);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* select tuner-output on saa7111a */
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = 0;
2945325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
295340dde817a4f68af79453ed295ca0e8de7232669Hans Verkuil		SAA7111_FMT_CCIR, 0);
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* select a tuner type */
29885369df350b138f26eac779da33de0960635ca4dMauro Carvalho Chehab	tun_setup.mode_mask = T_ANALOG_TV;
29985369df350b138f26eac779da33de0960635ca4dMauro Carvalho Chehab	tun_setup.addr = ADDR_UNSET;
3009d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	tun_setup.type = TUNER_PHILIPS_PAL;
3011b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	tuner_call(mxb, tuner, s_type_addr, &tun_setup);
3029d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	/* tune in some frequency on tuner */
3039d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	mxb->cur_freq.tuner = 0;
3049d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
3059d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold	mxb->cur_freq.frequency = freq;
3061b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
3079d2599d98e9cb511f326b2d1b353e462bc360774Michael Hunold
3086acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold	/* set a default video standard */
309f41737ece472cd803ffb24ac9f5d6fdd1d871341Hans Verkuil	tuner_call(mxb, core, s_std, std);
3106acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* mute audio on tea6420s */
3125325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	tea6420_route_line(mxb, 6);
3135325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	tea6420_route_cd(mxb, 6);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	/* switch to tuner-channel on tea6415c */
3165325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	tea6415c_call(mxb, video, s_routing, 3, 17, 0);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	/* select tuner-output on multicable on tea6415c */
3195325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	tea6415c_call(mxb, video, s_routing, 3, 13, 0);
320a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the rest for mxb */
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mxb->cur_input = 0;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mxb->cur_mute = 1;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
326a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* check if the saa7740 (aka 'sound arena module') is present
328a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	   on the mxb. if so, we must initialize it. due to lack of
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   informations about the saa7740, the values were reverse
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   engineered. */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.addr = 0x1b;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.flags = 0;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.len = mxb_saa7740_init[0].length;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	msg.buf = &mxb_saa7740_init[0].data[0];
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3362633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
3372633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	if (err == 1) {
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* the sound arena module is a pos, that's probably the reason
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   philips refuses to hand out a datasheet for the saa7740...
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   it seems to screw up the i2c bus, so we disable fast irq
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   based i2c transactions here and rely on the slow and safe
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   polling method ... */
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		extension.flags &= ~SAA7146_USE_I2C_IRQ;
3442633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil		for (i = 1; ; i++) {
3452633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			if (-1 == mxb_saa7740_init[i].length)
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
348a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab			msg.len = mxb_saa7740_init[i].length;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msg.buf = &mxb_saa7740_init[i].data[0];
3502633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
3512633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			if (err != 1) {
35244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches				DEB_D("failed to initialize 'sound arena module'\n");
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
35644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		pr_info("'sound arena module' detected\n");
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
358a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehaberr:
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* the rest for saa7146: you should definitely set some basic values
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   for the input-port handling of the saa7146. */
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ext->saa has been filled by the core driver */
363a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* some stuff is done via variables */
3652633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
3662633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil			input_port_selection[mxb->cur_input].hps_sync);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* some stuff is done via direct write to the registers */
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* this is ugly, but because of the fact that this is completely
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   hardware dependend, it should be done directly... */
372a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	saa7146_write(dev, DD1_STREAM_B,	0x00000000);
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, DD1_INIT,		0x02000200);
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* interrupt-handler. this gets called when irq_mask is != 0.
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   it must clear the interrupt-bits in irq_mask it has handled */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mxb* mxb = (struct mxb*)dev->ext_priv;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
388b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
390b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
391b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	int i;
392a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
393b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	for (i = MAXCONTROLS - 1; i >= 0; i--) {
394b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		if (mxb_controls[i].id == qc->id) {
395b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			*qc = mxb_controls[i];
39644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches			DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
397b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			return 0;
398b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		}
399b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
400b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
401b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
403b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
404b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
405b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
406b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
407b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	int i;
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
409b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	for (i = MAXCONTROLS - 1; i >= 0; i--) {
410b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		if (mxb_controls[i].id == vc->id)
411b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			break;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
413a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
414b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (i < 0)
415b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
417b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (vc->id == V4L2_CID_AUDIO_MUTE) {
418b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		vc->value = mxb->cur_mute;
41944d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
420b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return 0;
421b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42344d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
427b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
429b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
4302633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
431b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	int i = 0;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
433b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	for (i = MAXCONTROLS - 1; i >= 0; i--) {
434b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		if (mxb_controls[i].id == vc->id)
435b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			break;
436b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
438b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (i < 0)
439b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (vc->id == V4L2_CID_AUDIO_MUTE) {
442b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		mxb->cur_mute = vc->value;
4435325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		/* switch the audio-source */
4445325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		tea6420_route_line(mxb, vc->value ? 6 :
4455325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil				video_audio_connect[mxb->cur_input]);
44644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value);
447b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
448b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
449b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
452b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
45344d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
454223ffe5f8270ba9d069f1cbff9acec095a6f58b1Roel Kluin	if (i->index >= MXB_INPUTS)
455b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
456b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
460b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
462b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
4632633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
464b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	*i = mxb->cur_input;
465a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
46644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_INPUT %d\n", *i);
467b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
468b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
469a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
470b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_input(struct file *file, void *fh, unsigned int input)
471b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
472b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
473b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
4745325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	int err = 0;
475b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	int i = 0;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47744d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_S_INPUT %d\n", input);
478a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
479f14a2972e40dbfbe7077ec7ab21cc2729f7e7d6dRoel Kluin	if (input >= MXB_INPUTS)
480b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
481a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
482b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb->cur_input = input;
483a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
484b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
485b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			input_port_selection[input].hps_sync);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
487b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* prepare switching of tea6415c and saa7111a;
488b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	   have a look at the 'background'-file for further informations  */
489b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	switch (input) {
490b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case TUNER:
491b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_COMPOSITE0;
492a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
4935325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
4945325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil
495b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		/* connect tuner-output always to multicable */
4965325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		if (!err)
4975325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil			err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
498b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
499b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case AUX3_YC:
500b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		/* nothing to be done here. aux3_yc is
501b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		   directly connected to the saa711a */
502b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_SVIDEO1;
503b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
504b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case AUX3:
505b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		/* nothing to be done here. aux3 is
506b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		   directly connected to the saa711a */
507b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_COMPOSITE1;
508b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
509b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	case AUX1:
510b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		i = SAA7115_COMPOSITE0;
5115325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
512b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		break;
513b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
514a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
5155325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	if (err)
5165325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		return err;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
518b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* switch video in saa7111a */
519340dde817a4f68af79453ed295ca0e8de7232669Hans Verkuil	if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
52044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
521b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
522b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* switch the audio-source only if necessary */
5235325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil	if (0 == mxb->cur_mute)
5245325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		tea6420_route_line(mxb, video_audio_connect[input]);
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
526b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
527b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
529b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
530b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
531b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
532b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
533a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
534b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (t->index) {
53544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
53644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		      t->index);
537b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
538b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
539a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
54044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
541a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
542b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	memset(t, 0, sizeof(*t));
543b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	strlcpy(t->name, "TV Tuner", sizeof(t->name));
544b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	t->type = V4L2_TUNER_ANALOG_TV;
545b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
546b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
547b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	t->audmode = mxb->cur_mode;
5481b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	return call_all(dev, tuner, g_tuner, t);
549b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
552b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
553b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
554b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
555a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
556b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (t->index) {
55744d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
55844d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		      t->index);
559b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
560b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
562b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb->cur_mode = t->audmode;
5631b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	return call_all(dev, tuner, s_tuner, t);
564b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
566b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
567b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
568b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
569b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
570b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
571b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (mxb->cur_input) {
57244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
57344d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		      mxb->cur_input);
574b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
577b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	*f = mxb->cur_freq;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57944d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
580b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
581b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
583b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
584b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
585b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
586b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
587b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_vv *vv = dev->vv_data;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
589b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (f->tuner)
590b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
591a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
592b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (V4L2_TUNER_ANALOG_TV != f->type)
593b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
594a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
595b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (mxb->cur_input) {
59644d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",
59744d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		      mxb->cur_input);
598b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb->cur_freq = *f;
60244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
604b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* tune in desired frequency */
6051b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
607b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
608b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	spin_lock(&dev->slock);
609b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv->vbi_fieldcount = 0;
610b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	spin_unlock(&dev->slock);
611b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
612b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
613b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
614b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
615b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
616b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
617b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
618b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
619b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
620223ffe5f8270ba9d069f1cbff9acec095a6f58b1Roel Kluin	if (a->index > MXB_INPUTS) {
62144d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_G_AUDIO %d out of range\n", a->index);
622b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -EINVAL;
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
62544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("VIDIOC_G_AUDIO %d\n", a->index);
626b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
627b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
628b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
630b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
631b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
63244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
633b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
634b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
635a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
636b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil#ifdef CONFIG_VIDEO_ADV_DEBUG
637b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
638b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
639b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	return call_all(dev, core, g_register, reg);
642b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
644b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
645b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
646b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil	return call_all(dev, core, s_register, reg);
649b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
650b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil#endif
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65299cd47bc733436da282016e629eef6baa0f6047cHans Verkuilstatic long vidioc_default(struct file *file, void *fh, bool valid_prio,
65399cd47bc733436da282016e629eef6baa0f6047cHans Verkuil							int cmd, void *arg)
654b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
655b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
656b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
657b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
658b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	switch (cmd) {
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MXB_S_AUDIO_CD:
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
661b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		int i = *(int *)arg;
662a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
6632633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil		if (i < 0 || i >= MXB_AUDIOS) {
66444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches			DEB_D("invalid argument to MXB_S_AUDIO_CD: i:%d\n", i);
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
667a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
66844d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_EE("MXB_S_AUDIO_CD: i:%d\n", i);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6705325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		tea6420_route_cd(mxb, i);
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MXB_S_AUDIO_LINE:
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
675b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		int i = *(int *)arg;
676a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
6772633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil		if (i < 0 || i >= MXB_AUDIOS) {
67844d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches			DEB_D("invalid argument to MXB_S_AUDIO_LINE: i:%d\n",
67944d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches			      i);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
682a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
68344d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_EE("MXB_S_AUDIO_LINE: i:%d\n", i);
6845325b4272a53b43f55b82cc369c310c2fcacdca1Hans Verkuil		tea6420_route_line(mxb, i);
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
687b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	default:
688b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil/*
68944d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB2(pr_err("does not handle this ioctl\n"));
690b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil*/
691b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -ENOIOCTLCMD;
692b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
693b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
694b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
696b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic struct saa7146_ext_vv vv_data;
697b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
698b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil/* this function only gets called when the probing was successful */
699b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
700b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
70103b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	struct mxb *mxb;
702a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
70344d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("dev:%p\n", dev);
704a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
705b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_vv_init(dev, &vv_data);
70603b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	if (mxb_probe(dev)) {
70703b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil		saa7146_vv_release(dev);
70803b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil		return -1;
70903b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	}
71003b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil	mxb = (struct mxb *)dev->ext_priv;
71103b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil
712b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
713b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
714b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
715b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
716b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_g_input = vidioc_g_input;
717b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_s_input = vidioc_s_input;
718b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
719b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
720b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
721b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
722b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_g_audio = vidioc_g_audio;
723b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_s_audio = vidioc_s_audio;
7242633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil#ifdef CONFIG_VIDEO_ADV_DEBUG
725b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_g_register = vidioc_g_register;
726b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_s_register = vidioc_s_register;
7272633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil#endif
728b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	vv_data.ops.vidioc_default = vidioc_default;
729b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
73044d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		ERR("cannot register capture v4l2 device. skipping.\n");
73103b1930efd3c2320b1dcba76c8af15f7e454919dHans Verkuil		saa7146_vv_release(dev);
732b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		return -1;
733b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	}
734b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
735b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
736b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (MXB_BOARD_CAN_DO_VBI(dev)) {
737b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
73844d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches			ERR("cannot register vbi v4l2 device. skipping.\n");
739b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		}
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
741b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
74244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
743b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
744b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb_num++;
745b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb_init_done(dev);
746b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	return 0;
747b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil}
748b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
749b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuilstatic int mxb_detach(struct saa7146_dev *dev)
750b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil{
751b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
752b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
75344d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches	DEB_EE("dev:%p\n", dev);
754b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
755b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_unregister_device(&mxb->video_dev,dev);
756b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	if (MXB_BOARD_CAN_DO_VBI(dev))
757b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil		saa7146_unregister_device(&mxb->vbi_dev, dev);
758b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	saa7146_vv_release(dev);
759b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
760b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	mxb_num--;
761b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
762b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	i2c_del_adapter(&mxb->i2c_adapter);
763b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil	kfree(mxb);
764b960074fec573fb1b226d9e2686ce51be807cdf1Hans Verkuil
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
768c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuilstatic int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
770c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil	struct mxb *mxb = (struct mxb *)dev->ext_priv;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
772c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil	if (V4L2_STD_PAL_I == standard->id) {
7736acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold		v4l2_std_id std = V4L2_STD_PAL_I;
774c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil
77544d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* set the 7146 gpio register -- I don't know what this does exactly */
777a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab		saa7146_write(dev, GPIO_CTRL, 0x00404050);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* unset the 7111 gpio register -- I don't know what this does exactly */
7791b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil		saa7111a_call(mxb, core, s_gpio, 0);
780f41737ece472cd803ffb24ac9f5d6fdd1d871341Hans Verkuil		tuner_call(mxb, core, s_std, std);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
7826acaba8e22bb355409e06d9e7ce4e7bef1bcaa04Michael Hunold		v4l2_std_id std = V4L2_STD_PAL_BG;
783c6eb8eafdba4ad18b4520a0d28a38bc9e61883eaHans Verkuil
78444d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* set the 7146 gpio register -- I don't know what this does exactly */
786a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab		saa7146_write(dev, GPIO_CTRL, 0x00404050);
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* set the 7111 gpio register -- I don't know what this does exactly */
7881b8dac150a01e2312d8e3fedd6462a0ec34c96d0Hans Verkuil		saa7111a_call(mxb, core, s_gpio, 1);
789f41737ece472cd803ffb24ac9f5d6fdd1d871341Hans Verkuil		tuner_call(mxb, core, s_std, std);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_standard standard[] = {
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "PAL-BG", 	.id	= V4L2_STD_PAL_BG,
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x17,	.v_field 	= 288,
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x14,	.h_pixels 	= 680,
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 576,	.h_max_out	= 768,
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "PAL-I", 	.id	= V4L2_STD_PAL_I,
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x17,	.v_field 	= 288,
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x14,	.h_pixels 	= 680,
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 576,	.h_max_out	= 768,
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x16,	.v_field 	= 240,
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x06,	.h_pixels 	= 708,
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 480,	.h_max_out	= 640,
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_offset	= 0x14,	.v_field 	= 288,
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.h_offset	= 0x14,	.h_pixels 	= 720,
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.v_max_out	= 576,	.h_max_out	= 768,
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_pci_extension_data mxb = {
819a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	.ext_priv = "Multimedia eXtension Board",
820a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	.ext = &extension,
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id pci_tbl[] = {
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.vendor    = PCI_VENDOR_ID_PHILIPS,
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.subvendor = 0x0000,
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.subdevice = 0x0000,
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.driver_data = (unsigned long)&mxb,
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}, {
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.vendor	= 0,
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, pci_tbl);
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_ext_vv vv_data = {
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inputs		= MXB_INPUTS,
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.stds		= &standard[0],
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
842a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab	.std_callback	= &std_callback,
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_extension extension = {
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= MXB_IDENTIFIER,
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.flags		= SAA7146_USE_I2C_IRQ,
848a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.pci_tbl	= &pci_tbl[0],
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.module		= THIS_MODULE,
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.attach		= mxb_attach,
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.detach		= mxb_detach,
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irq_mask	= 0,
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.irq_func	= NULL,
857a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab};
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mxb_init_module(void)
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8612633812f897cc354071699e86ea82e3bfd77cddcHans Verkuil	if (saa7146_register_extension(&extension)) {
86244d0b80e5ff741d502a6ccc8685a18bda1ac9da4Joe Perches		DEB_S("failed to register extension\n");
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
865a8733ca5141c256322ab5ea9fd3074942a209bbaMauro Carvalho Chehab
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mxb_cleanup_module(void)
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	saa7146_unregister_extension(&extension);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mxb_init_module);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mxb_cleanup_module);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
880