Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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