Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/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/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         hexium->i2c_adapter = (struct i2c_adapter) {
236                 .name = "hexium orion",
237         };
238         saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
239         if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
240                 DEB_S("cannot register i2c-device. skipping.\n");
241                 kfree(hexium);
242                 return -EFAULT;
243         }
244 
245         /* set SAA7110 control GPIO 0 */
246         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
247         /*  set HWControl GPIO number 2 */
248         saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
249 
250         mdelay(10);
251 
252         /* detect newer Hexium Orion cards by subsystem ids */
253         if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
254                 pr_info("device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs\n");
255                 /* we store the pointer in our private data field */
256                 dev->ext_priv = hexium;
257                 hexium->type = HEXIUM_ORION_1SVHS_3BNC;
258                 return 0;
259         }
260 
261         if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
262                 pr_info("device is a Hexium Orion w/ 4 BNC inputs\n");
263                 /* we store the pointer in our private data field */
264                 dev->ext_priv = hexium;
265                 hexium->type = HEXIUM_ORION_4BNC;
266                 return 0;
267         }
268 
269         /* check if this is an old hexium Orion card by looking at
270            a saa7110 at address 0x4e */
271         if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
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 
371         DEB_EE("\n");
372 
373         saa7146_vv_init(dev, &vv_data);
374         vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
375         vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
376         vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
377         if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
378                 pr_err("cannot register capture v4l2 device. skipping.\n");
379                 return -1;
380         }
381 
382         pr_err("found 'hexium orion' frame grabber-%d\n", hexium_num);
383         hexium_num++;
384 
385         /* the rest */
386         hexium->cur_input = 0;
387         hexium_init_done(dev);
388 
389         return 0;
390 }
391 
392 static int hexium_detach(struct saa7146_dev *dev)
393 {
394         struct hexium *hexium = (struct hexium *) dev->ext_priv;
395 
396         DEB_EE("dev:%p\n", dev);
397 
398         saa7146_unregister_device(&hexium->video_dev, dev);
399         saa7146_vv_release(dev);
400 
401         hexium_num--;
402 
403         i2c_del_adapter(&hexium->i2c_adapter);
404         kfree(hexium);
405         return 0;
406 }
407 
408 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
409 {
410         return 0;
411 }
412 
413 static struct saa7146_extension extension;
414 
415 static struct saa7146_pci_extension_data hexium_hv_pci6 = {
416         .ext_priv = "Hexium HV-PCI6 / Orion",
417         .ext = &extension,
418 };
419 
420 static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
421         .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
422         .ext = &extension,
423 };
424 
425 static struct saa7146_pci_extension_data hexium_orion_4bnc = {
426         .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
427         .ext = &extension,
428 };
429 
430 static struct pci_device_id pci_tbl[] = {
431         {
432          .vendor = PCI_VENDOR_ID_PHILIPS,
433          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
434          .subvendor = 0x0000,
435          .subdevice = 0x0000,
436          .driver_data = (unsigned long) &hexium_hv_pci6,
437          },
438         {
439          .vendor = PCI_VENDOR_ID_PHILIPS,
440          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
441          .subvendor = 0x17c8,
442          .subdevice = 0x0101,
443          .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
444          },
445         {
446          .vendor = PCI_VENDOR_ID_PHILIPS,
447          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
448          .subvendor = 0x17c8,
449          .subdevice = 0x2101,
450          .driver_data = (unsigned long) &hexium_orion_4bnc,
451          },
452         {
453          .vendor = 0,
454          }
455 };
456 
457 MODULE_DEVICE_TABLE(pci, pci_tbl);
458 
459 static struct saa7146_ext_vv vv_data = {
460         .inputs = HEXIUM_INPUTS,
461         .capabilities = 0,
462         .stds = &hexium_standards[0],
463         .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
464         .std_callback = &std_callback,
465 };
466 
467 static struct saa7146_extension extension = {
468         .name = "hexium HV-PCI6 Orion",
469         .flags = 0,             // SAA7146_USE_I2C_IRQ,
470 
471         .pci_tbl = &pci_tbl[0],
472         .module = THIS_MODULE,
473 
474         .probe = hexium_probe,
475         .attach = hexium_attach,
476         .detach = hexium_detach,
477 
478         .irq_mask = 0,
479         .irq_func = NULL,
480 };
481 
482 static int __init hexium_init_module(void)
483 {
484         if (0 != saa7146_register_extension(&extension)) {
485                 DEB_S("failed to register extension\n");
486                 return -ENODEV;
487         }
488 
489         return 0;
490 }
491 
492 static void __exit hexium_cleanup_module(void)
493 {
494         saa7146_unregister_extension(&extension);
495 }
496 
497 module_init(hexium_init_module);
498 module_exit(hexium_cleanup_module);
499 
500 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
501 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
502 MODULE_LICENSE("GPL");
503 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us