GNU Linux-libre 4.14.254-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
370         DEB_EE("\n");
371
372         saa7146_vv_init(dev, &vv_data);
373         vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
374         vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
375         vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
376         if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
377                 pr_err("cannot register capture v4l2 device. skipping.\n");
378                 return -1;
379         }
380
381         pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
382         hexium_num++;
383
384         /* the rest */
385         hexium->cur_input = 0;
386         hexium_init_done(dev);
387
388         return 0;
389 }
390
391 static int hexium_detach(struct saa7146_dev *dev)
392 {
393         struct hexium *hexium = (struct hexium *) dev->ext_priv;
394
395         DEB_EE("dev:%p\n", dev);
396
397         saa7146_unregister_device(&hexium->video_dev, dev);
398         saa7146_vv_release(dev);
399
400         hexium_num--;
401
402         i2c_del_adapter(&hexium->i2c_adapter);
403         kfree(hexium);
404         return 0;
405 }
406
407 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
408 {
409         return 0;
410 }
411
412 static struct saa7146_extension extension;
413
414 static struct saa7146_pci_extension_data hexium_hv_pci6 = {
415         .ext_priv = "Hexium HV-PCI6 / Orion",
416         .ext = &extension,
417 };
418
419 static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
420         .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
421         .ext = &extension,
422 };
423
424 static struct saa7146_pci_extension_data hexium_orion_4bnc = {
425         .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
426         .ext = &extension,
427 };
428
429 static const struct pci_device_id pci_tbl[] = {
430         {
431          .vendor = PCI_VENDOR_ID_PHILIPS,
432          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
433          .subvendor = 0x0000,
434          .subdevice = 0x0000,
435          .driver_data = (unsigned long) &hexium_hv_pci6,
436          },
437         {
438          .vendor = PCI_VENDOR_ID_PHILIPS,
439          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
440          .subvendor = 0x17c8,
441          .subdevice = 0x0101,
442          .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
443          },
444         {
445          .vendor = PCI_VENDOR_ID_PHILIPS,
446          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
447          .subvendor = 0x17c8,
448          .subdevice = 0x2101,
449          .driver_data = (unsigned long) &hexium_orion_4bnc,
450          },
451         {
452          .vendor = 0,
453          }
454 };
455
456 MODULE_DEVICE_TABLE(pci, pci_tbl);
457
458 static struct saa7146_ext_vv vv_data = {
459         .inputs = HEXIUM_INPUTS,
460         .capabilities = 0,
461         .stds = &hexium_standards[0],
462         .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
463         .std_callback = &std_callback,
464 };
465
466 static struct saa7146_extension extension = {
467         .name = "hexium HV-PCI6 Orion",
468         .flags = 0,             // SAA7146_USE_I2C_IRQ,
469
470         .pci_tbl = &pci_tbl[0],
471         .module = THIS_MODULE,
472
473         .probe = hexium_probe,
474         .attach = hexium_attach,
475         .detach = hexium_detach,
476
477         .irq_mask = 0,
478         .irq_func = NULL,
479 };
480
481 static int __init hexium_init_module(void)
482 {
483         if (0 != saa7146_register_extension(&extension)) {
484                 DEB_S("failed to register extension\n");
485                 return -ENODEV;
486         }
487
488         return 0;
489 }
490
491 static void __exit hexium_cleanup_module(void)
492 {
493         saa7146_unregister_extension(&extension);
494 }
495
496 module_init(hexium_init_module);
497 module_exit(hexium_cleanup_module);
498
499 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
500 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
501 MODULE_LICENSE("GPL");