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