Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
425 giacomo 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 DEBUG_VARIABLE debug
25
 
26
#include <media/saa7146_vv.h>
27
 
28
static int debug = 0;
29
MODULE_PARM(debug, "i");
30
MODULE_PARM_DESC(debug, "debug verbosity");
31
 
32
/* global variables */
33
int hexium_num = 0;
34
 
35
#define HEXIUM_HV_PCI6_ORION            1
36
#define HEXIUM_ORION_1SVHS_3BNC         2
37
#define HEXIUM_ORION_4BNC               3
38
 
39
#define HEXIUM_INPUTS   9
40
static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
41
        { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
42
        { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
43
        { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
44
        { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
45
        { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
46
        { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
47
        { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
48
        { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
49
        { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
50
};
51
 
52
#define HEXIUM_AUDIOS   0
53
 
54
struct hexium_data
55
{
56
        s8 adr;
57
        u8 byte;
58
};
59
 
60
static struct saa7146_extension_ioctls ioctls[] = {
61
        { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
62
        { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
63
        { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
64
        { VIDIOC_S_STD,         SAA7146_AFTER },
65
        { 0,                    0 }
66
};
67
 
68
struct hexium
69
{
70
        int type;
71
        struct video_device     video_dev;
72
        struct i2c_adapter      i2c_adapter;   
73
        int cur_input;  /* current input */
74
};
75
 
76
/* Philips SAA7110 decoder default registers */
77
static u8 hexium_saa7110[53]={
78
/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
79
/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
80
/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
81
/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
82
/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
83
/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
84
/*30*/ 0x44,0x75,0x01,0x8C,0x03
85
};
86
 
87
static struct {
88
        struct hexium_data data[8];    
89
} hexium_input_select[] = {
90
{
91
        { /* cvbs 1 */
92
                { 0x06, 0x00 },
93
                { 0x20, 0xD9 },
94
                { 0x21, 0x17 }, // 0x16,
95
                { 0x22, 0x40 },
96
                { 0x2C, 0x03 },
97
                { 0x30, 0x44 },
98
                { 0x31, 0x75 }, // ??
99
                { 0x21, 0x16 }, // 0x03,
100
        }
101
}, {
102
        { /* cvbs 2 */
103
                { 0x06, 0x00 },
104
                { 0x20, 0x78 },
105
                { 0x21, 0x07 }, // 0x03,
106
                { 0x22, 0xD2 },
107
                { 0x2C, 0x83 },
108
                { 0x30, 0x60 },
109
                { 0x31, 0xB5 }, // ?
110
                { 0x21, 0x03 },
111
        }
112
}, {
113
        { /* cvbs 3 */
114
                { 0x06, 0x00 },
115
                { 0x20, 0xBA },
116
                { 0x21, 0x07 }, // 0x05,
117
                { 0x22, 0x91 },
118
                { 0x2C, 0x03 },
119
                { 0x30, 0x60 },
120
                { 0x31, 0xB5 }, // ??
121
                { 0x21, 0x05 }, // 0x03,
122
        }
123
}, {
124
        { /* cvbs 4 */
125
                { 0x06, 0x00 },
126
                { 0x20, 0xD8 },
127
                { 0x21, 0x17 }, // 0x16,
128
                { 0x22, 0x40 },
129
                { 0x2C, 0x03 },
130
                { 0x30, 0x44 },
131
                { 0x31, 0x75 }, // ??
132
                { 0x21, 0x16 }, // 0x03,
133
        }
134
}, {
135
        { /* cvbs 5 */
136
                { 0x06, 0x00 },
137
                { 0x20, 0xB8 },
138
                { 0x21, 0x07 }, // 0x05,
139
                { 0x22, 0x91 },
140
                { 0x2C, 0x03 },
141
                { 0x30, 0x60 },
142
                { 0x31, 0xB5 }, // ??
143
                { 0x21, 0x05 }, // 0x03,
144
        }
145
}, {
146
        { /* cvbs 6 */
147
                { 0x06, 0x00 },
148
                { 0x20, 0x7C },
149
                { 0x21, 0x07 }, // 0x03
150
                { 0x22, 0xD2 },
151
                { 0x2C, 0x83 },
152
                { 0x30, 0x60 },
153
                { 0x31, 0xB5 }, // ??
154
                { 0x21, 0x03 },
155
        }
156
}, {
157
        { /* y/c 1 */
158
                { 0x06, 0x80 },
159
                { 0x20, 0x59 },
160
                { 0x21, 0x17 },
161
                { 0x22, 0x42 },
162
                { 0x2C, 0xA3 },
163
                { 0x30, 0x44 },
164
                { 0x31, 0x75 },
165
                { 0x21, 0x12 },
166
        }
167
}, {
168
        { /* y/c 2 */
169
                { 0x06, 0x80 },
170
                { 0x20, 0x9A },
171
                { 0x21, 0x17 },
172
                { 0x22, 0xB1 },
173
                { 0x2C, 0x13 },
174
                { 0x30, 0x60 },
175
                { 0x31, 0xB5 },
176
                { 0x21, 0x14 },
177
        }
178
}, {
179
        { /* y/c 3 */
180
                { 0x06, 0x80 },
181
                { 0x20, 0x3C },
182
                { 0x21, 0x27 },
183
                { 0x22, 0xC1 },
184
                { 0x2C, 0x23 },
185
                { 0x30, 0x44 },
186
                { 0x31, 0x75 },
187
                { 0x21, 0x21 },
188
        }
189
}      
190
};
191
 
192
static struct saa7146_standard hexium_standards[] = {
193
        {
194
                .name   = "PAL",        .id     = V4L2_STD_PAL,
195
                .v_offset       = 16,   .v_field        = 288,  .v_calc         = 576,
196
                .h_offset       = 1,    .h_pixels       = 680,  .h_calc         = 680+1,
197
                .v_max_out      = 576,  .h_max_out      = 768,
198
        }, {
199
                .name   = "NTSC",       .id     = V4L2_STD_NTSC,
200
                .v_offset       = 16,   .v_field        = 240,  .v_calc         = 480,
201
                .h_offset       = 1,    .h_pixels       = 640,  .h_calc         = 641+1,
202
                .v_max_out      = 480,  .h_max_out      = 640,
203
        }, {
204
                .name   = "SECAM",      .id     = V4L2_STD_SECAM,
205
                .v_offset       = 16,   .v_field        = 288,  .v_calc         = 576,
206
                .h_offset       = 1,    .h_pixels       = 720,  .h_calc         = 720+1,
207
                .v_max_out      = 576,  .h_max_out      = 768,
208
        }
209
};             
210
 
211
/* this is only called for old HV-PCI6/Orion cards
212
   without eeprom */
213
static int hexium_probe(struct saa7146_dev *dev)
214
{
215
        struct hexium *hexium = 0;
216
        union i2c_smbus_data data;
217
        int err = 0;
218
 
219
        DEB_EE((".\n"));
220
 
221
        /* there are no hexium orion cards with revision 0 saa7146s */
222
        if (0 == dev->revision) {
223
                return -EFAULT;
224
        }
225
 
226
        hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
227
        if (NULL == hexium) {
228
                printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
229
                return -ENOMEM;
230
        }
231
        memset(hexium, 0x0, sizeof(struct hexium));
232
 
233
        saa7146_write(dev, DD1_INIT, 0x01000100);
234
        saa7146_write(dev, DD1_STREAM_B, 0x00000000);
235
        saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
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) {
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
                printk("hexium_orion: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
254
                /* we store the pointer in our private data field */
255
                (struct hexium *) 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
                printk("hexium_orion: device is a Hexium Orion w/ 4 BNC inputs.\n");
262
                /* we store the pointer in our private data field */
263
                (struct hexium *) 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
                printk("hexium_orion: device is a Hexium HV-PCI6/Orion (old).\n");
272
                /* we store the pointer in our private data field */
273
                (struct hexium *) 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
                        printk("hexium_orion: 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
                printk("%d: 0x%02x => 0x%02x\n",input, adr,data.byte);
320
        }
321
 
322
        return 0;
323
}
324
 
325
static struct saa7146_ext_vv vv_data;
326
 
327
/* this function only gets called when the probing was successful */
328
static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
329
{
330
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
331
 
332
        DEB_EE((".\n"));
333
 
334
        saa7146_vv_init(dev, &vv_data);
335
        if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
336
                printk("hexium_orion: cannot register capture v4l2 device. skipping.\n");
337
                return -1;
338
        }
339
 
340
        printk("hexium_orion: found 'hexium orion' frame grabber-%d.\n", hexium_num);
341
        hexium_num++;
342
 
343
        /* the rest */
344
        hexium->cur_input = 0;
345
        hexium_init_done(dev);
346
 
347
        return 0;
348
}
349
 
350
static int hexium_detach(struct saa7146_dev *dev)
351
{
352
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
353
 
354
        DEB_EE(("dev:%p\n", dev));
355
 
356
        saa7146_unregister_device(&hexium->video_dev, dev);
357
        saa7146_vv_release(dev);
358
 
359
        hexium_num--;
360
 
361
        i2c_del_adapter(&hexium->i2c_adapter);
362
        kfree(hexium);
363
        return 0;
364
}
365
 
366
static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
367
{
368
        struct saa7146_dev *dev = fh->dev;
369
        struct hexium *hexium = (struct hexium *) dev->ext_priv;
370
/*
371
        struct saa7146_vv *vv = dev->vv_data;
372
*/
373
        switch (cmd) {
374
        case VIDIOC_ENUMINPUT:
375
                {
376
                        struct v4l2_input *i = arg;
377
                        DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
378
 
379
                        if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
380
                                return -EINVAL;
381
                        }
382
 
383
                        memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
384
 
385
                        DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
386
                        return 0;
387
                }
388
        case VIDIOC_G_INPUT:
389
                {
390
                        int *input = (int *) arg;
391
                        *input = hexium->cur_input;
392
 
393
                        DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
394
                        return 0;
395
                }
396
        case VIDIOC_S_INPUT:
397
                {
398
                        int input = *(int *) arg;
399
 
400
                        if (input < 0 || input >= HEXIUM_INPUTS) {
401
                                return -EINVAL;
402
                        }
403
 
404
                        hexium->cur_input = input;
405
                        hexium_set_input(hexium, input);
406
 
407
                        return 0;
408
                }
409
        default:
410
/*
411
                DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
412
*/
413
                return -ENOIOCTLCMD;
414
        }
415
        return 0;
416
}
417
 
418
static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
419
{
420
        return 0;
421
}
422
 
423
static struct saa7146_extension extension;
424
 
425
static struct saa7146_pci_extension_data hexium_hv_pci6 = {
426
        .ext_priv = "Hexium HV-PCI6 / Orion",
427
        .ext = &extension,
428
};
429
 
430
static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
431
        .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
432
        .ext = &extension,
433
};
434
 
435
static struct saa7146_pci_extension_data hexium_orion_4bnc = {
436
        .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
437
        .ext = &extension,
438
};
439
 
440
static struct pci_device_id pci_tbl[] = {
441
        {
442
         .vendor = PCI_VENDOR_ID_PHILIPS,
443
         .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
444
         .subvendor = 0x0000,
445
         .subdevice = 0x0000,
446
         .driver_data = (unsigned long) &hexium_hv_pci6,
447
         },
448
        {
449
         .vendor = PCI_VENDOR_ID_PHILIPS,
450
         .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
451
         .subvendor = 0x17c8,
452
         .subdevice = 0x0101,
453
         .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
454
         },
455
        {
456
         .vendor = PCI_VENDOR_ID_PHILIPS,
457
         .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
458
         .subvendor = 0x17c8,
459
         .subdevice = 0x2101,
460
         .driver_data = (unsigned long) &hexium_orion_4bnc,
461
         },
462
        {
463
         .vendor = 0,
464
         }
465
};
466
 
467
MODULE_DEVICE_TABLE(pci, pci_tbl);
468
 
469
static struct saa7146_ext_vv vv_data = {
470
        .inputs = HEXIUM_INPUTS,
471
        .capabilities = 0,
472
        .stds = &hexium_standards[0],
473
        .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
474
        .std_callback = &std_callback,
475
        .ioctls = &ioctls[0],
476
        .ioctl = hexium_ioctl,
477
};
478
 
479
static struct saa7146_extension extension = {
480
        .name = "hexium HV-PCI6/Orion",
481
        .flags = 0,             // SAA7146_USE_I2C_IRQ,
482
 
483
        .pci_tbl = &pci_tbl[0],
484
        .module = THIS_MODULE,
485
 
486
        .probe = hexium_probe,
487
        .attach = hexium_attach,
488
        .detach = hexium_detach,
489
 
490
        .irq_mask = 0,
491
        .irq_func = NULL,
492
};
493
 
494
int __init hexium_init_module(void)
495
{
496
        if (0 != saa7146_register_extension(&extension)) {
497
                DEB_S(("failed to register extension.\n"));
498
                return -ENODEV;
499
        }
500
 
501
        return 0;
502
}
503
 
504
void __exit hexium_cleanup_module(void)
505
{
506
        saa7146_unregister_extension(&extension);
507
}
508
 
509
module_init(hexium_init_module);
510
module_exit(hexium_cleanup_module);
511
 
512
MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
513
MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
514
MODULE_LICENSE("GPL");