ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / video / mxb.c
1 /*
2     mxb.c - v4l2 driver for the Multimedia eXtension Board
3     
4     Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
5
6     Visit http://www.mihu.de/linux/saa7146/mxb/
7     for further details about this card.
8     
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.
13
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.
18
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.
22 */
23
24 #define DEBUG_VARIABLE debug
25
26 #include <media/saa7146_vv.h>
27 #include <linux/video_decoder.h>        /* for saa7111a */
28
29 #include "mxb.h"
30 #include "tea6415c.h"
31 #include "tea6420.h"
32 #include "tda9840.h"
33 #include <media/tuner.h>
34
35 #define I2C_SAA7111A            0x24
36
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
63
64 #define MXB_BOARD_CAN_DO_VBI(dev)   (dev->revision != 0) 
65
66 /* global variable */
67 static int mxb_num = 0;
68
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");
75
76 static int debug = 0;
77 MODULE_PARM(debug,"i");
78 MODULE_PARM_DESC(debug, "debug verbosity");
79
80 #define MXB_INPUTS 4
81 enum { TUNER, AUX1, AUX3, AUX3_YC };
82
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 },
88 };
89
90 /* this array holds the information, which port of the saa7146 each
91    input actually uses. the mxb uses port 0 for every input */
92 static struct {
93         int hps_source;
94         int hps_sync;
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 },
100 };
101
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] =
105         { 0, 1, 3, 3 };
106
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] =
110                 { 
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 */
118                 };
119
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] =
123                 {
124                 {{2,3,0},{1,2,0}},
125                 {{5,3,0},{6,2,0}},
126                 {{4,3,0},{6,2,0}},
127                 {{3,3,0},{6,2,0}},
128                 {{2,3,0},{3,2,0}},
129                 {{2,3,0},{2,2,0}},
130                 {{6,3,0},{6,2,0}}       /* Mute */
131                 };
132
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 },
136 };
137
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 */    
153         { 0,                    0 }
154 };
155
156 struct mxb
157 {
158         struct video_device     video_dev;
159         struct video_device     vbi_dev;
160
161         struct i2c_adapter      i2c_adapter;    
162
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;
169
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 */
174 };
175
176 static struct saa7146_extension extension;
177
178 static int mxb_vbi_bypass(struct saa7146_dev* dev)
179 {
180         struct mxb* mxb = (struct mxb*)dev->ext_priv;
181         s32 byte = 0x0;
182         int result = 0;
183
184         DEB_EE(("dev:%p\n",dev));
185
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"));
190                 return -EFAULT;
191         }
192         byte = result;
193         byte &= 0xf0;
194         byte |= 0x0a;
195
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"));
198                 return -EFAULT;
199         }
200         return 0;
201 }
202
203 static int mxb_probe(struct saa7146_dev* dev)
204 {
205         struct mxb* mxb = 0;
206         struct i2c_client *client;
207         struct list_head *item;
208
209         request_module("tuner");
210         request_module("tea6420");
211         request_module("tea6415c");
212         request_module("tda9840");
213         request_module("saa7111");
214
215         mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);
216         if( NULL == mxb ) {
217                 DEB_D(("not enough kernel memory.\n"));
218                 return -ENOMEM;
219         }
220         memset(mxb, 0x0, sizeof(struct mxb));   
221
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));
225
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"));
229                 kfree(mxb);
230                 return -EFAULT;
231         }
232
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 ) 
247                         mxb->tuner = client;
248         }
249
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 ) {
253
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);
257                 kfree(mxb);
258                 return -ENODEV;
259         }
260
261         /* all devices are present, probe was successful */     
262
263         /* we store the pointer in our private data field */
264         dev->ext_priv = mxb;
265
266         return 0;
267 }
268
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 */
271 static struct {
272         int     length;
273         char    data[9];
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 } },
322         {-1, { 0} }
323 };
324
325 static unsigned char mxb_saa7111_init[25] = {
326         0x00,
327         
328         0x00,     /* 00 - ID byte */
329         0x00,     /* 01 - reserved */
330
331         /*front end */
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 */
336
337         /* decoder */
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 */
353         0x15,     /* 15 - VBI */
354         0x04,     /* 16 - VBI */
355         0x00,     /* 17 - VBI */
356 };
357
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)
363 {
364         struct mxb* mxb = (struct mxb*)dev->ext_priv;
365         
366         struct i2c_msg msg;
367
368         int i = 0, err = 0;
369         struct  tea6415c_multiplex vm;  
370
371         /* write configuration to saa7111a */
372         i = i2c_master_send(mxb->saa7111a, mxb_saa7111_init, sizeof(mxb_saa7111_init));
373         if (i < 0) {
374                 printk("failed to initialize saa7111a. this should never happen.\n");
375         }
376
377         /* select tuner-output on saa7111a */
378         i = 0;
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);
382
383         mxb_vbi_bypass(dev);
384
385         /* select a tuner type */
386         i = 5; 
387         mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE, &i);
388         
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]);
394
395         /* switch to tuner-channel on tea6415c*/
396         vm.out = 17;
397         vm.in  = 3;
398         mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
399
400         /* select tuner-output on multicable on tea6415c*/
401         vm.in  = 3;
402         vm.out = 13;
403         mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
404                                 
405         /* tune in some frequency on tuner */
406         mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &freq);
407
408         /* the rest for mxb */
409         mxb->cur_input = 0;
410         mxb->cur_freq = freq;
411         mxb->cur_mute = 1;
412
413         mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
414         mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
415                         
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
419            engineered. */
420         msg.addr = 0x1b;
421         msg.flags = 0;
422         msg.len = mxb_saa7740_init[0].length;
423         msg.buf = &mxb_saa7740_init[0].data[0];
424
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;
432                 for(i = 1;;i++) {
433                         if( -1 == mxb_saa7740_init[i].length ) {
434                                 break;
435                         }
436
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"));
441                                 goto err;
442                         }
443                 }
444                 INFO(("'sound arena module' detected.\n"));
445         }
446 err:    
447         /* the rest for saa7146: you should definitely set some basic values
448            for the input-port handling of the saa7146. */
449
450         /* ext->saa has been filled by the core driver */
451            
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);
454
455         /* some stuff is done via direct write to the registers */
456
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));
462
463         return 0;
464 }
465
466 /* interrupt-handler. this gets called when irq_mask is != 0.
467    it must clear the interrupt-bits in irq_mask it has handled */
468 /*
469 void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
470 {
471         struct mxb* mxb = (struct mxb*)dev->ext_priv;
472 }
473 */
474
475 static struct saa7146_ext_vv vv_data;
476
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)
479 {
480         struct mxb* mxb = (struct mxb*)dev->ext_priv;
481         
482         DEB_EE(("dev:%p\n",dev));
483
484         /* checking for i2c-devices can be omitted here, because we
485            already did this in "mxb_vl42_probe" */
486
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"));
490                 return -1;
491         }
492         
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"));
497                 }
498         }
499
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);
506
507         printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
508
509         mxb_num++;
510         mxb_init_done(dev);
511         return 0;
512 }
513
514 static int mxb_detach(struct saa7146_dev* dev)
515 {
516         struct mxb* mxb = (struct mxb*)dev->ext_priv;
517
518         DEB_EE(("dev:%p\n",dev));
519
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);
526
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);
530         }
531         saa7146_vv_release(dev);
532
533         mxb_num--;
534
535         i2c_del_adapter(&mxb->i2c_adapter);
536         kfree(mxb);
537
538         return 0;
539 }
540
541 /* hack: this should go into saa711x */
542 static int saa7111_set_gpio(struct saa7146_dev *dev, int bl)
543 {
544         struct mxb* mxb = (struct mxb*)dev->ext_priv;
545         s32 byte = 0x0;
546         int result = 0;
547         
548         DEB_EE(("dev:%p\n",dev));
549
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"));
553                 return -EFAULT;
554         }
555         
556         if( 0 == bl ) {
557                 byte &= 0x7f;
558         } else {
559                 byte |= 0x80;
560         }
561
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"));
565                 return -EFAULT;
566         }
567
568         return 0;
569 }
570
571 static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
572 {
573         struct saa7146_dev *dev = fh->dev;
574         struct mxb* mxb = (struct mxb*)dev->ext_priv;
575         struct saa7146_vv *vv = dev->vv_data; 
576         
577         switch(cmd) {
578         case VIDIOC_ENUMINPUT:
579         {
580                 struct v4l2_input *i = arg;
581                 
582                 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
583                 if( i->index < 0 || i->index >= MXB_INPUTS) {
584                         return -EINVAL;
585                 }
586                 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
587
588                 return 0;
589         }
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:
594         {
595                 struct v4l2_queryctrl *qc = arg;
596                 int i;
597
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));
602                                 return 0;
603                         }
604                 }
605                 return -EAGAIN;
606         }
607         case VIDIOC_G_CTRL:
608         {
609                 struct v4l2_control *vc = arg;
610                 int i;
611
612                 for (i = MAXCONTROLS - 1; i >= 0; i--) {
613                         if (mxb_controls[i].id == vc->id) {
614                                 break;
615                         }
616                 }
617                 
618                 if( i < 0 ) {
619                         return -EAGAIN;
620                 }
621                         
622                 switch (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));
626                                 return 0;
627                         }
628                 }
629                 
630                 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
631                 return 0;
632         }
633
634         case VIDIOC_S_CTRL:
635         {
636                 struct  v4l2_control    *vc = arg;
637                 int i = 0;
638                 
639                 for (i = MAXCONTROLS - 1; i >= 0; i--) {
640                         if (mxb_controls[i].id == vc->id) {
641                                 break;
642                         }
643                 }
644                 
645                 if( i < 0 ) {
646                         return -EAGAIN;
647                 }
648                 
649                 switch (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]);
656                                 } else {
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]);
659                                 }
660                                 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
661                                 break;
662                         }
663                 }
664                 return 0;
665         }
666         case VIDIOC_G_INPUT:
667         {
668                 int *input = (int *)arg;
669                 *input = mxb->cur_input;
670
671                 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
672                 return 0;               
673         }       
674         case VIDIOC_S_INPUT:
675         {
676                 int input = *(int *)arg;
677                 struct  tea6415c_multiplex vm;  
678                 int i = 0;
679
680                 DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
681
682                 if (input < 0 || input >= MXB_INPUTS) {
683                         return -EINVAL;
684                 }
685                 
686                 /* fixme: locke das setzen des inputs mit hilfe des mutexes
687                 down(&dev->lock);
688                 video_mux(dev,*i);
689                 up(&dev->lock);
690                 */
691                                 
692                 /* fixme: check if streaming capture
693                 if ( 0 != dev->streaming ) {
694                         DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
695                         return -EPERM;
696                 }
697                 */
698                 
699                 mxb->cur_input = input;
700         
701                 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
702                 
703                 /* prepare switching of tea6415c and saa7111a;
704                    have a look at the 'background'-file for further informations  */
705                 switch( input ) {
706                         
707                         case TUNER:
708                         {
709                                 i = 0;
710                                 vm.in  = 3;
711                                 vm.out = 17;
712                                                                 
713                         if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
714                                         printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
715                                         return -EFAULT;
716                                 }
717                                 /* connect tuner-output always to multicable */
718                                 vm.in  = 3;
719                                 vm.out = 13;
720                                 break;                          
721                         }
722                         case AUX3_YC:
723                         {
724                                 /* nothing to be done here. aux3_yc is
725                                    directly connected to the saa711a */
726                                 i = 5;
727                                 break;
728                         }
729                         case AUX3:
730                         {
731                                 /* nothing to be done here. aux3 is
732                                    directly connected to the saa711a */
733                                 i = 1;
734                                 break;
735                         }
736                         case AUX1:
737                         {
738                                 i = 0;
739                                 vm.in  = 1;
740                                 vm.out = 17;
741                                 break;
742                         }
743                 }
744
745                 /* switch video in tea6415c only if necessary */
746                 switch( input ) {
747                         case TUNER:
748                         case AUX1:
749                         {
750                                 if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
751                                         printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
752                                         return -EFAULT;
753                                 }
754                                 break;
755                         }
756                         default:
757                         {
758                                 break;
759                         }
760                 }
761                                 
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");
765                 }                       
766
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]);
771                 }
772
773                 return 0;
774         }
775         case VIDIOC_G_TUNER:
776         {
777                 struct v4l2_tuner *t = arg;
778                 int byte = 0;
779
780                 if( 0 != t->index ) {
781                         DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
782                         return -EINVAL;
783                 }
784
785                 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
786
787                 memset(t,0,sizeof(*t));
788                 strcpy(t->name, "Television");
789
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 */
795                 t->signal = 0xffff;
796                 t->afc = 0;             
797
798                 byte = mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, NULL);
799                 t->audmode = mxb->cur_mode;
800                 
801                 if( byte < 0 ) {
802                         t->rxsubchans  = V4L2_TUNER_SUB_MONO;
803                 } else {
804                         switch(byte) {
805                                 case TDA9840_MONO_DETECT: {
806                                         t->rxsubchans   = V4L2_TUNER_SUB_MONO;
807                                         DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
808                                         break;
809                                 }
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"));
813                                         break;
814                                 }
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"));
818                                         break;
819                                 }
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"));
823                                         break;
824                                 }
825                         }
826                 }
827
828                 return 0;
829         }
830         case VIDIOC_S_TUNER:
831         {
832                 struct v4l2_tuner *t = arg;
833                 int result = 0;
834                 int byte = 0;
835                 
836                 if( 0 != t->index ) {
837                         DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
838                         return -EINVAL;
839                 }
840         
841                 switch(t->audmode) {
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"));
846                                 break;
847                         }
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"));
852                                 break;
853                         }
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"));
858                                 break;
859                         }
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"));
864                                 break;
865                         }
866                 }
867
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);
870                 }
871                                 
872                 return 0;
873         }
874         case VIDIOC_G_FREQUENCY:
875         {
876                 struct v4l2_frequency *f = arg;
877
878                 if(0 != mxb->cur_input) {
879                         DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
880                         return -EINVAL;
881                 }
882
883                 memset(f,0,sizeof(*f));
884                 f->type = V4L2_TUNER_ANALOG_TV;
885                 f->frequency =  mxb->cur_freq;
886
887                 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq));
888                 return 0;
889         }
890         case VIDIOC_S_FREQUENCY:
891         {
892                 struct v4l2_frequency *f = arg;
893                 int t_locked = 0;
894                 int v_byte = 0;
895
896                 if (0 != f->tuner)
897                         return -EINVAL;
898
899                 if (V4L2_TUNER_ANALOG_TV != f->type)
900                         return -EINVAL;
901                 
902                 if(0 != mxb->cur_input) {
903                         DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
904                         return -EINVAL;
905                 }
906
907                 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency));
908
909                 mxb->cur_freq = f->frequency;
910
911                 /* tune in desired frequency */                 
912                 mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &mxb->cur_freq);
913
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);
917
918                 /* not locked -- anything to do here ? */
919                 if( 0 == t_locked || 0 == (v_byte & DECODER_STATUS_GOOD)) {
920                 }
921
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);
926
927                 return 0;
928         }
929         case MXB_S_AUDIO_CD:
930         {
931                 int i = *(int*)arg;
932                                 
933                 if( i < 0 || i >= MXB_AUDIOS ) {
934                         DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
935                         return -EINVAL;
936                 }
937                 
938                 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
939
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]);
942
943                 return 0;
944         }
945         case MXB_S_AUDIO_LINE:
946         {
947                 int i = *(int*)arg;
948                                 
949                 if( i < 0 || i >= MXB_AUDIOS ) {
950                         DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
951                         return -EINVAL;
952                 }
953                 
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]);
957
958                 return 0;
959         }
960         case VIDIOC_G_AUDIO:
961         {
962                 struct v4l2_audio *a = arg;
963
964                 if( a->index < 0 || a->index > MXB_INPUTS ) {
965                         DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
966                         return -EINVAL;
967                 }
968                 
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));
971                 
972                 return 0;
973         }
974         case VIDIOC_S_AUDIO:
975         {
976                 struct v4l2_audio *a = arg;
977                 DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
978                 return 0;
979         }       
980         default:
981 /*
982                 DEB2(printk("does not handle this ioctl.\n"));
983 */
984                 return -ENOIOCTLCMD;
985         }
986         return 0;
987 }
988
989 static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
990 {
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);
997         } else {
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);
1003         }
1004         return 0;
1005 }
1006
1007 static struct saa7146_standard standard[] = {
1008         {
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,
1013         }, {
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,
1018         }, {
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,
1023         }, {
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,
1028         }
1029 };
1030
1031 static struct saa7146_pci_extension_data mxb = {
1032         .ext_priv = "Multimedia eXtension Board",
1033         .ext = &extension,
1034 };
1035
1036 static struct pci_device_id pci_tbl[] = {
1037         {
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,
1043         }, {
1044                 .vendor = 0,
1045         }
1046 };
1047
1048 MODULE_DEVICE_TABLE(pci, pci_tbl);
1049
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],
1057         .ioctl          = mxb_ioctl,
1058 };
1059
1060 static struct saa7146_extension extension = {
1061         .name           = MXB_IDENTIFIER,
1062         .flags          = SAA7146_USE_I2C_IRQ,
1063         
1064         .pci_tbl        = &pci_tbl[0],
1065         .module         = THIS_MODULE,
1066
1067         .probe          = mxb_probe,
1068         .attach         = mxb_attach,
1069         .detach         = mxb_detach,
1070
1071         .irq_mask       = 0,
1072         .irq_func       = NULL,
1073 };      
1074
1075 int __init mxb_init_module(void) 
1076 {
1077         if( 0 != saa7146_register_extension(&extension)) {
1078                 DEB_S(("failed to register extension.\n"));
1079                 return -ENODEV;
1080         }
1081         
1082         return 0;
1083 }
1084
1085 void __exit mxb_cleanup_module(void) 
1086 {
1087         saa7146_unregister_extension(&extension);
1088 }
1089
1090 module_init(mxb_init_module);
1091 module_exit(mxb_cleanup_module);
1092
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");