Subversion Repositories shark

Rev

Rev 425 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
425 giacomo 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
        int i = 0;     
207
 
208
        request_module("tuner");
209
        request_module("tea6420");
210
        request_module("tea6415c");
211
        request_module("tda9840");
212
        request_module("saa7111");
213
 
214
        mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);
215
        if( NULL == mxb ) {
216
                DEB_D(("not enough kernel memory.\n"));
217
                return -ENOMEM;
218
        }
219
        memset(mxb, 0x0, sizeof(struct mxb));  
220
 
221
        saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
222
        if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
223
                DEB_S(("cannot register i2c-device. skipping.\n"));
224
                kfree(mxb);
225
                return -EFAULT;
226
        }
227
 
228
        /* loop through all i2c-devices on the bus and look who is there */
229
        for(i = 0; i < I2C_CLIENT_MAX; i++) {
230
                if( NULL == mxb->i2c_adapter.clients[i] ) {
231
                        continue;
232
                }
233
                if( I2C_TEA6420_1 == mxb->i2c_adapter.clients[i]->addr )
234
                        mxb->tea6420_1 = mxb->i2c_adapter.clients[i];
235
                if( I2C_TEA6420_2 == mxb->i2c_adapter.clients[i]->addr )
236
                        mxb->tea6420_2 = mxb->i2c_adapter.clients[i];
237
                if( I2C_TEA6415C_2 == mxb->i2c_adapter.clients[i]->addr )
238
                        mxb->tea6415c = mxb->i2c_adapter.clients[i];
239
                if( I2C_TDA9840 == mxb->i2c_adapter.clients[i]->addr )
240
                        mxb->tda9840 = mxb->i2c_adapter.clients[i];
241
                if( I2C_SAA7111A == mxb->i2c_adapter.clients[i]->addr )
242
                        mxb->saa7111a = mxb->i2c_adapter.clients[i];
243
                if( 0x60 == mxb->i2c_adapter.clients[i]->addr )
244
                        mxb->tuner = mxb->i2c_adapter.clients[i];
245
        }
246
 
247
        /* check if all devices are present */
248
        if(    0 == mxb->tea6420_1      || 0 == mxb->tea6420_2  || 0 == mxb->tea6415c
249
            || 0 == mxb->tda9840        || 0 == mxb->saa7111a   || 0 == mxb->tuner ) {
250
 
251
                printk("mxb: did not find all i2c devices. are you sure you\n");
252
                printk("mxb: insmod'ed tea6420, tea6415c, saa7111, tea6415c and tuner?\n");
253
                i2c_del_adapter(&mxb->i2c_adapter);
254
                kfree(mxb);
255
                return -ENODEV;
256
        }
257
 
258
        /* all devices are present, probe was successful */    
259
 
260
        /* we store the pointer in our private data field */
261
        (struct mxb*)dev->ext_priv = mxb;
262
 
263
        return 0;
264
}
265
 
266
/* some init data for the saa7740, the so-called 'sound arena module'.
267
   there are no specs available, so we simply use some init values */
268
static struct {
269
        int     length;
270
        char    data[9];
271
} mxb_saa7740_init[] = {
272
        { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
273
        { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
274
        { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
275
        { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
276
        { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
277
        { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
278
        { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
279
        { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
280
        { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
281
        { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
282
        { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
283
        { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
284
        { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
285
        { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
286
        { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
287
        { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
288
        { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
289
        { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
290
        { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
291
        { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
292
        { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
293
        { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
294
        { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
295
        { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
296
        { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
297
        { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
298
        { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
299
        { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
300
        { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
301
        { 3, { 0x48, 0x00, 0x01 } },
302
        { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
303
        { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
304
        { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
305
        { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
306
        { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
307
        { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
308
        { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
309
        { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
310
        { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
311
        { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
312
        { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
313
        { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
314
        { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
315
        { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
316
        { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
317
        { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
318
        { 3, { 0x80, 0xb3, 0x0a } },
319
        {-1, { 0} }
320
};
321
 
322
static unsigned char mxb_saa7111_init[25] = {
323
        0x00,
324
 
325
        0x00,     /* 00 - ID byte */
326
        0x00,     /* 01 - reserved */
327
 
328
        /*front end */
329
        0xd8,     /* 02 - FUSE=x, GUDL=x, MODE=x */
330
        0x23,     /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
331
        0x00,     /* 04 - GAI1=256 */
332
        0x00,     /* 05 - GAI2=256 */
333
 
334
        /* decoder */
335
        0xf0,     /* 06 - HSB at  xx(50Hz) /  xx(60Hz) pixels after end of last line */
336
        0x30,     /* 07 - HSS at  xx(50Hz) /  xx(60Hz) pixels after end of last line */
337
        0xa8,     /* 08 - AUFD=x, FSEL=x, EXFIL=x, VTRC=x, HPLL=x, VNOI=x */
338
        0x02,     /* 09 - BYPS=x, PREF=x, BPSS=x, VBLB=x, UPTCV=x, APER=x */
339
        0x80,     /* 0a - BRIG=128 */
340
        0x47,     /* 0b - CONT=1.109 */
341
        0x40,     /* 0c - SATN=1.0 */
342
        0x00,     /* 0d - HUE=0 */
343
        0x01,     /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
344
        0x00,     /* 0f - reserved */
345
        0xd0,     /* 10 - OFTS=x, HDEL=x, VRLN=x, YDEL=x */
346
        0x8c,     /* 11 - GPSW=x, CM99=x, FECO=x, COMPO=x, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
347
        0x80,     /* 12 - xx output control 2 */
348
        0x30,     /* 13 - xx output control 3 */
349
        0x00,     /* 14 - reserved */
350
        0x15,     /* 15 - VBI */
351
        0x04,     /* 16 - VBI */
352
        0x00,     /* 17 - VBI */
353
};
354
 
355
/* bring hardware to a sane state. this has to be done, just in case someone
356
   wants to capture from this device before it has been properly initialized.
357
   the capture engine would badly fail, because no valid signal arrives on the
358
   saa7146, thus leading to timeouts and stuff. */
359
static int mxb_init_done(struct saa7146_dev* dev)
360
{
361
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
362
 
363
        struct i2c_msg msg;
364
 
365
        int i = 0, err = 0;
366
        struct  tea6415c_multiplex vm; 
367
 
368
        /* write configuration to saa7111a */
369
        i = i2c_master_send(mxb->saa7111a, mxb_saa7111_init, sizeof(mxb_saa7111_init));
370
        if (i < 0) {
371
                printk("failed to initialize saa7111a. this should never happen.\n");
372
        }
373
 
374
        /* select tuner-output on saa7111a */
375
        i = 0;
376
        mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i);
377
//      i = VIDEO_MODE_PAL;
378
//      mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_NORM, &i);
379
 
380
        mxb_vbi_bypass(dev);
381
 
382
        /* select a tuner type */
383
        i = 5;
384
        mxb->tuner->driver->command(mxb->tuner,TUNER_SET_TYPE, &i);
385
 
386
        /* mute audio on tea6420s */
387
        mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
388
        mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
389
        mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[6][0]);
390
        mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[6][1]);
391
 
392
        /* switch to tuner-channel on tea6415c*/
393
        vm.out = 17;
394
        vm.in  = 3;
395
        mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
396
 
397
        /* select tuner-output on multicable on tea6415c*/
398
        vm.in  = 3;
399
        vm.out = 13;
400
        mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm);
401
 
402
        /* tune in some frequency on tuner */
403
        mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &freq);
404
 
405
        /* the rest for mxb */
406
        mxb->cur_input = 0;
407
        mxb->cur_freq = freq;
408
        mxb->cur_mute = 1;
409
 
410
        mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
411
        mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &mxb->cur_mode);
412
 
413
        /* check if the saa7740 (aka 'sound arena module') is present
414
           on the mxb. if so, we must initialize it. due to lack of
415
           informations about the saa7740, the values were reverse
416
           engineered. */
417
        msg.addr = 0x1b;
418
        msg.flags = 0;
419
        msg.len = mxb_saa7740_init[0].length;
420
        msg.buf = &mxb_saa7740_init[0].data[0];
421
 
422
        if( 1 == (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
423
                /* the sound arena module is a pos, that's probably the reason
424
                   philips refuses to hand out a datasheet for the saa7740...
425
                   it seems to screw up the i2c bus, so we disable fast irq
426
                   based i2c transactions here and rely on the slow and safe
427
                   polling method ... */
428
                extension.flags &= ~SAA7146_USE_I2C_IRQ;
429
                for(i = 1;;i++) {
430
                        if( -1 == mxb_saa7740_init[i].length ) {
431
                                break;
432
                        }
433
 
434
                        msg.len = mxb_saa7740_init[i].length;          
435
                        msg.buf = &mxb_saa7740_init[i].data[0];
436
                        if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
437
                                DEB_D(("failed to initialize 'sound arena module'.\n"));
438
                                goto err;
439
                        }
440
                }
441
                INFO(("'sound arena module' detected.\n"));
442
        }
443
err:   
444
        /* the rest for saa7146: you should definitely set some basic values
445
           for the input-port handling of the saa7146. */
446
 
447
        /* ext->saa has been filled by the core driver */
448
 
449
        /* some stuff is done via variables */
450
        saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source, input_port_selection[mxb->cur_input].hps_sync);
451
 
452
        /* some stuff is done via direct write to the registers */
453
 
454
        /* this is ugly, but because of the fact that this is completely
455
           hardware dependend, it should be done directly... */
456
        saa7146_write(dev, DD1_STREAM_B,        0x00000000);
457
        saa7146_write(dev, DD1_INIT,            0x02000200);
458
        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
459
 
460
        return 0;
461
}
462
 
463
/* interrupt-handler. this gets called when irq_mask is != 0.
464
   it must clear the interrupt-bits in irq_mask it has handled */
465
/*
466
void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
467
{
468
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
469
}
470
*/
471
 
472
static struct saa7146_ext_vv vv_data;
473
 
474
/* this function only gets called when the probing was successful */
475
static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
476
{
477
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
478
 
479
        DEB_EE(("dev:%p\n",dev));
480
 
481
        /* checking for i2c-devices can be omitted here, because we
482
           already did this in "mxb_vl42_probe" */
483
 
484
        saa7146_vv_init(dev,&vv_data);
485
        if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
486
                ERR(("cannot register capture v4l2 device. skipping.\n"));
487
                return -1;
488
        }
489
 
490
        /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
491
        if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
492
                if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
493
                        ERR(("cannot register vbi v4l2 device. skipping.\n"));
494
                }
495
        }
496
 
497
        i2c_use_client(mxb->tea6420_1);
498
        i2c_use_client(mxb->tea6420_2);
499
        i2c_use_client(mxb->tea6415c);
500
        i2c_use_client(mxb->tda9840);
501
        i2c_use_client(mxb->saa7111a);
502
        i2c_use_client(mxb->tuner);
503
 
504
        printk("mxb: found 'Multimedia eXtension Board'-%d.\n",mxb_num);
505
 
506
        mxb_num++;
507
        mxb_init_done(dev);
508
        return 0;
509
}
510
 
511
static int mxb_detach(struct saa7146_dev* dev)
512
{
513
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
514
 
515
        DEB_EE(("dev:%p\n",dev));
516
 
517
        i2c_release_client(mxb->tea6420_1);
518
        i2c_release_client(mxb->tea6420_2);
519
        i2c_release_client(mxb->tea6415c);
520
        i2c_release_client(mxb->tda9840);
521
        i2c_release_client(mxb->saa7111a);
522
        i2c_release_client(mxb->tuner);
523
 
524
        saa7146_unregister_device(&mxb->video_dev,dev);
525
        if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) {
526
                saa7146_unregister_device(&mxb->vbi_dev,dev);
527
        }
528
        saa7146_vv_release(dev);
529
 
530
        mxb_num--;
531
 
532
        i2c_del_adapter(&mxb->i2c_adapter);
533
        kfree(mxb);
534
 
535
        return 0;
536
}
537
 
538
/* hack: this should go into saa711x */
539
static int saa7111_set_gpio(struct saa7146_dev *dev, int bl)
540
{
541
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
542
        s32 byte = 0x0;
543
        int result = 0;
544
 
545
        DEB_EE(("dev:%p\n",dev));
546
 
547
        /* get the old register contents */
548
        if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1))) {
549
                DEB_D(("could not read from saa711x\n"));
550
                return -EFAULT;
551
        }
552
 
553
        if( 0 == bl ) {
554
                byte &= 0x7f;
555
        } else {
556
                byte |= 0x80;
557
        }
558
 
559
        /* write register contents back */
560
        if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1, byte))) {
561
                DEB_D(("could not write to saa711x\n"));
562
                return -EFAULT;
563
        }
564
 
565
        return 0;
566
}
567
 
568
static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
569
{
570
        struct saa7146_dev *dev = fh->dev;
571
        struct mxb* mxb = (struct mxb*)dev->ext_priv;
572
        struct saa7146_vv *vv = dev->vv_data;
573
 
574
        switch(cmd) {
575
        case VIDIOC_ENUMINPUT:
576
        {
577
                struct v4l2_input *i = arg;
578
 
579
                DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
580
                if( i->index < 0 || i->index >= MXB_INPUTS) {
581
                        return -EINVAL;
582
                }
583
                memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
584
 
585
                return 0;
586
        }
587
        /* the saa7146 provides some controls (brightness, contrast, saturation)
588
           which gets registered *after* this function. because of this we have
589
           to return with a value != 0 even if the function succeded.. */
590
        case VIDIOC_QUERYCTRL:
591
        {
592
                struct v4l2_queryctrl *qc = arg;
593
                int i;
594
 
595
                for (i = MAXCONTROLS - 1; i >= 0; i--) {
596
                        if (mxb_controls[i].id == qc->id) {
597
                                *qc = mxb_controls[i];
598
                                DEB_D(("VIDIOC_QUERYCTRL %d.\n",qc->id));
599
                                return 0;
600
                        }
601
                }
602
                return -EAGAIN;
603
        }
604
        case VIDIOC_G_CTRL:
605
        {
606
                struct v4l2_control *vc = arg;
607
                int i;
608
 
609
                for (i = MAXCONTROLS - 1; i >= 0; i--) {
610
                        if (mxb_controls[i].id == vc->id) {
611
                                break;
612
                        }
613
                }
614
 
615
                if( i < 0 ) {
616
                        return -EAGAIN;
617
                }
618
 
619
                switch (vc->id ) {
620
                        case V4L2_CID_AUDIO_MUTE: {
621
                                vc->value = mxb->cur_mute;
622
                                DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
623
                                return 0;
624
                        }
625
                }
626
 
627
                DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n",vc->value));
628
                return 0;
629
        }
630
 
631
        case VIDIOC_S_CTRL:
632
        {
633
                struct  v4l2_control    *vc = arg;
634
                int i = 0;
635
 
636
                for (i = MAXCONTROLS - 1; i >= 0; i--) {
637
                        if (mxb_controls[i].id == vc->id) {
638
                                break;
639
                        }
640
                }
641
 
642
                if( i < 0 ) {
643
                        return -EAGAIN;
644
                }
645
 
646
                switch (vc->id ) {
647
                        case V4L2_CID_AUDIO_MUTE: {
648
                                mxb->cur_mute = vc->value;
649
                                if( 0 == vc->value ) {
650
                                        /* switch the audio-source */
651
                                        mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
652
                                        mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
653
                                } else {
654
                                        mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[6][0]);
655
                                        mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[6][1]);
656
                                }
657
                                DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n",vc->value));
658
                                break;
659
                        }
660
                }
661
                return 0;
662
        }
663
        case VIDIOC_G_INPUT:
664
        {
665
                int *input = (int *)arg;
666
                *input = mxb->cur_input;
667
 
668
                DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
669
                return 0;              
670
        }      
671
        case VIDIOC_S_INPUT:
672
        {
673
                int input = *(int *)arg;
674
                struct  tea6415c_multiplex vm; 
675
                int i = 0;
676
 
677
                DEB_EE(("VIDIOC_S_INPUT %d.\n",input));
678
 
679
                if (input < 0 || input >= MXB_INPUTS) {
680
                        return -EINVAL;
681
                }
682
 
683
                /* fixme: locke das setzen des inputs mit hilfe des mutexes
684
                down(&dev->lock);
685
                video_mux(dev,*i);
686
                up(&dev->lock);
687
                */
688
 
689
                /* fixme: check if streaming capture
690
                if ( 0 != dev->streaming ) {
691
                        DEB_D(("VIDIOC_S_INPUT illegal while streaming.\n"));
692
                        return -EPERM;
693
                }
694
                */
695
 
696
                mxb->cur_input = input;
697
 
698
                saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
699
 
700
                /* prepare switching of tea6415c and saa7111a;
701
                   have a look at the 'background'-file for further informations  */
702
                switch( input ) {
703
 
704
                        case TUNER:
705
                        {
706
                                i = 0;
707
                                vm.in  = 3;
708
                                vm.out = 17;
709
 
710
                        if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
711
                                        printk("VIDIOC_S_INPUT: could not address tea6415c #1\n");
712
                                        return -EFAULT;
713
                                }
714
                                /* connect tuner-output always to multicable */
715
                                vm.in  = 3;
716
                                vm.out = 13;
717
                                break;                         
718
                        }
719
                        case AUX3_YC:
720
                        {
721
                                /* nothing to be done here. aux3_yc is
722
                                   directly connected to the saa711a */
723
                                i = 5;
724
                                break;
725
                        }
726
                        case AUX3:
727
                        {
728
                                /* nothing to be done here. aux3 is
729
                                   directly connected to the saa711a */
730
                                i = 1;
731
                                break;
732
                        }
733
                        case AUX1:
734
                        {
735
                                i = 0;
736
                                vm.in  = 1;
737
                                vm.out = 17;
738
                                break;
739
                        }
740
                }
741
 
742
                /* switch video in tea6415c only if necessary */
743
                switch( input ) {
744
                        case TUNER:
745
                        case AUX1:
746
                        {
747
                                if ( 0 != mxb->tea6415c->driver->command(mxb->tea6415c,TEA6415C_SWITCH, &vm)) {
748
                                        printk("VIDIOC_S_INPUT: could not address tea6415c #3\n");
749
                                        return -EFAULT;
750
                                }
751
                                break;
752
                        }
753
                        default:
754
                        {
755
                                break;
756
                        }
757
                }
758
 
759
                /* switch video in saa7111a */
760
                if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_SET_INPUT, &i)) {
761
                        printk("VIDIOC_S_INPUT: could not address saa7111a #1.\n");
762
                }                      
763
 
764
                /* switch the audio-source only if necessary */
765
                if( 0 == mxb->cur_mute ) {
766
                        mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][0]);
767
                        mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[video_audio_connect[input]][1]);
768
                }
769
 
770
                return 0;
771
        }
772
        case VIDIOC_G_TUNER:
773
        {
774
                struct v4l2_tuner *t = arg;
775
                int byte = 0;
776
 
777
                if( 0 != t->index ) {
778
                        DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
779
                        return -EINVAL;
780
                }
781
 
782
                DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
783
 
784
                memset(t,0,sizeof(*t));
785
                strcpy(t->name, "Television");
786
 
787
                t->type = V4L2_TUNER_ANALOG_TV;
788
                t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
789
                t->rangelow = 772;      /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
790
                t->rangehigh = 13684;   /* 855.25 MHz / 62.5 kHz = 13684 */
791
                /* FIXME: add the real signal strength here */
792
                t->signal = 0xffff;
793
                t->afc = 0;            
794
 
795
                byte = mxb->tda9840->driver->command(mxb->tda9840,TDA9840_DETECT, NULL);
796
                t->audmode = mxb->cur_mode;
797
 
798
                if( byte < 0 ) {
799
                        t->rxsubchans  = V4L2_TUNER_SUB_MONO;
800
                } else {
801
                        switch(byte) {
802
                                case TDA9840_MONO_DETECT: {
803
                                        t->rxsubchans   = V4L2_TUNER_SUB_MONO;
804
                                        DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_MONO.\n"));
805
                                        break;
806
                                }
807
                                case TDA9840_DUAL_DETECT: {
808
                                        t->rxsubchans   = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
809
                                        DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_LANG1.\n"));
810
                                        break;
811
                                }
812
                                case TDA9840_STEREO_DETECT: {
813
                                        t->rxsubchans   = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
814
                                        DEB_D(("VIDIOC_G_TUNER: V4L2_TUNER_MODE_STEREO.\n"));
815
                                        break;
816
                                }
817
                                default: { /* TDA9840_INCORRECT_DETECT */
818
                                        t->rxsubchans   = V4L2_TUNER_MODE_MONO;
819
                                        DEB_D(("VIDIOC_G_TUNER: TDA9840_INCORRECT_DETECT => V4L2_TUNER_MODE_MONO\n"));
820
                                        break;
821
                                }
822
                        }
823
                }
824
 
825
                return 0;
826
        }
827
        case VIDIOC_S_TUNER:
828
        {
829
                struct v4l2_tuner *t = arg;
830
                int result = 0;
831
                int byte = 0;
832
 
833
                if( 0 != t->index ) {
834
                        DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n",t->index));
835
                        return -EINVAL;
836
                }
837
 
838
                switch(t->audmode) {
839
                        case V4L2_TUNER_MODE_STEREO: {
840
                                mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
841
                                byte = TDA9840_SET_STEREO;
842
                                DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
843
                                break;
844
                        }
845
                        case V4L2_TUNER_MODE_LANG1: {
846
                                mxb->cur_mode = V4L2_TUNER_MODE_LANG1;
847
                                byte = TDA9840_SET_LANG1;
848
                                DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
849
                                break;
850
                        }
851
                        case V4L2_TUNER_MODE_LANG2: {
852
                                mxb->cur_mode = V4L2_TUNER_MODE_LANG2;
853
                                byte = TDA9840_SET_LANG2;
854
                                DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
855
                                break;
856
                        }
857
                        default: { /* case V4L2_TUNER_MODE_MONO: {*/
858
                                mxb->cur_mode = V4L2_TUNER_MODE_MONO;
859
                                byte = TDA9840_SET_MONO;
860
                                DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
861
                                break;
862
                        }
863
                }
864
 
865
                if( 0 != (result = mxb->tda9840->driver->command(mxb->tda9840, TDA9840_SWITCH, &byte))) {
866
                        printk("VIDIOC_S_TUNER error. result:%d, byte:%d\n",result,byte);
867
                }
868
 
869
                return 0;
870
        }
871
        case VIDIOC_G_FREQUENCY:
872
        {
873
                struct v4l2_frequency *f = arg;
874
 
875
                if(0 != mxb->cur_input) {
876
                        DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
877
                        return -EINVAL;
878
                }
879
 
880
                memset(f,0,sizeof(*f));
881
                f->type = V4L2_TUNER_ANALOG_TV;
882
                f->frequency =  mxb->cur_freq;
883
 
884
                DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq));
885
                return 0;
886
        }
887
        case VIDIOC_S_FREQUENCY:
888
        {
889
                struct v4l2_frequency *f = arg;
890
                int t_locked = 0;
891
                int v_byte = 0;
892
 
893
                if (0 != f->tuner)
894
                        return -EINVAL;
895
 
896
                if (V4L2_TUNER_ANALOG_TV != f->type)
897
                        return -EINVAL;
898
 
899
                if(0 != mxb->cur_input) {
900
                        DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",mxb->cur_input));
901
                        return -EINVAL;
902
                }
903
 
904
                DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency));
905
 
906
                mxb->cur_freq = f->frequency;
907
 
908
                /* tune in desired frequency */                
909
                mxb->tuner->driver->command(mxb->tuner, VIDIOCSFREQ, &mxb->cur_freq);
910
 
911
                /* check if pll of tuner & saa7111a is locked */
912
//              mxb->tuner->driver->command(mxb->tuner,TUNER_IS_LOCKED, &t_locked);
913
                mxb->saa7111a->driver->command(mxb->saa7111a,DECODER_GET_STATUS, &v_byte);
914
 
915
                /* not locked -- anything to do here ? */
916
                if( 0 == t_locked || 0 == (v_byte & DECODER_STATUS_GOOD)) {
917
                }
918
 
919
                /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
920
                spin_lock(&dev->slock);
921
                vv->vbi_fieldcount = 0;
922
                spin_unlock(&dev->slock);
923
 
924
                return 0;
925
        }
926
        case MXB_S_AUDIO_CD:
927
        {
928
                int i = *(int*)arg;
929
 
930
                if( i < 0 || i >= MXB_AUDIOS ) {
931
                        DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n",i));
932
                        return -EINVAL;
933
                }
934
 
935
                DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n",i));
936
 
937
                mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_cd[i][0]);
938
                mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_cd[i][1]);
939
 
940
                return 0;
941
        }
942
        case MXB_S_AUDIO_LINE:
943
        {
944
                int i = *(int*)arg;
945
 
946
                if( i < 0 || i >= MXB_AUDIOS ) {
947
                        DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n",i));
948
                        return -EINVAL;
949
                }
950
 
951
                DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n",i));
952
                mxb->tea6420_1->driver->command(mxb->tea6420_1,TEA6420_SWITCH, &TEA6420_line[i][0]);
953
                mxb->tea6420_2->driver->command(mxb->tea6420_2,TEA6420_SWITCH, &TEA6420_line[i][1]);
954
 
955
                return 0;
956
        }
957
        case VIDIOC_G_AUDIO:
958
        {
959
                struct v4l2_audio *a = arg;
960
 
961
                if( a->index < 0 || a->index > MXB_INPUTS ) {
962
                        DEB_D(("VIDIOC_G_AUDIO %d out of range.\n",a->index));
963
                        return -EINVAL;
964
                }
965
 
966
                DEB_EE(("VIDIOC_G_AUDIO %d.\n",a->index));
967
                memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
968
 
969
                return 0;
970
        }
971
        case VIDIOC_S_AUDIO:
972
        {
973
                struct v4l2_audio *a = arg;
974
                DEB_D(("VIDIOC_S_AUDIO %d.\n",a->index));
975
                return 0;
976
        }      
977
        default:
978
/*
979
                DEB2(printk("does not handle this ioctl.\n"));
980
*/
981
                return -ENOIOCTLCMD;
982
        }
983
        return 0;
984
}
985
 
986
static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
987
{
988
        if(V4L2_STD_PAL_I == std->id ) {
989
                DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
990
                /* set the 7146 gpio register -- I don't know what this does exactly */
991
                saa7146_write(dev, GPIO_CTRL, 0x00404050);
992
                /* unset the 7111 gpio register -- I don't know what this does exactly */
993
                saa7111_set_gpio(dev,0);
994
        } else {
995
                DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
996
                /* set the 7146 gpio register -- I don't know what this does exactly */
997
                saa7146_write(dev, GPIO_CTRL, 0x00404050);
998
                /* set the 7111 gpio register -- I don't know what this does exactly */
999
                saa7111_set_gpio(dev,1);
1000
        }
1001
        return 0;
1002
}
1003
 
1004
static struct saa7146_standard standard[] = {
1005
        {
1006
                .name   = "PAL-BG",     .id     = V4L2_STD_PAL_BG,
1007
                .v_offset       = 0x17, .v_field        = 288,  .v_calc         = 576,
1008
                .h_offset       = 0x14, .h_pixels       = 680,  .h_calc         = 680+1,
1009
                .v_max_out      = 576,  .h_max_out      = 768,
1010
        }, {
1011
                .name   = "PAL-I",      .id     = V4L2_STD_PAL_I,
1012
                .v_offset       = 0x17, .v_field        = 288,  .v_calc         = 576,
1013
                .h_offset       = 0x14, .h_pixels       = 680,  .h_calc         = 680+1,
1014
                .v_max_out      = 576,  .h_max_out      = 768,
1015
        }, {
1016
                .name   = "NTSC",       .id     = V4L2_STD_NTSC,
1017
                .v_offset       = 0x16, .v_field        = 240,  .v_calc         = 480,
1018
                .h_offset       = 0x06, .h_pixels       = 708,  .h_calc         = 708+1,
1019
                .v_max_out      = 480,  .h_max_out      = 640,
1020
        }, {
1021
                .name   = "SECAM",      .id     = V4L2_STD_SECAM,
1022
                .v_offset       = 0x14, .v_field        = 288,  .v_calc         = 576,
1023
                .h_offset       = 0x14, .h_pixels       = 720,  .h_calc         = 720+1,
1024
                .v_max_out      = 576,  .h_max_out      = 768,
1025
        }
1026
};             
1027
 
1028
static struct saa7146_pci_extension_data mxb = {
1029
        .ext_priv = "Multimedia eXtension Board",
1030
        .ext = &extension,
1031
};
1032
 
1033
static struct pci_device_id pci_tbl[] = {
1034
        {
1035
                .vendor    = PCI_VENDOR_ID_PHILIPS,
1036
                .device    = PCI_DEVICE_ID_PHILIPS_SAA7146,
1037
                .subvendor = 0x0000,
1038
                .subdevice = 0x0000,
1039
                .driver_data = (unsigned long)&mxb,
1040
        }, {
1041
                .vendor = 0,
1042
        }
1043
};
1044
 
1045
MODULE_DEVICE_TABLE(pci, pci_tbl);
1046
 
1047
static struct saa7146_ext_vv vv_data = {
1048
        .inputs         = MXB_INPUTS,
1049
        .capabilities   = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
1050
        .stds           = &standard[0],
1051
        .num_stds       = sizeof(standard)/sizeof(struct saa7146_standard),
1052
        .std_callback   = &std_callback,
1053
        .ioctls         = &ioctls[0],
1054
        .ioctl          = mxb_ioctl,
1055
};
1056
 
1057
static struct saa7146_extension extension = {
1058
        .name           = MXB_IDENTIFIER,
1059
        .flags          = SAA7146_USE_I2C_IRQ,
1060
 
1061
        .pci_tbl        = &pci_tbl[0],
1062
        .module         = THIS_MODULE,
1063
 
1064
        .probe          = mxb_probe,
1065
        .attach         = mxb_attach,
1066
        .detach         = mxb_detach,
1067
 
1068
        .irq_mask       = 0,
1069
        .irq_func       = NULL,
1070
};     
1071
 
1072
int __init mxb_init_module(void)
1073
{
1074
        if( 0 != saa7146_register_extension(&extension)) {
1075
                DEB_S(("failed to register extension.\n"));
1076
                return -ENODEV;
1077
        }
1078
 
1079
        return 0;
1080
}
1081
 
1082
void __exit mxb_cleanup_module(void)
1083
{
1084
        saa7146_unregister_extension(&extension);
1085
}
1086
 
1087
module_init(mxb_init_module);
1088
module_exit(mxb_cleanup_module);
1089
 
1090
MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
1091
MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
1092
MODULE_LICENSE("GPL");