mxb.c 27.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
    mxb - v4l2 driver for the Multimedia eXtension Board
3

4
    Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
L
Linus Torvalds 已提交
5 6 7

    Visit http://www.mihu.de/linux/saa7146/mxb/
    for further details about this card.
8

L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define DEBUG_VARIABLE debug

#include <media/saa7146_vv.h>
#include <media/tuner.h>
28
#include <media/v4l2-common.h>
29
#include <media/saa7115.h>
L
Linus Torvalds 已提交
30 31 32 33 34

#include "mxb.h"
#include "tea6415c.h"
#include "tea6420.h"

35 36 37 38 39 40 41
#define	I2C_SAA5246A  0x11
#define I2C_SAA7111A  0x24
#define	I2C_TDA9840   0x42
#define	I2C_TEA6415C  0x43
#define	I2C_TEA6420_1 0x4c
#define	I2C_TEA6420_2 0x4d
#define	I2C_TUNER     0x60
L
Linus Torvalds 已提交
42

43
#define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0)
L
Linus Torvalds 已提交
44 45

/* global variable */
46
static int mxb_num;
L
Linus Torvalds 已提交
47

48
/* initial frequence the tuner will be tuned to.
L
Linus Torvalds 已提交
49 50 51 52 53 54
   in verden (lower saxony, germany) 4148 is a
   channel called "phoenix" */
static int freq = 4148;
module_param(freq, int, 0644);
MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");

55
static int debug;
L
Linus Torvalds 已提交
56 57 58 59 60 61 62
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");

#define MXB_INPUTS 4
enum { TUNER, AUX1, AUX3, AUX3_YC };

static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
63
	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
L
Linus Torvalds 已提交
64 65 66 67 68 69 70 71 72 73
	{ AUX1,		"AUX1",			V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
	{ AUX3,		"AUX3 Composite",	V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
	{ AUX3_YC,	"AUX3 S-Video",		V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
};

/* this array holds the information, which port of the saa7146 each
   input actually uses. the mxb uses port 0 for every input */
static struct {
	int hps_source;
	int hps_sync;
74
} input_port_selection[MXB_INPUTS] = {
L
Linus Torvalds 已提交
75 76 77 78 79 80 81 82 83 84 85
	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
	{ SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
};

/* this array holds the information of the audio source (mxb_audios),
   which has to be switched corresponding to the video source (mxb_channels) */
static int video_audio_connect[MXB_INPUTS] =
	{ 0, 1, 3, 3 };

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
/* These are the necessary input-output-pins for bringing one audio source
   (see above) to the CD-output. Note that gain is set to 0 in this table. */
static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
	{ { 1, 1 }, { 1, 1 } },	/* Tuner */
	{ { 5, 1 }, { 6, 1 } },	/* AUX 1 */
	{ { 4, 1 }, { 6, 1 } },	/* AUX 2 */
	{ { 3, 1 }, { 6, 1 } },	/* AUX 3 */
	{ { 1, 1 }, { 3, 1 } },	/* Radio */
	{ { 1, 1 }, { 2, 1 } },	/* CD-Rom */
	{ { 6, 1 }, { 6, 1 } }	/* Mute */
};

/* These are the necessary input-output-pins for bringing one audio source
   (see above) to the line-output. Note that gain is set to 0 in this table. */
static struct v4l2_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
	{ { 2, 3 }, { 1, 2 } },
	{ { 5, 3 }, { 6, 2 } },
	{ { 4, 3 }, { 6, 2 } },
	{ { 3, 3 }, { 6, 2 } },
	{ { 2, 3 }, { 3, 2 } },
	{ { 2, 3 }, { 2, 2 } },
	{ { 6, 3 }, { 6, 2 } }	/* Mute */
};
L
Linus Torvalds 已提交
109 110 111 112 113 114 115 116 117 118 119

#define MAXCONTROLS	1
static struct v4l2_queryctrl mxb_controls[] = {
	{ V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
};

struct mxb
{
	struct video_device	*video_dev;
	struct video_device	*vbi_dev;

120
	struct i2c_adapter	i2c_adapter;
L
Linus Torvalds 已提交
121

122 123 124 125 126 127
	struct v4l2_subdev	*saa7111a;
	struct v4l2_subdev	*tda9840;
	struct v4l2_subdev	*tea6415c;
	struct v4l2_subdev	*tuner;
	struct v4l2_subdev	*tea6420_1;
	struct v4l2_subdev	*tea6420_2;
L
Linus Torvalds 已提交
128 129 130 131

	int	cur_mode;	/* current audio mode (mono, stereo, ...) */
	int	cur_input;	/* current input */
	int	cur_mute;	/* current mute status */
132
	struct v4l2_frequency	cur_freq;	/* current frequency the tuner is tuned to */
L
Linus Torvalds 已提交
133 134
};

135 136 137 138 139 140 141 142 143 144 145 146 147 148
#define saa7111a_call(mxb, o, f, args...) \
	v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
#define tea6420_1_call(mxb, o, f, args...) \
	v4l2_subdev_call(mxb->tea6420_1, o, f, ##args)
#define tea6420_2_call(mxb, o, f, args...) \
	v4l2_subdev_call(mxb->tea6420_2, o, f, ##args)
#define tda9840_call(mxb, o, f, args...) \
	v4l2_subdev_call(mxb->tda9840, o, f, ##args)
#define tea6415c_call(mxb, o, f, args...) \
	v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
#define tuner_call(mxb, o, f, args...) \
	v4l2_subdev_call(mxb->tuner, o, f, ##args)
#define call_all(dev, o, f, args...) \
	v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
149

150
static struct saa7146_extension extension;
151

152
static int mxb_probe(struct saa7146_dev *dev)
L
Linus Torvalds 已提交
153
{
154
	struct mxb *mxb = NULL;
L
Linus Torvalds 已提交
155

P
 
Panagiotis Issaris 已提交
156
	mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
157
	if (mxb == NULL) {
L
Linus Torvalds 已提交
158 159 160 161
		DEB_D(("not enough kernel memory.\n"));
		return -ENOMEM;
	}

162 163
	snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);

L
Linus Torvalds 已提交
164
	saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
165
	if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
L
Linus Torvalds 已提交
166 167 168 169 170
		DEB_S(("cannot register i2c-device. skipping.\n"));
		kfree(mxb);
		return -EFAULT;
	}

171 172 173 174 175 176 177 178 179 180 181 182 183 184
	mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"saa7115", "saa7111", I2C_SAA7111A);
	mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"tea6420", "tea6420", I2C_TEA6420_1);
	mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"tea6420", "tea6420", I2C_TEA6420_2);
	mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"tea6415c", "tea6415c", I2C_TEA6415C);
	mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"tda9840", "tda9840", I2C_TDA9840);
	mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"tuner", "tuner", I2C_TUNER);
	if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
			"saa5246a", "saa5246a", I2C_SAA5246A)) {
185 186
		printk(KERN_INFO "mxb: found teletext decoder\n");
	}
L
Linus Torvalds 已提交
187 188

	/* check if all devices are present */
A
Al Viro 已提交
189 190
	if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
	    !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
L
Linus Torvalds 已提交
191 192 193 194 195 196
		printk("mxb: did not find all i2c devices. aborting\n");
		i2c_del_adapter(&mxb->i2c_adapter);
		kfree(mxb);
		return -ENODEV;
	}

197
	/* all devices are present, probe was successful */
L
Linus Torvalds 已提交
198 199 200 201 202 203 204

	/* we store the pointer in our private data field */
	dev->ext_priv = mxb;

	return 0;
}

205
/* some init data for the saa7740, the so-called 'sound arena module'.
L
Linus Torvalds 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
   there are no specs available, so we simply use some init values */
static struct {
	int	length;
	char	data[9];
} mxb_saa7740_init[] = {
	{ 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
	{ 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
	{ 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
	{ 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
	{ 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
	{ 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
	{ 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
	{ 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
	{ 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
	{ 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
	{ 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
	{ 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
	{ 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
	{ 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
	{ 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
	{ 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
	{ 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
	{ 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
	{ 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
	{ 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
	{ 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
	{ 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
	{ 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
	{ 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
	{ 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
	{ 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
	{ 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
	{ 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
	{ 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
	{ 3, { 0x48, 0x00, 0x01 } },
	{ 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
	{ 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
	{ 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
	{ 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
	{ 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
	{ 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
	{ 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
	{ 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
	{ 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
	{ 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
	{ 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
	{ 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
	{ 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
	{ 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
	{ 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
	{ 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
	{ 3, { 0x80, 0xb3, 0x0a } },
258
	{-1, { 0 } }
L
Linus Torvalds 已提交
259 260 261 262 263 264 265 266 267 268
};

/* bring hardware to a sane state. this has to be done, just in case someone
   wants to capture from this device before it has been properly initialized.
   the capture engine would badly fail, because no valid signal arrives on the
   saa7146, thus leading to timeouts and stuff. */
static int mxb_init_done(struct saa7146_dev* dev)
{
	struct mxb* mxb = (struct mxb*)dev->ext_priv;
	struct i2c_msg msg;
269
	struct tuner_setup tun_setup;
270
	v4l2_std_id std = V4L2_STD_PAL_BG;
271
	struct v4l2_routing route;
L
Linus Torvalds 已提交
272 273 274 275

	int i = 0, err = 0;

	/* select video mode in saa7111a */
276
	saa7111a_call(mxb, core, s_std, std);
L
Linus Torvalds 已提交
277 278 279

	/* select tuner-output on saa7111a */
	i = 0;
280 281
	route.input = SAA7115_COMPOSITE0;
	route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
282
	saa7111a_call(mxb, video, s_routing, &route);
L
Linus Torvalds 已提交
283 284

	/* select a tuner type */
285 286
	tun_setup.mode_mask = T_ANALOG_TV;
	tun_setup.addr = ADDR_UNSET;
287
	tun_setup.type = TUNER_PHILIPS_PAL;
288
	tuner_call(mxb, tuner, s_type_addr, &tun_setup);
289 290 291 292
	/* tune in some frequency on tuner */
	mxb->cur_freq.tuner = 0;
	mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
	mxb->cur_freq.frequency = freq;
293
	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
294

295
	/* set a default video standard */
296
	tuner_call(mxb, core, s_std, std);
297

L
Linus Torvalds 已提交
298
	/* mute audio on tea6420s */
299 300
	tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
	tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
301 302
	tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[6][0]);
	tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[6][1]);
L
Linus Torvalds 已提交
303

304 305 306 307
	/* switch to tuner-channel on tea6415c */
	route.input = 3;
	route.output = 17;
	tea6415c_call(mxb, video, s_routing, &route);
L
Linus Torvalds 已提交
308

309 310 311 312
	/* select tuner-output on multicable on tea6415c */
	route.input = 3;
	route.output = 13;
	tea6415c_call(mxb, video, s_routing, &route);
313

L
Linus Torvalds 已提交
314 315 316 317 318
	/* the rest for mxb */
	mxb->cur_input = 0;
	mxb->cur_mute = 1;

	mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
319

L
Linus Torvalds 已提交
320
	/* check if the saa7740 (aka 'sound arena module') is present
321
	   on the mxb. if so, we must initialize it. due to lack of
L
Linus Torvalds 已提交
322 323 324 325 326 327 328
	   informations about the saa7740, the values were reverse
	   engineered. */
	msg.addr = 0x1b;
	msg.flags = 0;
	msg.len = mxb_saa7740_init[0].length;
	msg.buf = &mxb_saa7740_init[0].data[0];

329 330
	err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
	if (err == 1) {
L
Linus Torvalds 已提交
331 332 333 334 335 336
		/* the sound arena module is a pos, that's probably the reason
		   philips refuses to hand out a datasheet for the saa7740...
		   it seems to screw up the i2c bus, so we disable fast irq
		   based i2c transactions here and rely on the slow and safe
		   polling method ... */
		extension.flags &= ~SAA7146_USE_I2C_IRQ;
337 338
		for (i = 1; ; i++) {
			if (-1 == mxb_saa7740_init[i].length)
L
Linus Torvalds 已提交
339 340
				break;

341
			msg.len = mxb_saa7740_init[i].length;
L
Linus Torvalds 已提交
342
			msg.buf = &mxb_saa7740_init[i].data[0];
343 344
			err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
			if (err != 1) {
L
Linus Torvalds 已提交
345 346 347 348 349 350
				DEB_D(("failed to initialize 'sound arena module'.\n"));
				goto err;
			}
		}
		INFO(("'sound arena module' detected.\n"));
	}
351
err:
L
Linus Torvalds 已提交
352 353 354 355
	/* the rest for saa7146: you should definitely set some basic values
	   for the input-port handling of the saa7146. */

	/* ext->saa has been filled by the core driver */
356

L
Linus Torvalds 已提交
357
	/* some stuff is done via variables */
358 359
	saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
			input_port_selection[mxb->cur_input].hps_sync);
L
Linus Torvalds 已提交
360 361 362 363 364

	/* some stuff is done via direct write to the registers */

	/* this is ugly, but because of the fact that this is completely
	   hardware dependend, it should be done directly... */
365
	saa7146_write(dev, DD1_STREAM_B,	0x00000000);
L
Linus Torvalds 已提交
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
	saa7146_write(dev, DD1_INIT,		0x02000200);
	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));

	return 0;
}

/* interrupt-handler. this gets called when irq_mask is != 0.
   it must clear the interrupt-bits in irq_mask it has handled */
/*
void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
{
	struct mxb* mxb = (struct mxb*)dev->ext_priv;
}
*/

381
static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
L
Linus Torvalds 已提交
382
{
383 384
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	int i;
385

386 387 388 389 390 391 392 393 394
	for (i = MAXCONTROLS - 1; i >= 0; i--) {
		if (mxb_controls[i].id == qc->id) {
			*qc = mxb_controls[i];
			DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
			return 0;
		}
	}
	return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
}
L
Linus Torvalds 已提交
395

396 397 398 399 400
static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
	int i;
L
Linus Torvalds 已提交
401

402 403 404
	for (i = MAXCONTROLS - 1; i >= 0; i--) {
		if (mxb_controls[i].id == vc->id)
			break;
L
Linus Torvalds 已提交
405
	}
406

407 408
	if (i < 0)
		return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
L
Linus Torvalds 已提交
409

410 411 412 413 414
	if (vc->id == V4L2_CID_AUDIO_MUTE) {
		vc->value = mxb->cur_mute;
		DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
		return 0;
	}
L
Linus Torvalds 已提交
415

416
	DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
L
Linus Torvalds 已提交
417 418 419
	return 0;
}

420
static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
L
Linus Torvalds 已提交
421
{
422
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
423
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
424
	int i = 0;
L
Linus Torvalds 已提交
425

426 427 428 429
	for (i = MAXCONTROLS - 1; i >= 0; i--) {
		if (mxb_controls[i].id == vc->id)
			break;
	}
L
Linus Torvalds 已提交
430

431 432
	if (i < 0)
		return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
L
Linus Torvalds 已提交
433

434 435 436 437
	if (vc->id == V4L2_CID_AUDIO_MUTE) {
		mxb->cur_mute = vc->value;
		if (!vc->value) {
			/* switch the audio-source */
438
			tea6420_1_call(mxb, audio, s_routing,
439
					&TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
440
			tea6420_2_call(mxb, audio, s_routing,
441 442
					&TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
		} else {
443
			tea6420_1_call(mxb, audio, s_routing,
444
					&TEA6420_line[6][0]);
445
			tea6420_2_call(mxb, audio, s_routing,
446 447 448 449 450 451
					&TEA6420_line[6][1]);
		}
		DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
	}
	return 0;
}
L
Linus Torvalds 已提交
452

453 454 455 456 457 458
static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
{
	DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
	if (i->index < 0 || i->index >= MXB_INPUTS)
		return -EINVAL;
	memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
L
Linus Torvalds 已提交
459 460 461
	return 0;
}

462
static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
L
Linus Torvalds 已提交
463
{
464
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
465
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
466
	*i = mxb->cur_input;
467

468 469 470
	DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
	return 0;
}
471

472 473 474 475 476 477
static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
	struct v4l2_routing route;
	int i = 0;
L
Linus Torvalds 已提交
478

479
	DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
480

481 482
	if (input < 0 || input >= MXB_INPUTS)
		return -EINVAL;
483

484
	mxb->cur_input = input;
485

486 487
	saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
			input_port_selection[input].hps_sync);
L
Linus Torvalds 已提交
488

489 490 491 492 493
	/* prepare switching of tea6415c and saa7111a;
	   have a look at the 'background'-file for further informations  */
	switch (input) {
	case TUNER:
		i = SAA7115_COMPOSITE0;
494 495
		route.input = 3;
		route.output = 17;
496

497
		if (tea6415c_call(mxb, video, s_routing, &route)) {
498 499
			printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
			return -EFAULT;
L
Linus Torvalds 已提交
500
		}
501
		/* connect tuner-output always to multicable */
502 503
		route.input = 3;
		route.output = 13;
504 505 506 507 508 509 510 511 512 513 514 515 516
		break;
	case AUX3_YC:
		/* nothing to be done here. aux3_yc is
		   directly connected to the saa711a */
		i = SAA7115_SVIDEO1;
		break;
	case AUX3:
		/* nothing to be done here. aux3 is
		   directly connected to the saa711a */
		i = SAA7115_COMPOSITE1;
		break;
	case AUX1:
		i = SAA7115_COMPOSITE0;
517 518
		route.input = 1;
		route.output = 17;
519 520
		break;
	}
521

522 523 524 525
	/* switch video in tea6415c only if necessary */
	switch (input) {
	case TUNER:
	case AUX1:
526
		if (tea6415c_call(mxb, video, s_routing, &route)) {
527 528
			printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
			return -EFAULT;
L
Linus Torvalds 已提交
529
		}
530 531 532
		break;
	default:
		break;
L
Linus Torvalds 已提交
533 534
	}

535 536 537
	/* switch video in saa7111a */
	route.input = i;
	route.output = 0;
538
	if (saa7111a_call(mxb, video, s_routing, &route))
539 540 541 542
		printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n");

	/* switch the audio-source only if necessary */
	if (0 == mxb->cur_mute) {
543
		tea6420_1_call(mxb, audio, s_routing,
544
				&TEA6420_line[video_audio_connect[input]][0]);
545
		tea6420_2_call(mxb, audio, s_routing,
546
				&TEA6420_line[video_audio_connect[input]][1]);
547
	}
L
Linus Torvalds 已提交
548

549 550
	return 0;
}
L
Linus Torvalds 已提交
551

552 553 554 555
static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
556

557 558 559 560
	if (t->index) {
		DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
		return -EINVAL;
	}
561

562
	DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
563

564 565 566 567 568 569
	memset(t, 0, sizeof(*t));
	strlcpy(t->name, "TV Tuner", sizeof(t->name));
	t->type = V4L2_TUNER_ANALOG_TV;
	t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
			V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
	t->audmode = mxb->cur_mode;
570
	return call_all(dev, tuner, g_tuner, t);
571
}
L
Linus Torvalds 已提交
572

573 574 575 576
static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
577

578 579 580 581
	if (t->index) {
		DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
		return -EINVAL;
	}
L
Linus Torvalds 已提交
582

583
	mxb->cur_mode = t->audmode;
584
	return call_all(dev, tuner, s_tuner, t);
585
}
L
Linus Torvalds 已提交
586

587 588 589 590 591 592 593 594 595
static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;

	if (mxb->cur_input) {
		DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
					mxb->cur_input));
		return -EINVAL;
L
Linus Torvalds 已提交
596 597
	}

598
	*f = mxb->cur_freq;
L
Linus Torvalds 已提交
599

600 601 602
	DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
	return 0;
}
L
Linus Torvalds 已提交
603

604 605 606 607 608
static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
	struct saa7146_vv *vv = dev->vv_data;
L
Linus Torvalds 已提交
609

610 611
	if (f->tuner)
		return -EINVAL;
612

613 614
	if (V4L2_TUNER_ANALOG_TV != f->type)
		return -EINVAL;
615

616 617 618
	if (mxb->cur_input) {
		DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
		return -EINVAL;
L
Linus Torvalds 已提交
619 620
	}

621 622
	mxb->cur_freq = *f;
	DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
L
Linus Torvalds 已提交
623

624
	/* tune in desired frequency */
625
	tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
L
Linus Torvalds 已提交
626

627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
	/* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
	spin_lock(&dev->slock);
	vv->vbi_fieldcount = 0;
	spin_unlock(&dev->slock);

	return 0;
}

static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;

	if (a->index < 0 || a->index > MXB_INPUTS) {
		DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
		return -EINVAL;
L
Linus Torvalds 已提交
643 644
	}

645 646 647 648
	DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
	memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
	return 0;
}
L
Linus Torvalds 已提交
649

650 651 652 653 654
static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
{
	DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
	return 0;
}
655

656 657 658 659
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
L
Linus Torvalds 已提交
660

661
	return call_all(dev, core, g_register, reg);
662
}
L
Linus Torvalds 已提交
663

664 665 666
static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
L
Linus Torvalds 已提交
667

668
	return call_all(dev, core, s_register, reg);
669 670
}
#endif
L
Linus Torvalds 已提交
671

672 673 674 675 676 677
static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
{
	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
	struct mxb *mxb = (struct mxb *)dev->ext_priv;

	switch (cmd) {
L
Linus Torvalds 已提交
678 679
	case MXB_S_AUDIO_CD:
	{
680
		int i = *(int *)arg;
681

682
		if (i < 0 || i >= MXB_AUDIOS) {
683
			DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
L
Linus Torvalds 已提交
684 685
			return -EINVAL;
		}
686

687
		DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
L
Linus Torvalds 已提交
688

689 690
		tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]);
		tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]);
L
Linus Torvalds 已提交
691 692 693 694 695

		return 0;
	}
	case MXB_S_AUDIO_LINE:
	{
696
		int i = *(int *)arg;
697

698
		if (i < 0 || i >= MXB_AUDIOS) {
699
			DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
L
Linus Torvalds 已提交
700 701
			return -EINVAL;
		}
702

703
		DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
704 705
		tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]);
		tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]);
L
Linus Torvalds 已提交
706 707 708

		return 0;
	}
709 710 711 712 713 714 715 716
	default:
/*
		DEB2(printk("does not handle this ioctl.\n"));
*/
		return -ENOIOCTLCMD;
	}
	return 0;
}
L
Linus Torvalds 已提交
717

718 719 720 721 722 723
static struct saa7146_ext_vv vv_data;

/* this function only gets called when the probing was successful */
static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
724

725
	DEB_EE(("dev:%p\n", dev));
726

727 728
	/* checking for i2c-devices can be omitted here, because we
	   already did this in "mxb_vl42_probe" */
729

730 731 732 733 734 735 736 737 738 739 740 741 742
	saa7146_vv_init(dev, &vv_data);
	vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
	vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
	vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
	vv_data.ops.vidioc_enum_input = vidioc_enum_input;
	vv_data.ops.vidioc_g_input = vidioc_g_input;
	vv_data.ops.vidioc_s_input = vidioc_s_input;
	vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
	vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
	vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
	vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
	vv_data.ops.vidioc_g_audio = vidioc_g_audio;
	vv_data.ops.vidioc_s_audio = vidioc_s_audio;
743
#ifdef CONFIG_VIDEO_ADV_DEBUG
744 745
	vv_data.ops.vidioc_g_register = vidioc_g_register;
	vv_data.ops.vidioc_s_register = vidioc_s_register;
746
#endif
747 748 749 750 751 752 753 754 755 756 757
	vv_data.ops.vidioc_default = vidioc_default;
	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
		ERR(("cannot register capture v4l2 device. skipping.\n"));
		return -1;
	}

	/* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
	if (MXB_BOARD_CAN_DO_VBI(dev)) {
		if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
			ERR(("cannot register vbi v4l2 device. skipping.\n"));
		}
L
Linus Torvalds 已提交
758
	}
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

	printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);

	mxb_num++;
	mxb_init_done(dev);
	return 0;
}

static int mxb_detach(struct saa7146_dev *dev)
{
	struct mxb *mxb = (struct mxb *)dev->ext_priv;

	DEB_EE(("dev:%p\n", dev));

	saa7146_unregister_device(&mxb->video_dev,dev);
	if (MXB_BOARD_CAN_DO_VBI(dev))
		saa7146_unregister_device(&mxb->vbi_dev, dev);
	saa7146_vv_release(dev);

	mxb_num--;

	i2c_del_adapter(&mxb->i2c_adapter);
	kfree(mxb);

L
Linus Torvalds 已提交
783 784 785
	return 0;
}

786
static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
L
Linus Torvalds 已提交
787
{
788
	struct mxb *mxb = (struct mxb *)dev->ext_priv;
L
Linus Torvalds 已提交
789

790
	if (V4L2_STD_PAL_I == standard->id) {
791
		v4l2_std_id std = V4L2_STD_PAL_I;
792

L
Linus Torvalds 已提交
793 794
		DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
		/* set the 7146 gpio register -- I don't know what this does exactly */
795
		saa7146_write(dev, GPIO_CTRL, 0x00404050);
L
Linus Torvalds 已提交
796
		/* unset the 7111 gpio register -- I don't know what this does exactly */
797
		saa7111a_call(mxb, core, s_gpio, 0);
798
		tuner_call(mxb, core, s_std, std);
L
Linus Torvalds 已提交
799
	} else {
800
		v4l2_std_id std = V4L2_STD_PAL_BG;
801

L
Linus Torvalds 已提交
802 803
		DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
		/* set the 7146 gpio register -- I don't know what this does exactly */
804
		saa7146_write(dev, GPIO_CTRL, 0x00404050);
L
Linus Torvalds 已提交
805
		/* set the 7111 gpio register -- I don't know what this does exactly */
806
		saa7111a_call(mxb, core, s_gpio, 1);
807
		tuner_call(mxb, core, s_std, std);
L
Linus Torvalds 已提交
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
	}
	return 0;
}

static struct saa7146_standard standard[] = {
	{
		.name	= "PAL-BG", 	.id	= V4L2_STD_PAL_BG,
		.v_offset	= 0x17,	.v_field 	= 288,
		.h_offset	= 0x14,	.h_pixels 	= 680,
		.v_max_out	= 576,	.h_max_out	= 768,
	}, {
		.name	= "PAL-I", 	.id	= V4L2_STD_PAL_I,
		.v_offset	= 0x17,	.v_field 	= 288,
		.h_offset	= 0x14,	.h_pixels 	= 680,
		.v_max_out	= 576,	.h_max_out	= 768,
	}, {
		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
		.v_offset	= 0x16,	.v_field 	= 240,
		.h_offset	= 0x06,	.h_pixels 	= 708,
		.v_max_out	= 480,	.h_max_out	= 640,
	}, {
		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
		.v_offset	= 0x14,	.v_field 	= 288,
		.h_offset	= 0x14,	.h_pixels 	= 720,
		.v_max_out	= 576,	.h_max_out	= 768,
	}
};

static struct saa7146_pci_extension_data mxb = {
837 838
	.ext_priv = "Multimedia eXtension Board",
	.ext = &extension,
L
Linus Torvalds 已提交
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
};

static struct pci_device_id pci_tbl[] = {
	{
		.vendor    = PCI_VENDOR_ID_PHILIPS,
		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,
		.subvendor = 0x0000,
		.subdevice = 0x0000,
		.driver_data = (unsigned long)&mxb,
	}, {
		.vendor	= 0,
	}
};

MODULE_DEVICE_TABLE(pci, pci_tbl);

static struct saa7146_ext_vv vv_data = {
	.inputs		= MXB_INPUTS,
	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
	.stds		= &standard[0],
	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
860
	.std_callback	= &std_callback,
L
Linus Torvalds 已提交
861 862 863 864 865
};

static struct saa7146_extension extension = {
	.name		= MXB_IDENTIFIER,
	.flags		= SAA7146_USE_I2C_IRQ,
866

L
Linus Torvalds 已提交
867 868 869 870 871 872 873 874 875
	.pci_tbl	= &pci_tbl[0],
	.module		= THIS_MODULE,

	.probe		= mxb_probe,
	.attach		= mxb_attach,
	.detach		= mxb_detach,

	.irq_mask	= 0,
	.irq_func	= NULL,
876
};
L
Linus Torvalds 已提交
877 878 879

static int __init mxb_init_module(void)
{
880
	if (saa7146_register_extension(&extension)) {
L
Linus Torvalds 已提交
881 882 883
		DEB_S(("failed to register extension.\n"));
		return -ENODEV;
	}
884

L
Linus Torvalds 已提交
885 886 887 888 889 890 891 892 893 894 895 896 897 898
	return 0;
}

static void __exit mxb_cleanup_module(void)
{
	saa7146_unregister_extension(&extension);
}

module_init(mxb_init_module);
module_exit(mxb_cleanup_module);

MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
MODULE_LICENSE("GPL");