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