2 mxb.c - v4l2 driver for the Multimedia eXtension Board
4 Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
6 Visit http://www.mihu.de/linux/saa7146/mxb/
7 for further details about this card.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DEBUG_VARIABLE debug
26 #include <media/saa7146_vv.h>
27 #include <linux/video_decoder.h> /* for saa7111a */
33 #include <media/tuner.h>
35 #define I2C_SAA7111A 0x24
37 /* All unused bytes are reserverd. */
38 #define SAA711X_CHIP_VERSION 0x00
39 #define SAA711X_ANALOG_INPUT_CONTROL_1 0x02
40 #define SAA711X_ANALOG_INPUT_CONTROL_2 0x03
41 #define SAA711X_ANALOG_INPUT_CONTROL_3 0x04
42 #define SAA711X_ANALOG_INPUT_CONTROL_4 0x05
43 #define SAA711X_HORIZONTAL_SYNC_START 0x06
44 #define SAA711X_HORIZONTAL_SYNC_STOP 0x07
45 #define SAA711X_SYNC_CONTROL 0x08
46 #define SAA711X_LUMINANCE_CONTROL 0x09
47 #define SAA711X_LUMINANCE_BRIGHTNESS 0x0A
48 #define SAA711X_LUMINANCE_CONTRAST 0x0B
49 #define SAA711X_CHROMA_SATURATION 0x0C
50 #define SAA711X_CHROMA_HUE_CONTROL 0x0D
51 #define SAA711X_CHROMA_CONTROL 0x0E
52 #define SAA711X_FORMAT_DELAY_CONTROL 0x10
53 #define SAA711X_OUTPUT_CONTROL_1 0x11
54 #define SAA711X_OUTPUT_CONTROL_2 0x12
55 #define SAA711X_OUTPUT_CONTROL_3 0x13
56 #define SAA711X_V_GATE_1_START 0x15
57 #define SAA711X_V_GATE_1_STOP 0x16
58 #define SAA711X_V_GATE_1_MSB 0x17
59 #define SAA711X_TEXT_SLICER_STATUS 0x1A
60 #define SAA711X_DECODED_BYTES_OF_TS_1 0x1B
61 #define SAA711X_DECODED_BYTES_OF_TS_2 0x1C
62 #define SAA711X_STATUS_BYTE 0x1F
64 #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
67 static int mxb_num = 0;
69 /* initial frequence the tuner will be tuned to.
70 in verden (lower saxony, germany) 4148 is a
71 channel called "phoenix" */
72 static int freq = 4148;
73 MODULE_PARM(freq,"i");
74 MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
77 MODULE_PARM(debug,"i");
78 MODULE_PARM_DESC(debug, "debug verbosity");
81 enum { TUNER, AUX1, AUX3, AUX3_YC };
83 static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
84 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
85 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
86 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
87 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
90 /* this array holds the information, which port of the saa7146 each
91 input actually uses. the mxb uses port 0 for every input */
95 } input_port_selection[MXB_INPUTS] = {
96 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
97 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
98 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
99 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
102 /* this array holds the information of the audio source (mxb_audios),
103 which has to be switched corresponding to the video source (mxb_channels) */
104 static int video_audio_connect[MXB_INPUTS] =
107 /* these are the necessary input-output-pins for bringing one audio source
108 (see above) to the CD-output */
109 static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =
111 {{1,1,0},{1,1,0}}, /* Tuner */
112 {{5,1,0},{6,1,0}}, /* AUX 1 */
113 {{4,1,0},{6,1,0}}, /* AUX 2 */
114 {{3,1,0},{6,1,0}}, /* AUX 3 */
115 {{1,1,0},{3,1,0}}, /* Radio */
116 {{1,1,0},{2,1,0}}, /* CD-Rom */
117 {{6,1,0},{6,1,0}} /* Mute */
120 /* these are the necessary input-output-pins for bringing one audio source
121 (see above) to the line-output */
122 static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =
130 {{6,3,0},{6,2,0}} /* Mute */
133 #define MAXCONTROLS 1
134 static struct v4l2_queryctrl mxb_controls[] = {
135 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
138 static struct saa7146_extension_ioctls ioctls[] = {
139 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
140 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
141 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
142 { VIDIOC_QUERYCTRL, SAA7146_BEFORE },
143 { VIDIOC_G_CTRL, SAA7146_BEFORE },
144 { VIDIOC_S_CTRL, SAA7146_BEFORE },
145 { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE },
146 { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
147 { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE },
148 { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE },
149 { VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
150 { VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
151 { MXB_S_AUDIO_CD, SAA7146_EXCLUSIVE }, /* custom control */
152 { MXB_S_AUDIO_LINE, SAA7146_EXCLUSIVE }, /* custom control */
158 struct video_device video_dev;
159 struct video_device vbi_dev;
161 struct i2c_adapter i2c_adapter;
163 struct i2c_client* saa7111a;
164 struct i2c_client* tda9840;
165 struct i2c_client* tea6415c;
166 struct i2c_client* tuner;
167 struct i2c_client* tea6420_1;
168 struct i2c_client* tea6420_2;
170 int cur_mode; /* current audio mode (mono, stereo, ...) */
171 int cur_input; /* current input */
172 int cur_freq; /* current frequency the tuner is tuned to */
173 int cur_mute; /* current mute status */
176 static struct saa7146_extension extension;
178 static int mxb_vbi_bypass(struct saa7146_dev* dev)
180 struct mxb* mxb = (struct mxb*)dev->ext_priv;
184 DEB_EE(("dev:%p\n",dev));
186 /* switch bypass in saa7111a, this should be done in the
187 saa7111a driver of course... */
188 if ( -1 == (result = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3))) {
189 DEB_D(("could not read from saa7111a.\n"));
196 if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3, byte))) {
197 DEB_D(("could not write to saa7111a.\n"));
203 static int mxb_probe(struct saa7146_dev* dev)
206 struct i2c_client *client;
207 struct list_head *item;
209 request_module("tuner");
210 request_module("tea6420");
211 request_module("tea6415c");
212 request_module("tda9840");
213 request_module("saa7111");
215 mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);
217 DEB_D(("not enough kernel memory.\n"));
220 memset(mxb, 0x0, sizeof(struct mxb));
222 /* FIXME: enable i2c-port pins, video-port-pins
223 video port pins should be enabled here ?! */
224 saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
226 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, I2C_ADAP_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
227 if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
228 DEB_S(("cannot register i2c-device. skipping.\n"));
233 /* loop through all i2c-devices on the bus and look who is there */
234 list_for_each(item,&mxb->i2c_adapter.clients) {
235 client = list_entry(item, struct i2c_client, list);
236 if( I2C_TEA6420_1 == client->addr )
237 mxb->tea6420_1 = client;
238 if( I2C_TEA6420_2 == client->addr )
239 mxb->tea6420_2 = client;
240 if( I2C_TEA6415C_2 == client->addr )
241 mxb->tea6415c = client;
242 if( I2C_TDA9840 == client->addr )
243 mxb->tda9840 = client;
244 if( I2C_SAA7111A == client->addr )
245 mxb->saa7111a = client;
246 if( 0x60 == client->addr )
250 /* check if all devices are present */
251 if( 0 == mxb->tea6420_1 || 0 == mxb->tea6420_2 || 0 == mxb->tea6415c
252 || 0 == mxb->tda9840 || 0 == mxb->saa7111a || 0 == mxb->tuner ) {
254 printk("mxb: did not find all i2c devices. are you sure you\n");
255 printk("mxb: insmod'ed tea6420, tea6415c, saa7111, tea6415c and tuner?\n");
256 i2c_del_adapter(&mxb->i2c_adapter);
261 /* all devices are present, probe was successful */
263 /* we store the pointer in our private data field */
269 /* some init data for the saa7740, the so-called 'sound arena module'.
270 there are no specs available, so we simply use some init values */
274 } mxb_saa7740_init[] = {
275 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
276 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
277 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
278 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
279 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
280 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
281 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
282 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
283 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
284 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
285 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
286 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
287 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
288 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
289 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
290 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
291 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
292 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
293 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
294 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
295 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
296 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
297 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
298 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
299 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
300 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
301 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
302 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
303 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
304 { 3, { 0x48, 0x00, 0x01 } },
305 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
306 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
307 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
308 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
309 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
310 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
311 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
312 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
313 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
314 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
315 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
316 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
317 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
318 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
319 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
320 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
321 { 3, { 0x80, 0xb3, 0x0a } },
325 static unsigned char mxb_saa7111_init[25] = {
328 0x00, /* 00 - ID byte */
329 0x00, /* 01 - reserved */
332 0xd8, /* 02 - FUSE=x, GUDL=x, MODE=x */
333 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
334 0x00, /* 04 - GAI1=256 */
335 0x00, /* 05 - GAI2=256 */
338 0xf0, /* 06 - HSB at xx(50Hz) / xx(60Hz) pixels after end of last line */
339 0x30, /* 07 - HSS at xx(50Hz) / xx(60Hz) pixels after end of last line */
340 0xa8, /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */
341 0x02, /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */
342 0x80, /* 0a - BRIG=128 */
343 0x47, /* 0b - CONT=1.109 */
344 0x40, /* 0c - SATN=1.0 */
345 0x00, /* 0d - HUE=0 */
346 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
347 0x00, /* 0f - reserved */
348 0xd0, /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */
349 0x8c, /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
350 0x80, /* 12 - xx output control 2 */
351 0x30, /* 13 - xx output control 3 */
352 0x00, /* 14 - reserved */
358 /* bring hardware to a sane state. this has to be done, just in case someone
359 wants to capture from this device before it has been properly initialized.
360 the capture engine would badly fail, because no valid signal arrives on the
361 saa7146, thus leading to timeouts and stuff. */
362 static int mxb_init_done(struct saa7146_dev* dev)
364 struct mxb* mxb = (struct mxb*)dev->ext_priv;
369 struct tea6415c_multiplex vm;
371 /* write configuration to saa7111a */
372 i = i2c_master_send(mxb->saa7111a, mxb_saa7111_init, sizeof(mxb_saa7111_init));
374 printk("failed to initialize saa7111a. this should never happen.\n");
377 /* select tuner-output on saa7111a */
379 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i);
380 // i = VIDEO_MODE_PAL;
381 // mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);
385 /* select a tuner type */
387 mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE, &i);
389 /* mute audio on tea6420s */
390 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
391 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
392 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]);
393 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]);
395 /* switch to tuner-channel on tea6415c*/
398 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
400 /* select tuner-output on multicable on tea6415c*/
403 mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
405 /* tune in some frequency on tuner */
406 mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &freq);
408 /* the rest for mxb */
410 mxb->cur_freq = freq;
413 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
414 mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
416 /* check if the saa7740 (aka 'sound arena module') is present
417 on the mxb. if so, we must initialize it. due to lack of
418 informations about the saa7740, the values were reverse
422 msg.len = mxb_saa7740_init[0].length;
423 msg.buf = &mxb_saa7740_init[0].data[0];
425 if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
426 /* the sound arena module is a pos, that's probably the reason
427 philips refuses to hand out a datasheet for the saa7740...
428 it seems to screw up the i2c bus, so we disable fast irq
429 based i2c transactions here and rely on the slow and safe
430 polling method ... */
431 extension.flags &= ~SAA7146_USE_I2C_IRQ;
433 if( -1 == mxb_saa7740_init[i].length ) {
437 msg.len = mxb_saa7740_init[i].length;
438 msg.buf = &mxb_saa7740_init[i].data[0];
439 if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
440 DEB_D(("failed to initialize 'sound arena module'.\n"));
444 INFO(("'sound arena module' detected.\n"));
447 /* the rest for saa7146: you should definitely set some basic values
448 for the input-port handling of the saa7146. */
450 /* ext->saa has been filled by the core driver */
452 /* some stuff is done via variables */
453 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync);
455 /* some stuff is done via direct write to the registers */
457 /* this is ugly, but because of the fact that this is completely
458 hardware dependend, it should be done directly... */
459 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
460 saa7146_write(dev, DD1_INIT, 0x02000200);
461 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
466 /* interrupt-handler. this gets called when irq_mask is != 0.
467 it must clear the interrupt-bits in irq_mask it has handled */
469 void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
471 struct mxb* mxb = (struct mxb*)dev->ext_priv;
475 static struct saa7146_ext_vv vv_data;
477 /* this function only gets called when the probing was successful */
478 static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
480 struct mxb* mxb = (struct mxb*)dev->ext_priv;
482 DEB_EE(("dev:%p\n",dev));
484 /* checking for i2c-devices can be omitted here, because we
485 already did this in "mxb_vl42_probe" */
487 saa7146_vv_init(dev,&vv_data);
488 if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
489 ERR(("cannot register capture v4l2 device. skipping.\n"));
493 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
494 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
495 if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
496 ERR(("cannot register vbi v4l2 device. skipping.\n"));
500 i2c_use_client(mxb->tea6420_1);
501 i2c_use_client(mxb->tea6420_2);
502 i2c_use_client(mxb->tea6415c);
503 i2c_use_client(mxb->tda9840);
504 i2c_use_client(mxb->saa7111a);
505 i2c_use_client(mxb->tuner);
507 printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
514 static int mxb_detach(struct saa7146_dev* dev)
516 struct mxb* mxb = (struct mxb*)dev->ext_priv;
518 DEB_EE(("dev:%p\n",dev));
520 i2c_release_client(mxb->tea6420_1);
521 i2c_release_client(mxb->tea6420_2);
522 i2c_release_client(mxb->tea6415c);
523 i2c_release_client(mxb->tda9840);
524 i2c_release_client(mxb->saa7111a);
525 i2c_release_client(mxb->tuner);
527 saa7146_unregister_device(&mxb->video_dev,dev);
528 if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
529 saa7146_unregister_device(&mxb->vbi_dev,dev);
531 saa7146_vv_release(dev);
535 i2c_del_adapter(&mxb->i2c_adapter);
541 /* hack: this should go into saa711x */
542 static int saa7111_set_gpio(struct saa7146_dev *dev, int bl)
544 struct mxb* mxb = (struct mxb*)dev->ext_priv;
548 DEB_EE(("dev:%p\n",dev));
550 /* get the old register contents */
551 if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1))) {
552 DEB_D(("could not read from saa711x\n"));
562 /* write register contents back */
563 if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1, byte))) {
564 DEB_D(("could not write to saa711x\n"));
571 static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
573 struct saa7146_dev *dev = fh->dev;
574 struct mxb* mxb = (struct mxb*)dev->ext_priv;
575 struct saa7146_vv *vv = dev->vv_data;
578 case VIDIOC_ENUMINPUT:
580 struct v4l2_input *i = arg;
582 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
583 if( i->index < 0 || i->index >= MXB_INPUTS) {
586 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
590 /* the saa7146 provides some controls (brightness, contrast, saturation)
591 which gets registered *after* this function. because of this we have
592 to return with a value != 0 even if the function succeded.. */
593 case VIDIOC_QUERYCTRL:
595 struct v4l2_queryctrl *qc = arg;
598 for (i = MAXCONTROLS - 1; i >= 0; i--) {
599 if (mxb_controls[i].id == qc->id) {
600 *qc = mxb_controls[i];
601 DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id));
609 struct v4l2_control *vc = arg;
612 for (i = MAXCONTROLS - 1; i >= 0; i--) {
613 if (mxb_controls[i].id == vc->id) {
623 case V4L2_CID_AUDIO_MUTE: {
624 vc->value = mxb->cur_mute;
625 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
630 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
636 struct v4l2_control *vc = arg;
639 for (i = MAXCONTROLS - 1; i >= 0; i--) {
640 if (mxb_controls[i].id == vc->id) {
650 case V4L2_CID_AUDIO_MUTE: {
651 mxb->cur_mute = vc->value;
652 if( 0 == vc->value ) {
653 /* switch the audio-source */
654 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
655 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
657 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
658 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
660 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
668 int *input = (int *)arg;
669 *input = mxb->cur_input;
671 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
676 int input = *(int *)arg;
677 struct tea6415c_multiplex vm;
680 DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
682 if (input < 0 || input >= MXB_INPUTS) {
686 /* fixme: locke das setzen des inputs mit hilfe des mutexes
692 /* fixme: check if streaming capture
693 if ( 0 != dev->streaming ) {
694 DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
699 mxb->cur_input = input;
701 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
703 /* prepare switching of tea6415c and saa7111a;
704 have a look at the 'background'-file for further informations */
713 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
714 printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
717 /* connect tuner-output always to multicable */
724 /* nothing to be done here. aux3_yc is
725 directly connected to the saa711a */
731 /* nothing to be done here. aux3 is
732 directly connected to the saa711a */
745 /* switch video in tea6415c only if necessary */
750 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
751 printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
762 /* switch video in saa7111a */
763 if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) {
764 printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
767 /* switch the audio-source only if necessary */
768 if( 0 == mxb->cur_mute ) {
769 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]);
770 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]);
777 struct v4l2_tuner *t = arg;
780 if( 0 != t->index ) {
781 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
785 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
787 memset(t,0,sizeof(*t));
788 strcpy(t->name, "Television");
790 t->type = V4L2_TUNER_ANALOG_TV;
791 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
792 t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
793 t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */
794 /* FIXME: add the real signal strength here */
798 byte = mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, NULL);
799 t->audmode = mxb->cur_mode;
802 t->rxsubchans = V4L2_TUNER_SUB_MONO;
805 case TDA9840_MONO_DETECT: {
806 t->rxsubchans = V4L2_TUNER_SUB_MONO;
807 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
810 case TDA9840_DUAL_DETECT: {
811 t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
812 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n"));
815 case TDA9840_STEREO_DETECT: {
816 t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
817 DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n"));
820 default: { /* TDA9840_INCORRECT_DETECT */
821 t->rxsubchans = V4L2_TUNER_MODE_MONO;
822 DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n"));
832 struct v4l2_tuner *t = arg;
836 if( 0 != t->index ) {
837 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
842 case V4L2_TUNER_MODE_STEREO: {
843 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
844 byte = TDA9840_SET_STEREO;
845 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
848 case V4L2_TUNER_MODE_LANG1: {
849 mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
850 byte = TDA9840_SET_LANG1;
851 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
854 case V4L2_TUNER_MODE_LANG2: {
855 mxb->cur_mode = V4L2_TUNER_MODE_LANG2;
856 byte = TDA9840_SET_LANG2;
857 DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
860 default: { /* case V4L2_TUNER_MODE_MONO: {*/
861 mxb->cur_mode = V4L2_TUNER_MODE_MONO;
862 byte = TDA9840_SET_MONO;
863 DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
868 if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) {
869 printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte);
874 case VIDIOC_G_FREQUENCY:
876 struct v4l2_frequency *f = arg;
878 if(0 != mxb->cur_input) {
879 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
883 memset(f,0,sizeof(*f));
884 f->type = V4L2_TUNER_ANALOG_TV;
885 f->frequency = mxb->cur_freq;
887 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq));
890 case VIDIOC_S_FREQUENCY:
892 struct v4l2_frequency *f = arg;
899 if (V4L2_TUNER_ANALOG_TV != f->type)
902 if(0 != mxb->cur_input) {
903 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
907 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency));
909 mxb->cur_freq = f->frequency;
911 /* tune in desired frequency */
912 mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &mxb->cur_freq);
914 /* check if pll of tuner & saa7111a is locked */
915 // mxb->tuner->driver->command(mxb->tuner,TUNER_IS_LOCKED, &t_locked);
916 mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_GET_STATUS, &v_byte);
918 /* not locked -- anything to do here ? */
919 if( 0 == t_locked || 0 == (v_byte & DECODER_STATUS_GOOD)) {
922 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
923 spin_lock(&dev->slock);
924 vv->vbi_fieldcount = 0;
925 spin_unlock(&dev->slock);
933 if( i < 0 || i >= MXB_AUDIOS ) {
934 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
938 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
940 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]);
941 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]);
945 case MXB_S_AUDIO_LINE:
949 if( i < 0 || i >= MXB_AUDIOS ) {
950 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
954 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i));
955 mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]);
956 mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]);
962 struct v4l2_audio *a = arg;
964 if( a->index < 0 || a->index > MXB_INPUTS ) {
965 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
969 DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index));
970 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
976 struct v4l2_audio *a = arg;
977 DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
982 DEB2(printk("does not handle this ioctl.\n"));
989 static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
991 if(V4L2_STD_PAL_I == std->id ) {
992 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
993 /* set the 7146 gpio register -- I don't know what this does exactly */
994 saa7146_write(dev, GPIO_CTRL, 0x00404050);
995 /* unset the 7111 gpio register -- I don't know what this does exactly */
996 saa7111_set_gpio(dev,0);
998 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
999 /* set the 7146 gpio register -- I don't know what this does exactly */
1000 saa7146_write(dev, GPIO_CTRL, 0x00404050);
1001 /* set the 7111 gpio register -- I don't know what this does exactly */
1002 saa7111_set_gpio(dev,1);
1007 static struct saa7146_standard standard[] = {
1009 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
1010 .v_offset = 0x17, .v_field = 288,
1011 .h_offset = 0x14, .h_pixels = 680,
1012 .v_max_out = 576, .h_max_out = 768,
1014 .name = "PAL-I", .id = V4L2_STD_PAL_I,
1015 .v_offset = 0x17, .v_field = 288,
1016 .h_offset = 0x14, .h_pixels = 680,
1017 .v_max_out = 576, .h_max_out = 768,
1019 .name = "NTSC", .id = V4L2_STD_NTSC,
1020 .v_offset = 0x16, .v_field = 240,
1021 .h_offset = 0x06, .h_pixels = 708,
1022 .v_max_out = 480, .h_max_out = 640,
1024 .name = "SECAM", .id = V4L2_STD_SECAM,
1025 .v_offset = 0x14, .v_field = 288,
1026 .h_offset = 0x14, .h_pixels = 720,
1027 .v_max_out = 576, .h_max_out = 768,
1031 static struct saa7146_pci_extension_data mxb = {
1032 .ext_priv = "Multimedia eXtension Board",
1036 static struct pci_device_id pci_tbl[] = {
1038 .vendor = PCI_VENDOR_ID_PHILIPS,
1039 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
1040 .subvendor = 0x0000,
1041 .subdevice = 0x0000,
1042 .driver_data = (unsigned long)&mxb,
1048 MODULE_DEVICE_TABLE(pci, pci_tbl);
1050 static struct saa7146_ext_vv vv_data = {
1051 .inputs = MXB_INPUTS,
1052 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
1053 .stds = &standard[0],
1054 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
1055 .std_callback = &std_callback,
1056 .ioctls = &ioctls[0],
1060 static struct saa7146_extension extension = {
1061 .name = MXB_IDENTIFIER,
1062 .flags = SAA7146_USE_I2C_IRQ,
1064 .pci_tbl = &pci_tbl[0],
1065 .module = THIS_MODULE,
1068 .attach = mxb_attach,
1069 .detach = mxb_detach,
1075 int __init mxb_init_module(void)
1077 if( 0 != saa7146_register_extension(&extension)) {
1078 DEB_S(("failed to register extension.\n"));
1085 void __exit mxb_cleanup_module(void)
1087 saa7146_unregister_extension(&extension);
1090 module_init(mxb_init_module);
1091 module_exit(mxb_cleanup_module);
1093 MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
1094 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
1095 MODULE_LICENSE("GPL");