]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/media/video/hexium_orion.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/linux-dm
[mirror_ubuntu-bionic-kernel.git] / drivers / media / video / hexium_orion.c
CommitLineData
1da177e4
LT
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.
a8733ca5 6
1da177e4
LT
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
44d0b80e
JP
24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
1da177e4
LT
26#define DEBUG_VARIABLE debug
27
28#include <media/saa7146_vv.h>
29
ff699e6b 30static int debug;
1da177e4
LT
31module_param(debug, int, 0);
32MODULE_PARM_DESC(debug, "debug verbosity");
33
34/* global variables */
ff699e6b 35static int hexium_num;
1da177e4
LT
36
37#define HEXIUM_HV_PCI6_ORION 1
38#define HEXIUM_ORION_1SVHS_3BNC 2
39#define HEXIUM_ORION_4BNC 3
40
41#define HEXIUM_INPUTS 9
42static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
657f2271
HV
43 { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
44 { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
45 { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
46 { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
47 { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
48 { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
49 { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
50 { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
51 { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
1da177e4
LT
52};
53
54#define HEXIUM_AUDIOS 0
55
56struct hexium_data
57{
58 s8 adr;
59 u8 byte;
60};
61
1da177e4
LT
62struct hexium
63{
64 int type;
65 struct video_device *video_dev;
a8733ca5 66 struct i2c_adapter i2c_adapter;
1da177e4
LT
67
68 int cur_input; /* current input */
69};
70
71/* Philips SAA7110 decoder default registers */
72static u8 hexium_saa7110[53]={
73/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
74/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
75/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
76/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
77/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
78/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
79/*30*/ 0x44,0x75,0x01,0x8C,0x03
80};
81
82static struct {
a8733ca5 83 struct hexium_data data[8];
1da177e4
LT
84} hexium_input_select[] = {
85{
86 { /* cvbs 1 */
87 { 0x06, 0x00 },
88 { 0x20, 0xD9 },
89 { 0x21, 0x17 }, // 0x16,
90 { 0x22, 0x40 },
91 { 0x2C, 0x03 },
92 { 0x30, 0x44 },
93 { 0x31, 0x75 }, // ??
94 { 0x21, 0x16 }, // 0x03,
95 }
96}, {
97 { /* cvbs 2 */
98 { 0x06, 0x00 },
99 { 0x20, 0x78 },
100 { 0x21, 0x07 }, // 0x03,
101 { 0x22, 0xD2 },
102 { 0x2C, 0x83 },
103 { 0x30, 0x60 },
104 { 0x31, 0xB5 }, // ?
105 { 0x21, 0x03 },
106 }
107}, {
108 { /* cvbs 3 */
109 { 0x06, 0x00 },
110 { 0x20, 0xBA },
111 { 0x21, 0x07 }, // 0x05,
112 { 0x22, 0x91 },
113 { 0x2C, 0x03 },
114 { 0x30, 0x60 },
115 { 0x31, 0xB5 }, // ??
116 { 0x21, 0x05 }, // 0x03,
117 }
118}, {
119 { /* cvbs 4 */
120 { 0x06, 0x00 },
121 { 0x20, 0xD8 },
122 { 0x21, 0x17 }, // 0x16,
123 { 0x22, 0x40 },
124 { 0x2C, 0x03 },
125 { 0x30, 0x44 },
126 { 0x31, 0x75 }, // ??
127 { 0x21, 0x16 }, // 0x03,
128 }
129}, {
130 { /* cvbs 5 */
131 { 0x06, 0x00 },
132 { 0x20, 0xB8 },
133 { 0x21, 0x07 }, // 0x05,
134 { 0x22, 0x91 },
135 { 0x2C, 0x03 },
136 { 0x30, 0x60 },
137 { 0x31, 0xB5 }, // ??
138 { 0x21, 0x05 }, // 0x03,
139 }
140}, {
141 { /* cvbs 6 */
142 { 0x06, 0x00 },
143 { 0x20, 0x7C },
144 { 0x21, 0x07 }, // 0x03
145 { 0x22, 0xD2 },
146 { 0x2C, 0x83 },
147 { 0x30, 0x60 },
148 { 0x31, 0xB5 }, // ??
149 { 0x21, 0x03 },
a8733ca5 150 }
1da177e4
LT
151}, {
152 { /* y/c 1 */
153 { 0x06, 0x80 },
154 { 0x20, 0x59 },
155 { 0x21, 0x17 },
156 { 0x22, 0x42 },
157 { 0x2C, 0xA3 },
158 { 0x30, 0x44 },
159 { 0x31, 0x75 },
160 { 0x21, 0x12 },
161 }
162}, {
163 { /* y/c 2 */
164 { 0x06, 0x80 },
165 { 0x20, 0x9A },
166 { 0x21, 0x17 },
167 { 0x22, 0xB1 },
168 { 0x2C, 0x13 },
169 { 0x30, 0x60 },
170 { 0x31, 0xB5 },
171 { 0x21, 0x14 },
172 }
173}, {
174 { /* y/c 3 */
175 { 0x06, 0x80 },
176 { 0x20, 0x3C },
177 { 0x21, 0x27 },
178 { 0x22, 0xC1 },
179 { 0x2C, 0x23 },
180 { 0x30, 0x44 },
181 { 0x31, 0x75 },
182 { 0x21, 0x21 },
183 }
a8733ca5 184}
1da177e4
LT
185};
186
187static struct saa7146_standard hexium_standards[] = {
188 {
189 .name = "PAL", .id = V4L2_STD_PAL,
190 .v_offset = 16, .v_field = 288,
191 .h_offset = 1, .h_pixels = 680,
192 .v_max_out = 576, .h_max_out = 768,
193 }, {
194 .name = "NTSC", .id = V4L2_STD_NTSC,
195 .v_offset = 16, .v_field = 240,
196 .h_offset = 1, .h_pixels = 640,
197 .v_max_out = 480, .h_max_out = 640,
198 }, {
199 .name = "SECAM", .id = V4L2_STD_SECAM,
200 .v_offset = 16, .v_field = 288,
201 .h_offset = 1, .h_pixels = 720,
202 .v_max_out = 576, .h_max_out = 768,
203 }
a8733ca5 204};
1da177e4
LT
205
206/* this is only called for old HV-PCI6/Orion cards
207 without eeprom */
208static int hexium_probe(struct saa7146_dev *dev)
209{
210 struct hexium *hexium = NULL;
211 union i2c_smbus_data data;
212 int err = 0;
213
44d0b80e 214 DEB_EE("\n");
1da177e4
LT
215
216 /* there are no hexium orion cards with revision 0 saa7146s */
217 if (0 == dev->revision) {
218 return -EFAULT;
219 }
220
7408187d 221 hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
1da177e4 222 if (NULL == hexium) {
44d0b80e 223 pr_err("hexium_probe: not enough kernel memory\n");
1da177e4
LT
224 return -ENOMEM;
225 }
1da177e4
LT
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 hexium->i2c_adapter = (struct i2c_adapter) {
1da177e4
LT
235 .name = "hexium orion",
236 };
237 saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
238 if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
44d0b80e 239 DEB_S("cannot register i2c-device. skipping.\n");
1da177e4
LT
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) {
44d0b80e 253 pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
1da177e4
LT
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) {
44d0b80e 261 pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
1da177e4
LT
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
a8733ca5 268 /* check if this is an old hexium Orion card by looking at
1da177e4
LT
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))) {
44d0b80e 271 pr_info("device is a Hexium HV-PCI6/Orion (old)\n");
1da177e4
LT
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. */
287static 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
44d0b80e 293 DEB_D("hexium_init_done called\n");
1da177e4
LT
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)) {
44d0b80e 299 pr_err("failed for address 0x%02x\n", i);
1da177e4
LT
300 }
301 }
302
303 return 0;
304}
305
306static int hexium_set_input(struct hexium *hexium, int input)
307{
308 union i2c_smbus_data data;
309 int i = 0;
a8733ca5 310
44d0b80e 311 DEB_D("\n");
1da177e4
LT
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 }
44d0b80e 319 pr_debug("%d: 0x%02x => 0x%02x\n", input, adr, data.byte);
1da177e4
LT
320 }
321
322 return 0;
323}
324
b960074f
HV
325static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
326{
44d0b80e 327 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
b960074f 328
223ffe5f 329 if (i->index >= HEXIUM_INPUTS)
b960074f
HV
330 return -EINVAL;
331
332 memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
333
44d0b80e 334 DEB_D("v4l2_ioctl: VIDIOC_ENUMINPUT %d\n", i->index);
b960074f
HV
335 return 0;
336}
337
338static 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
44d0b80e 345 DEB_D("VIDIOC_G_INPUT: %d\n", *input);
b960074f
HV
346 return 0;
347}
348
349static 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
f14a2972 354 if (input >= HEXIUM_INPUTS)
b960074f
HV
355 return -EINVAL;
356
357 hexium->cur_input = input;
358 hexium_set_input(hexium, input);
359
360 return 0;
361}
362
1da177e4
LT
363static struct saa7146_ext_vv vv_data;
364
365/* this function only gets called when the probing was successful */
366static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
367{
368 struct hexium *hexium = (struct hexium *) dev->ext_priv;
369
44d0b80e 370 DEB_EE("\n");
1da177e4
LT
371
372 saa7146_vv_init(dev, &vv_data);
b960074f
HV
373 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
374 vv_data.ops.vidioc_g_input = vidioc_g_input;
375 vv_data.ops.vidioc_s_input = vidioc_s_input;
1da177e4 376 if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
44d0b80e 377 pr_err("cannot register capture v4l2 device. skipping.\n");
1da177e4
LT
378 return -1;
379 }
380
44d0b80e 381 pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
1da177e4
LT
382 hexium_num++;
383
384 /* the rest */
385 hexium->cur_input = 0;
386 hexium_init_done(dev);
387
388 return 0;
389}
390
391static int hexium_detach(struct saa7146_dev *dev)
392{
393 struct hexium *hexium = (struct hexium *) dev->ext_priv;
394
44d0b80e 395 DEB_EE("dev:%p\n", dev);
1da177e4
LT
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
1da177e4
LT
407static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
408{
409 return 0;
410}
411
412static struct saa7146_extension extension;
413
414static struct saa7146_pci_extension_data hexium_hv_pci6 = {
415 .ext_priv = "Hexium HV-PCI6 / Orion",
416 .ext = &extension,
417};
418
419static 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
424static struct saa7146_pci_extension_data hexium_orion_4bnc = {
425 .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
426 .ext = &extension,
427};
428
429static 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
456MODULE_DEVICE_TABLE(pci, pci_tbl);
457
458static 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,
1da177e4
LT
464};
465
466static struct saa7146_extension extension = {
922f77de 467 .name = "hexium HV-PCI6 Orion",
1da177e4
LT
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
481static int __init hexium_init_module(void)
482{
483 if (0 != saa7146_register_extension(&extension)) {
44d0b80e 484 DEB_S("failed to register extension\n");
1da177e4
LT
485 return -ENODEV;
486 }
487
488 return 0;
489}
490
491static void __exit hexium_cleanup_module(void)
492{
493 saa7146_unregister_extension(&extension);
494}
495
496module_init(hexium_init_module);
497module_exit(hexium_cleanup_module);
498
499MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
500MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
501MODULE_LICENSE("GPL");