patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / media / video / hexium_orion.c
1 /*
2     hexium_orion.c - v4l2 driver for the Hexium Orion 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_HV_PCI6_ORION            1
36 #define HEXIUM_ORION_1SVHS_3BNC         2
37 #define HEXIUM_ORION_4BNC               3
38
39 #define HEXIUM_INPUTS   9
40 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
41         { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
42         { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
43         { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
44         { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
45         { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
46         { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
47         { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
48         { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
49         { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
50 };
51
52 #define HEXIUM_AUDIOS   0
53
54 struct hexium_data
55 {
56         s8 adr;
57         u8 byte;
58 };
59
60 static struct saa7146_extension_ioctls ioctls[] = {
61         { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
62         { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
63         { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
64         { VIDIOC_S_STD,         SAA7146_AFTER },
65         { 0,                    0 }
66 };
67
68 struct hexium
69 {
70         int type;
71         struct video_device     video_dev;
72         struct i2c_adapter      i2c_adapter;    
73         int cur_input;  /* current input */
74 };
75
76 /* Philips SAA7110 decoder default registers */
77 static u8 hexium_saa7110[53]={
78 /*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
79 /*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
80 /*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
81 /*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
82 /*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
83 /*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
84 /*30*/ 0x44,0x75,0x01,0x8C,0x03
85 };
86
87 static struct {
88         struct hexium_data data[8];     
89 } hexium_input_select[] = {
90 {
91         { /* cvbs 1 */
92                 { 0x06, 0x00 },
93                 { 0x20, 0xD9 },
94                 { 0x21, 0x17 }, // 0x16,
95                 { 0x22, 0x40 },
96                 { 0x2C, 0x03 },
97                 { 0x30, 0x44 },
98                 { 0x31, 0x75 }, // ??
99                 { 0x21, 0x16 }, // 0x03,
100         }
101 }, {
102         { /* cvbs 2 */
103                 { 0x06, 0x00 },
104                 { 0x20, 0x78 },
105                 { 0x21, 0x07 }, // 0x03,
106                 { 0x22, 0xD2 },
107                 { 0x2C, 0x83 },
108                 { 0x30, 0x60 },
109                 { 0x31, 0xB5 }, // ?
110                 { 0x21, 0x03 },
111         }
112 }, {
113         { /* cvbs 3 */
114                 { 0x06, 0x00 },
115                 { 0x20, 0xBA },
116                 { 0x21, 0x07 }, // 0x05,
117                 { 0x22, 0x91 },
118                 { 0x2C, 0x03 },
119                 { 0x30, 0x60 },
120                 { 0x31, 0xB5 }, // ??
121                 { 0x21, 0x05 }, // 0x03,
122         }
123 }, {
124         { /* cvbs 4 */
125                 { 0x06, 0x00 },
126                 { 0x20, 0xD8 },
127                 { 0x21, 0x17 }, // 0x16,
128                 { 0x22, 0x40 },
129                 { 0x2C, 0x03 },
130                 { 0x30, 0x44 },
131                 { 0x31, 0x75 }, // ??
132                 { 0x21, 0x16 }, // 0x03,
133         }
134 }, {
135         { /* cvbs 5 */
136                 { 0x06, 0x00 },
137                 { 0x20, 0xB8 },
138                 { 0x21, 0x07 }, // 0x05,
139                 { 0x22, 0x91 },
140                 { 0x2C, 0x03 },
141                 { 0x30, 0x60 },
142                 { 0x31, 0xB5 }, // ??
143                 { 0x21, 0x05 }, // 0x03,
144         }
145 }, {
146         { /* cvbs 6 */
147                 { 0x06, 0x00 },
148                 { 0x20, 0x7C },
149                 { 0x21, 0x07 }, // 0x03
150                 { 0x22, 0xD2 },
151                 { 0x2C, 0x83 },
152                 { 0x30, 0x60 },
153                 { 0x31, 0xB5 }, // ??
154                 { 0x21, 0x03 },
155         } 
156 }, {
157         { /* y/c 1 */
158                 { 0x06, 0x80 },
159                 { 0x20, 0x59 },
160                 { 0x21, 0x17 },
161                 { 0x22, 0x42 },
162                 { 0x2C, 0xA3 },
163                 { 0x30, 0x44 },
164                 { 0x31, 0x75 },
165                 { 0x21, 0x12 },
166         }
167 }, {
168         { /* y/c 2 */
169                 { 0x06, 0x80 },
170                 { 0x20, 0x9A },
171                 { 0x21, 0x17 },
172                 { 0x22, 0xB1 },
173                 { 0x2C, 0x13 },
174                 { 0x30, 0x60 },
175                 { 0x31, 0xB5 },
176                 { 0x21, 0x14 },
177         }
178 }, {
179         { /* y/c 3 */
180                 { 0x06, 0x80 },
181                 { 0x20, 0x3C },
182                 { 0x21, 0x27 },
183                 { 0x22, 0xC1 },
184                 { 0x2C, 0x23 },
185                 { 0x30, 0x44 },
186                 { 0x31, 0x75 },
187                 { 0x21, 0x21 },
188         }
189 }       
190 };
191
192 static struct saa7146_standard hexium_standards[] = {
193         {
194                 .name   = "PAL",        .id     = V4L2_STD_PAL,
195                 .v_offset       = 16,   .v_field        = 288,
196                 .h_offset       = 1,    .h_pixels       = 680,
197                 .v_max_out      = 576,  .h_max_out      = 768,
198         }, {
199                 .name   = "NTSC",       .id     = V4L2_STD_NTSC,
200                 .v_offset       = 16,   .v_field        = 240,
201                 .h_offset       = 1,    .h_pixels       = 640,
202                 .v_max_out      = 480,  .h_max_out      = 640,
203         }, {
204                 .name   = "SECAM",      .id     = V4L2_STD_SECAM,
205                 .v_offset       = 16,   .v_field        = 288,
206                 .h_offset       = 1,    .h_pixels       = 720,
207                 .v_max_out      = 576,  .h_max_out      = 768,
208         }
209 };              
210
211 /* this is only called for old HV-PCI6/Orion cards
212    without eeprom */
213 static int hexium_probe(struct saa7146_dev *dev)
214 {
215         struct hexium *hexium = 0;
216         union i2c_smbus_data data;
217         int err = 0;
218
219         DEB_EE((".\n"));
220
221         /* there are no hexium orion cards with revision 0 saa7146s */
222         if (0 == dev->revision) {
223                 return -EFAULT;
224         }
225
226         hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
227         if (NULL == hexium) {
228                 printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
229                 return -ENOMEM;
230         }
231         memset(hexium, 0x0, sizeof(struct hexium));
232
233         /* enable i2c-port pins */
234         saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
235
236         saa7146_write(dev, DD1_INIT, 0x01000100);
237         saa7146_write(dev, DD1_STREAM_B, 0x00000000);
238         saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
239
240         saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, I2C_CLASS_TV_ANALOG, SAA7146_I2C_BUS_BIT_RATE_480);
241         if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
242                 DEB_S(("cannot register i2c-device. skipping.\n"));
243                 kfree(hexium);
244                 return -EFAULT;
245         }
246
247         /* set SAA7110 control GPIO 0 */
248         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
249         /*  set HWControl GPIO number 2 */
250         saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
251
252         mdelay(10);
253
254         /* detect newer Hexium Orion cards by subsystem ids */
255         if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
256                 printk("hexium_orion: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
257                 /* we store the pointer in our private data field */
258                 dev->ext_priv = hexium;
259                 hexium->type = HEXIUM_ORION_1SVHS_3BNC;
260                 return 0;
261         }
262
263         if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
264                 printk("hexium_orion: device is a Hexium Orion w/ 4 BNC inputs.\n");
265                 /* we store the pointer in our private data field */
266                 dev->ext_priv = hexium;
267                 hexium->type = HEXIUM_ORION_4BNC;
268                 return 0;
269         }
270
271         /* check if this is an old hexium Orion card by looking at 
272            a saa7110 at address 0x4e */
273         if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
274                 printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n");
275                 /* we store the pointer in our private data field */
276                 dev->ext_priv = hexium;
277                 hexium->type = HEXIUM_HV_PCI6_ORION;
278                 return 0;
279         }
280
281         i2c_del_adapter(&hexium->i2c_adapter);
282         kfree(hexium);
283         return -EFAULT;
284 }
285
286 /* bring hardware to a sane state. this has to be done, just in case someone
287    wants to capture from this device before it has been properly initialized.
288    the capture engine would badly fail, because no valid signal arrives on the
289    saa7146, thus leading to timeouts and stuff. */
290 static int hexium_init_done(struct saa7146_dev *dev)
291 {
292         struct hexium *hexium = (struct hexium *) dev->ext_priv;
293         union i2c_smbus_data data;
294         int i = 0;
295
296         DEB_D(("hexium_init_done called.\n"));
297
298         /* initialize the helper ics to useful values */
299         for (i = 0; i < sizeof(hexium_saa7110); i++) {
300                 data.byte = hexium_saa7110[i];
301                 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
302                         printk("hexium_orion: failed for address 0x%02x\n", i);
303                 }
304         }
305
306         return 0;
307 }
308
309 static int hexium_set_input(struct hexium *hexium, int input)
310 {
311         union i2c_smbus_data data;
312         int i = 0;
313         
314         DEB_D((".\n"));
315
316         for (i = 0; i < 8; i++) {
317                 int adr = hexium_input_select[input].data[i].adr;
318                 data.byte = hexium_input_select[input].data[i].byte;
319                 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, adr, I2C_SMBUS_BYTE_DATA, &data)) {
320                         return -1;
321                 }
322                 printk("%d: 0x%02x => 0x%02x\n",input, adr,data.byte);
323         }
324
325         return 0;
326 }
327
328 static struct saa7146_ext_vv vv_data;
329
330 /* this function only gets called when the probing was successful */
331 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
332 {
333         struct hexium *hexium = (struct hexium *) dev->ext_priv;
334
335         DEB_EE((".\n"));
336
337         saa7146_vv_init(dev, &vv_data);
338         if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
339                 printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
340                 return -1;
341         }
342
343         printk("hexium_orion: found 'hexium orion' frame grabber-%d.\n", hexium_num);
344         hexium_num++;
345
346         /* the rest */
347         hexium->cur_input = 0;
348         hexium_init_done(dev);
349
350         return 0;
351 }
352
353 static int hexium_detach(struct saa7146_dev *dev)
354 {
355         struct hexium *hexium = (struct hexium *) dev->ext_priv;
356
357         DEB_EE(("dev:%p\n", dev));
358
359         saa7146_unregister_device(&hexium->video_dev, dev);
360         saa7146_vv_release(dev);
361
362         hexium_num--;
363
364         i2c_del_adapter(&hexium->i2c_adapter);
365         kfree(hexium);
366         return 0;
367 }
368
369 static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
370 {
371         struct saa7146_dev *dev = fh->dev;
372         struct hexium *hexium = (struct hexium *) dev->ext_priv;
373 /*
374         struct saa7146_vv *vv = dev->vv_data; 
375 */
376         switch (cmd) {
377         case VIDIOC_ENUMINPUT:
378                 {
379                         struct v4l2_input *i = arg;
380                         DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
381
382                         if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
383                                 return -EINVAL;
384                         }
385
386                         memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
387
388                         DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
389                         return 0;
390                 }
391         case VIDIOC_G_INPUT:
392                 {
393                         int *input = (int *) arg;
394                         *input = hexium->cur_input;
395
396                         DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
397                         return 0;
398                 }
399         case VIDIOC_S_INPUT:
400                 {
401                         int input = *(int *) arg;
402
403                         if (input < 0 || input >= HEXIUM_INPUTS) {
404                                 return -EINVAL;
405                         }
406
407                         hexium->cur_input = input;
408                         hexium_set_input(hexium, input);
409
410                         return 0;
411                 }
412         default:
413 /*
414                 DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
415 */
416                 return -ENOIOCTLCMD;
417         }
418         return 0;
419 }
420
421 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
422 {
423         return 0;
424 }
425
426 static struct saa7146_extension extension;
427
428 static struct saa7146_pci_extension_data hexium_hv_pci6 = {
429         .ext_priv = "Hexium HV-PCI6 / Orion",
430         .ext = &extension,
431 };
432
433 static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
434         .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
435         .ext = &extension,
436 };
437
438 static struct saa7146_pci_extension_data hexium_orion_4bnc = {
439         .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
440         .ext = &extension,
441 };
442
443 static struct pci_device_id pci_tbl[] = {
444         {
445          .vendor = PCI_VENDOR_ID_PHILIPS,
446          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
447          .subvendor = 0x0000,
448          .subdevice = 0x0000,
449          .driver_data = (unsigned long) &hexium_hv_pci6,
450          },
451         {
452          .vendor = PCI_VENDOR_ID_PHILIPS,
453          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
454          .subvendor = 0x17c8,
455          .subdevice = 0x0101,
456          .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
457          },
458         {
459          .vendor = PCI_VENDOR_ID_PHILIPS,
460          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
461          .subvendor = 0x17c8,
462          .subdevice = 0x2101,
463          .driver_data = (unsigned long) &hexium_orion_4bnc,
464          },
465         {
466          .vendor = 0,
467          }
468 };
469
470 MODULE_DEVICE_TABLE(pci, pci_tbl);
471
472 static struct saa7146_ext_vv vv_data = {
473         .inputs = HEXIUM_INPUTS,
474         .capabilities = 0,
475         .stds = &hexium_standards[0],
476         .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
477         .std_callback = &std_callback,
478         .ioctls = &ioctls[0],
479         .ioctl = hexium_ioctl,
480 };
481
482 static struct saa7146_extension extension = {
483         .name = "hexium HV-PCI6/Orion",
484         .flags = 0,             // SAA7146_USE_I2C_IRQ,
485
486         .pci_tbl = &pci_tbl[0],
487         .module = THIS_MODULE,
488
489         .probe = hexium_probe,
490         .attach = hexium_attach,
491         .detach = hexium_detach,
492
493         .irq_mask = 0,
494         .irq_func = NULL,
495 };
496
497 int __init hexium_init_module(void)
498 {
499         if (0 != saa7146_register_extension(&extension)) {
500                 DEB_S(("failed to register extension.\n"));
501                 return -ENODEV;
502         }
503
504         return 0;
505 }
506
507 void __exit hexium_cleanup_module(void)
508 {
509         saa7146_unregister_extension(&extension);
510 }
511
512 module_init(hexium_init_module);
513 module_exit(hexium_cleanup_module);
514
515 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
516 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
517 MODULE_LICENSE("GPL");