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