OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [video/] [mxb.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.