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
    hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards
3
 
4
    Visit http://www.mihu.de/linux/saa7146/ and follow the link
5
    to "hexium" for further details about this card.
6
 
7
    Copyright (C) 2003 Michael Hunold <michael@mihu.de>
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
 
28
static int debug = 0;
29
MODULE_PARM(debug, "i");
30
MODULE_PARM_DESC(debug, "debug verbosity");
31
 
32
/* global variables */
33
static int hexium_num = 0;
34
 
35
#define HEXIUM_GEMUINI                  4
36
#define HEXIUM_GEMUINI_DUAL             5
37
 
38
#define HEXIUM_INPUTS   9
39
static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
40
        { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
41
        { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
42
        { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
43
        { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
44
        { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
45
        { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
46
        { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
47
        { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
48
        { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
49
};
50
 
51
#define HEXIUM_AUDIOS   0
52
 
53
struct hexium_data
54
{
55
        s8 adr;
56
        u8 byte;
57
};
58
 
59
static struct saa7146_extension_ioctls ioctls[] = {
60
        { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
61
        { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
62
        { VIDIOC_QUERYCTRL,     SAA7146_BEFORE },
63
        { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
64
        { VIDIOC_S_STD,         SAA7146_AFTER },
65
        { VIDIOC_G_CTRL,        SAA7146_BEFORE },
66
        { VIDIOC_S_CTRL,        SAA7146_BEFORE },
67
        { 0,                    0 }
68
};
69
 
70
#define HEXIUM_CONTROLS 1
71
static struct v4l2_queryctrl hexium_controls[] = {
72
        { V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
73
};
74
 
75
#define HEXIUM_GEMUINI_V_1_0            1
76
#define HEXIUM_GEMUINI_DUAL_V_1_0       2
77
 
78
struct hexium
79
{
80
        int type;
81
        struct video_device     video_dev;
82
        struct i2c_adapter      i2c_adapter;
83
 
84
        int             cur_input;      /* current input */
85
        v4l2_std_id     cur_std;        /* current standard */
86
        int             cur_bw;         /* current black/white status */
87
};
88
 
89
/* Samsung KS0127B decoder default registers */
90
static u8 hexium_ks0127b[0x100]={
91
/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
92
/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
93
/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
94
/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
95
/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96
/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
97
/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
98
/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
99
/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100
/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
101
/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102
/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
103
/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104
/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
105
/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
106
/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
107
/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
108
/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
109
/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110
/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
111
/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
112
/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
113
/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
114
/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
115
/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
116
/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117
/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118
/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119
/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120
/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121
/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122
/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
123
};
124
 
125
static struct hexium_data hexium_pal[] = {
126
        { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
127
};
128
 
129
static struct hexium_data hexium_pal_bw[] = {
130
        { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
131
};
132
 
133
static struct hexium_data hexium_ntsc[] = {
134
        { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
135
};
136
 
137
static struct hexium_data hexium_ntsc_bw[] = {
138
        { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
139
};
140
 
141
static struct hexium_data hexium_secam[] = {
142
        { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
143
};
144
 
145
static struct hexium_data hexium_input_select[] = {
146
        { 0x02, 0x60 },
147
        { 0x02, 0x64 },
148
        { 0x02, 0x61 },
149
        { 0x02, 0x65 },
150
        { 0x02, 0x62 },
151
        { 0x02, 0x66 },
152
        { 0x02, 0x68 },
153
        { 0x02, 0x69 },
154
        { 0x02, 0x6A },
155
};
156
 
157
/* fixme: h_offset = 0 for Hexium Gemini Dual */
158
static struct saa7146_standard hexium_standards[] = {
159
        {
160
                .name   = "PAL",        .id     = V4L2_STD_PAL,
161
                .v_offset       = 28,   .v_field        = 288,  .v_calc         = 576,
162
                .h_offset       = 1,    .h_pixels       = 680,  .h_calc         = 680+1,
163
                .v_max_out      = 576,  .h_max_out      = 768,
164
        }, {
165
                .name   = "NTSC",       .id     = V4L2_STD_NTSC,
166
                .v_offset       = 28,   .v_field        = 240,  .v_calc         = 480,
167
                .h_offset       = 1,    .h_pixels       = 640,  .h_calc         = 641+1,
168
                .v_max_out      = 480,  .h_max_out      = 640,
169
        }, {
170
                .name   = "SECAM",      .id     = V4L2_STD_SECAM,
171
                .v_offset       = 28,   .v_field        = 288,  .v_calc         = 576,
172
                .h_offset       = 1,    .h_pixels       = 720,  .h_calc         = 720+1,
173
                .v_max_out      = 576,  .h_max_out      = 768,
174
        }
175
};             
176
 
177
/* bring hardware to a sane state. this has to be done, just in case someone
178
   wants to capture from this device before it has been properly initialized.
179
   the capture engine would badly fail, because no valid signal arrives on the
180
   saa7146, thus leading to timeouts and stuff. */
181
static int hexium_init_done(struct saa7146_dev *dev)
182
{
183
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
184
        union i2c_smbus_data data;
185
        int i = 0;
186
 
187
        DEB_D(("hexium_init_done called.\n"));
188
 
189
        /* initialize the helper ics to useful values */
190
        for (i = 0; i < sizeof(hexium_ks0127b); i++) {
191
                data.byte = hexium_ks0127b[i];
192
                if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
193
                        printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i);
194
                }
195
        }
196
 
197
        return 0;
198
}
199
 
200
static int hexium_set_input(struct hexium *hexium, int input)
201
{
202
        union i2c_smbus_data data;
203
 
204
        DEB_D((".\n"));
205
 
206
        data.byte = hexium_input_select[input].byte;
207
        if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
208
                return -1;
209
        }
210
 
211
        return 0;
212
}
213
 
214
static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
215
{
216
        union i2c_smbus_data data;
217
        int i = 0;
218
 
219
        DEB_D((".\n"));
220
 
221
        while (vdec[i].adr != -1) {
222
                data.byte = vdec[i].byte;
223
                if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
224
                        printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i);
225
                        return -1;
226
                }
227
                i++;
228
        }
229
        return 0;
230
}
231
 
232
static struct saa7146_ext_vv vv_data;
233
 
234
/* this function only gets called when the probing was successful */
235
static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
236
{
237
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
238
 
239
        DEB_EE((".\n"));
240
 
241
        hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
242
        if (NULL == hexium) {
243
                printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
244
                return -ENOMEM;
245
        }
246
        memset(hexium, 0x0, sizeof(struct hexium));
247
        (struct hexium *) dev->ext_priv = hexium;
248
 
249
        /* enable i2c-port pins */
250
        saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
251
 
252
        saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
253
        if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
254
                DEB_S(("cannot register i2c-device. skipping.\n"));
255
                kfree(hexium);
256
                return -EFAULT;
257
        }
258
 
259
        /*  set HWControl GPIO number 2 */
260
        saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
261
 
262
        saa7146_write(dev, DD1_INIT, 0x07000700);
263
        saa7146_write(dev, DD1_STREAM_B, 0x00000000);
264
        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
265
 
266
        /* the rest */
267
        hexium->cur_input = 0;
268
        hexium_init_done(dev);
269
 
270
        hexium_set_standard(hexium, hexium_pal);
271
        hexium->cur_std = V4L2_STD_PAL;
272
 
273
        hexium_set_input(hexium, 0);
274
        hexium->cur_input = 0;
275
 
276
        saa7146_vv_init(dev, &vv_data);
277
        if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) {
278
                printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
279
                return -1;
280
        }
281
 
282
        printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
283
        hexium_num++;
284
 
285
        return 0;
286
}
287
 
288
static int hexium_detach(struct saa7146_dev *dev)
289
{
290
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
291
 
292
        DEB_EE(("dev:%p\n", dev));
293
 
294
        saa7146_unregister_device(&hexium->video_dev, dev);
295
        saa7146_vv_release(dev);
296
 
297
        hexium_num--;
298
 
299
        i2c_del_adapter(&hexium->i2c_adapter);
300
        kfree(hexium);
301
        return 0;
302
}
303
 
304
static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
305
{
306
        struct saa7146_dev *dev = fh->dev;
307
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
308
/*
309
        struct saa7146_vv *vv = dev->vv_data;
310
*/
311
        switch (cmd) {
312
        case VIDIOC_ENUMINPUT:
313
                {
314
                        struct v4l2_input *i = arg;
315
                        DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
316
 
317
                        if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
318
                                return -EINVAL;
319
                        }
320
 
321
                        memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
322
 
323
                        DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
324
                        return 0;
325
                }
326
        case VIDIOC_G_INPUT:
327
                {
328
                        int *input = (int *) arg;
329
                        *input = hexium->cur_input;
330
 
331
                        DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
332
                        return 0;
333
                }
334
        case VIDIOC_S_INPUT:
335
                {
336
                        int input = *(int *) arg;
337
 
338
                        DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
339
 
340
                        if (input < 0 || input >= HEXIUM_INPUTS) {
341
                                return -EINVAL;
342
                        }
343
 
344
                        hexium->cur_input = input;
345
                        hexium_set_input(hexium, input);
346
 
347
                        return 0;
348
                }
349
                /* the saa7146 provides some controls (brightness, contrast, saturation)
350
                   which gets registered *after* this function. because of this we have
351
                   to return with a value != 0 even if the function succeded.. */
352
        case VIDIOC_QUERYCTRL:
353
                {
354
                        struct v4l2_queryctrl *qc = arg;
355
                        int i;
356
 
357
                        for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
358
                                if (hexium_controls[i].id == qc->id) {
359
                                        *qc = hexium_controls[i];
360
                                        DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
361
                                        return 0;
362
                                }
363
                        }
364
                        return -EAGAIN;
365
                }
366
        case VIDIOC_G_CTRL:
367
                {
368
                        struct v4l2_control *vc = arg;
369
                        int i;
370
 
371
                        for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
372
                                if (hexium_controls[i].id == vc->id) {
373
                                        break;
374
                                }
375
                        }
376
 
377
                        if (i < 0) {
378
                                return -EAGAIN;
379
                        }
380
 
381
                        switch (vc->id) {
382
                        case V4L2_CID_PRIVATE_BASE:{
383
                                        vc->value = hexium->cur_bw;
384
                                        DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
385
                                        return 0;
386
                                }
387
                        }
388
                        return -EINVAL;
389
                }
390
 
391
        case VIDIOC_S_CTRL:
392
                {
393
                        struct v4l2_control *vc = arg;
394
                        int i = 0;
395
 
396
                        for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
397
                                if (hexium_controls[i].id == vc->id) {
398
                                        break;
399
                                }
400
                        }
401
 
402
                        if (i < 0) {
403
                                return -EAGAIN;
404
                        }
405
 
406
                        switch (vc->id) {
407
                        case V4L2_CID_PRIVATE_BASE:{
408
                                        hexium->cur_bw = vc->value;
409
                                        break;
410
                                }
411
                        }
412
 
413
                        DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
414
 
415
                        if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
416
                                hexium_set_standard(hexium, hexium_pal);
417
                                return 0;
418
                        }
419
                        if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
420
                                hexium_set_standard(hexium, hexium_ntsc);
421
                                return 0;
422
                        }
423
                        if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
424
                                hexium_set_standard(hexium, hexium_secam);
425
                                return 0;
426
                        }
427
                        if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
428
                                hexium_set_standard(hexium, hexium_pal_bw);
429
                                return 0;
430
                        }
431
                        if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
432
                                hexium_set_standard(hexium, hexium_ntsc_bw);
433
                                return 0;
434
                        }
435
                        if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
436
                                /* fixme: is there no bw secam mode? */
437
                                return -EINVAL;
438
                        }
439
 
440
                        return -EINVAL;
441
                }
442
        default:
443
/*
444
                DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
445
*/
446
                return -ENOIOCTLCMD;
447
        }
448
        return 0;
449
}
450
 
451
static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
452
{
453
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
454
 
455
        if (V4L2_STD_PAL == std->id) {
456
                hexium_set_standard(hexium, hexium_pal);
457
                hexium->cur_std = V4L2_STD_PAL;
458
                return 0;
459
        } else if (V4L2_STD_NTSC == std->id) {
460
                hexium_set_standard(hexium, hexium_ntsc);
461
                hexium->cur_std = V4L2_STD_NTSC;
462
                return 0;
463
        } else if (V4L2_STD_SECAM == std->id) {
464
                hexium_set_standard(hexium, hexium_secam);
465
                hexium->cur_std = V4L2_STD_SECAM;
466
                return 0;
467
        }
468
 
469
        return -1;
470
}
471
 
472
static struct saa7146_extension hexium_extension;
473
 
474
static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
475
        .ext_priv = "Hexium Gemini (4 BNC)",
476
        .ext = &hexium_extension,
477
};
478
 
479
static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
480
        .ext_priv = "Hexium Gemini Dual (4 BNC)",
481
        .ext = &hexium_extension,
482
};
483
 
484
static struct pci_device_id pci_tbl[] = {
485
        {
486
         .vendor = PCI_VENDOR_ID_PHILIPS,
487
         .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
488
         .subvendor = 0x17c8,
489
         .subdevice = 0x2401,
490
         .driver_data = (unsigned long) &hexium_gemini_4bnc,
491
         },
492
        {
493
         .vendor = PCI_VENDOR_ID_PHILIPS,
494
         .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
495
         .subvendor = 0x17c8,
496
         .subdevice = 0x2402,
497
         .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
498
         },
499
        {
500
         .vendor = 0,
501
         }
502
};
503
 
504
MODULE_DEVICE_TABLE(pci, pci_tbl);
505
 
506
static struct saa7146_ext_vv vv_data = {
507
        .inputs = HEXIUM_INPUTS,
508
        .capabilities = 0,
509
        .stds = &hexium_standards[0],
510
        .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
511
        .std_callback = &std_callback,
512
        .ioctls = &ioctls[0],
513
        .ioctl = hexium_ioctl,
514
};
515
 
516
static struct saa7146_extension hexium_extension = {
517
        .name = "hexium gemini",
518
        .flags = SAA7146_USE_I2C_IRQ,
519
 
520
        .pci_tbl = &pci_tbl[0],
521
        .module = THIS_MODULE,
522
 
523
        .attach = hexium_attach,
524
        .detach = hexium_detach,
525
 
526
        .irq_mask = 0,
527
        .irq_func = NULL,
528
};
529
 
530
static int __init hexium_init_module(void)
531
{
532
        if (0 != saa7146_register_extension(&hexium_extension)) {
533
                DEB_S(("failed to register extension.\n"));
534
                return -ENODEV;
535
        }
536
 
537
        return 0;
538
}
539
 
540
static void __exit hexium_cleanup_module(void)
541
{
542
        saa7146_unregister_extension(&hexium_extension);
543
}
544
 
545
module_init(hexium_init_module);
546
module_exit(hexium_cleanup_module);
547
 
548
MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
549
MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
550
MODULE_LICENSE("GPL");