Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / media / video / hexium_gemini.c
1 /*
2     hexium_gemini.c - v4l2 driver for Hexium Gemini 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_param(debug, int, 0);
30 MODULE_PARM_DESC(debug, "debug verbosity");
31
32 /* global variables */
33 static int hexium_num = 0;
34
35 #define HEXIUM_GEMINI                   4
36 #define HEXIUM_GEMINI_DUAL              5
37
38 #define HEXIUM_INPUTS   9
39 static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
40         { 0, "CVBS 1",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
41         { 1, "CVBS 2",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
42         { 2, "CVBS 3",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
43         { 3, "CVBS 4",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
44         { 4, "CVBS 5",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
45         { 5, "CVBS 6",  V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
46         { 6, "Y/C 1",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
47         { 7, "Y/C 2",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
48         { 8, "Y/C 3",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
49 };
50
51 #define HEXIUM_AUDIOS   0
52
53 struct hexium_data
54 {
55         s8 adr;
56         u8 byte;
57 };
58
59 static struct saa7146_extension_ioctls ioctls[] = {
60         { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
61         { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
62         { VIDIOC_QUERYCTRL,     SAA7146_BEFORE },
63         { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
64         { VIDIOC_S_STD,         SAA7146_AFTER },
65         { VIDIOC_G_CTRL,        SAA7146_BEFORE },
66         { VIDIOC_S_CTRL,        SAA7146_BEFORE },
67         { 0,                    0 }
68 };
69
70 #define HEXIUM_CONTROLS 1
71 static struct v4l2_queryctrl hexium_controls[] = {
72         { V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
73 };
74
75 #define HEXIUM_GEMINI_V_1_0             1
76 #define HEXIUM_GEMINI_DUAL_V_1_0        2
77
78 struct hexium
79 {
80         int type;
81
82         struct video_device     *video_dev;
83         struct i2c_adapter      i2c_adapter;
84                 
85         int             cur_input;      /* current input */
86         v4l2_std_id     cur_std;        /* current standard */
87         int             cur_bw;         /* current black/white status */
88 };
89
90 /* Samsung KS0127B decoder default registers */
91 static u8 hexium_ks0127b[0x100]={
92 /*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
93 /*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
94 /*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
95 /*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
96 /*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
97 /*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
98 /*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
99 /*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
100 /*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
101 /*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102 /*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
103 /*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104 /*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
105 /*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
106 /*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
107 /*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
108 /*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
109 /*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110 /*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
111 /*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
112 /*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
113 /*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
114 /*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
115 /*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
116 /*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117 /*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118 /*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 /*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120 /*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121 /*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 /*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
123 /*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
124 };
125
126 static struct hexium_data hexium_pal[] = {
127         { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
128 };
129
130 static struct hexium_data hexium_pal_bw[] = {
131         { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
132 };
133
134 static struct hexium_data hexium_ntsc[] = {
135         { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
136 };
137
138 static struct hexium_data hexium_ntsc_bw[] = {
139         { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
140 };
141
142 static struct hexium_data hexium_secam[] = {
143         { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
144 };
145
146 static struct hexium_data hexium_input_select[] = {
147         { 0x02, 0x60 },
148         { 0x02, 0x64 },
149         { 0x02, 0x61 },
150         { 0x02, 0x65 },
151         { 0x02, 0x62 },
152         { 0x02, 0x66 },
153         { 0x02, 0x68 },
154         { 0x02, 0x69 },
155         { 0x02, 0x6A },
156 };
157
158 /* fixme: h_offset = 0 for Hexium Gemini *Dual*, which
159    are currently *not* supported*/
160 static struct saa7146_standard hexium_standards[] = {
161         {
162                 .name   = "PAL",        .id     = V4L2_STD_PAL,
163                 .v_offset       = 28,   .v_field        = 288,
164                 .h_offset       = 1,    .h_pixels       = 680,
165                 .v_max_out      = 576,  .h_max_out      = 768,
166         }, {
167                 .name   = "NTSC",       .id     = V4L2_STD_NTSC,
168                 .v_offset       = 28,   .v_field        = 240,
169                 .h_offset       = 1,    .h_pixels       = 640,
170                 .v_max_out      = 480,  .h_max_out      = 640,
171         }, {
172                 .name   = "SECAM",      .id     = V4L2_STD_SECAM,
173                 .v_offset       = 28,   .v_field        = 288,
174                 .h_offset       = 1,    .h_pixels       = 720,
175                 .v_max_out      = 576,  .h_max_out      = 768,
176         }
177 };              
178
179 /* bring hardware to a sane state. this has to be done, just in case someone
180    wants to capture from this device before it has been properly initialized.
181    the capture engine would badly fail, because no valid signal arrives on the
182    saa7146, thus leading to timeouts and stuff. */
183 static int hexium_init_done(struct saa7146_dev *dev)
184 {
185         struct hexium *hexium = (struct hexium *) dev->ext_priv;
186         union i2c_smbus_data data;
187         int i = 0;
188
189         DEB_D(("hexium_init_done called.\n"));
190
191         /* initialize the helper ics to useful values */
192         for (i = 0; i < sizeof(hexium_ks0127b); i++) {
193                 data.byte = hexium_ks0127b[i];
194                 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
195                         printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i);
196                 }
197         }
198
199         return 0;
200 }
201
202 static int hexium_set_input(struct hexium *hexium, int input)
203 {
204         union i2c_smbus_data data;
205
206         DEB_D((".\n"));
207
208         data.byte = hexium_input_select[input].byte;
209         if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
210                 return -1;
211         }
212
213         return 0;
214 }
215
216 static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
217 {
218         union i2c_smbus_data data;
219         int i = 0;
220
221         DEB_D((".\n"));
222
223         while (vdec[i].adr != -1) {
224                 data.byte = vdec[i].byte;
225                 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
226                         printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i);
227                         return -1;
228                 }
229                 i++;
230         }
231         return 0;
232 }
233
234 static struct saa7146_ext_vv vv_data;
235
236 /* this function only gets called when the probing was successful */
237 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
238 {
239         struct hexium *hexium = (struct hexium *) dev->ext_priv;
240
241         DEB_EE((".\n"));
242
243         hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
244         if (NULL == hexium) {
245                 printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
246                 return -ENOMEM;
247         }
248         memset(hexium, 0x0, sizeof(struct hexium));
249         dev->ext_priv = hexium;
250
251         /* enable i2c-port pins */
252         saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
253
254         hexium->i2c_adapter = (struct i2c_adapter) {
255                 .class = I2C_CLASS_TV_ANALOG,
256                 .name = "hexium gemini",
257         };
258         saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
259         if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
260                 DEB_S(("cannot register i2c-device. skipping.\n"));
261                 kfree(hexium);
262                 return -EFAULT;
263         }
264
265         /*  set HWControl GPIO number 2 */
266         saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
267
268         saa7146_write(dev, DD1_INIT, 0x07000700);
269         saa7146_write(dev, DD1_STREAM_B, 0x00000000);
270         saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
271
272         /* the rest */
273         hexium->cur_input = 0;
274         hexium_init_done(dev);
275
276         hexium_set_standard(hexium, hexium_pal);
277         hexium->cur_std = V4L2_STD_PAL;
278
279         hexium_set_input(hexium, 0);
280         hexium->cur_input = 0;
281
282         saa7146_vv_init(dev, &vv_data);
283         if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) {
284                 printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
285                 return -1;
286         }
287
288         printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
289         hexium_num++;
290
291         return 0;
292 }
293
294 static int hexium_detach(struct saa7146_dev *dev)
295 {
296         struct hexium *hexium = (struct hexium *) dev->ext_priv;
297
298         DEB_EE(("dev:%p\n", dev));
299
300         saa7146_unregister_device(&hexium->video_dev, dev);
301         saa7146_vv_release(dev);
302
303         hexium_num--;
304
305         i2c_del_adapter(&hexium->i2c_adapter);
306         kfree(hexium);
307         return 0;
308 }
309
310 static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
311 {
312         struct saa7146_dev *dev = fh->dev;
313         struct hexium *hexium = (struct hexium *) dev->ext_priv;
314 /*
315         struct saa7146_vv *vv = dev->vv_data; 
316 */
317         switch (cmd) {
318         case VIDIOC_ENUMINPUT:
319                 {
320                         struct v4l2_input *i = arg;
321                         DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
322
323                         if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
324                                 return -EINVAL;
325                         }
326
327                         memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
328
329                         DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
330                         return 0;
331                 }
332         case VIDIOC_G_INPUT:
333                 {
334                         int *input = (int *) arg;
335                         *input = hexium->cur_input;
336
337                         DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
338                         return 0;
339                 }
340         case VIDIOC_S_INPUT:
341                 {
342                         int input = *(int *) arg;
343
344                         DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
345
346                         if (input < 0 || input >= HEXIUM_INPUTS) {
347                                 return -EINVAL;
348                         }
349
350                         hexium->cur_input = input;
351                         hexium_set_input(hexium, input);
352
353                         return 0;
354                 }
355                 /* the saa7146 provides some controls (brightness, contrast, saturation)
356                    which gets registered *after* this function. because of this we have
357                    to return with a value != 0 even if the function succeded.. */
358         case VIDIOC_QUERYCTRL:
359                 {
360                         struct v4l2_queryctrl *qc = arg;
361                         int i;
362
363                         for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
364                                 if (hexium_controls[i].id == qc->id) {
365                                         *qc = hexium_controls[i];
366                                         DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
367                                         return 0;
368                                 }
369                         }
370                         return -EAGAIN;
371                 }
372         case VIDIOC_G_CTRL:
373                 {
374                         struct v4l2_control *vc = arg;
375                         int i;
376
377                         for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
378                                 if (hexium_controls[i].id == vc->id) {
379                                         break;
380                                 }
381                         }
382
383                         if (i < 0) {
384                                 return -EAGAIN;
385                         }
386
387                         switch (vc->id) {
388                         case V4L2_CID_PRIVATE_BASE:{
389                                         vc->value = hexium->cur_bw;
390                                         DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
391                                         return 0;
392                                 }
393                         }
394                         return -EINVAL;
395                 }
396
397         case VIDIOC_S_CTRL:
398                 {
399                         struct v4l2_control *vc = arg;
400                         int i = 0;
401
402                         for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
403                                 if (hexium_controls[i].id == vc->id) {
404                                         break;
405                                 }
406                         }
407
408                         if (i < 0) {
409                                 return -EAGAIN;
410                         }
411
412                         switch (vc->id) {
413                         case V4L2_CID_PRIVATE_BASE:{
414                                         hexium->cur_bw = vc->value;
415                                         break;
416                                 }
417                         }
418
419                         DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
420
421                         if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
422                                 hexium_set_standard(hexium, hexium_pal);
423                                 return 0;
424                         }
425                         if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
426                                 hexium_set_standard(hexium, hexium_ntsc);
427                                 return 0;
428                         }
429                         if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
430                                 hexium_set_standard(hexium, hexium_secam);
431                                 return 0;
432                         }
433                         if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
434                                 hexium_set_standard(hexium, hexium_pal_bw);
435                                 return 0;
436                         }
437                         if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
438                                 hexium_set_standard(hexium, hexium_ntsc_bw);
439                                 return 0;
440                         }
441                         if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
442                                 /* fixme: is there no bw secam mode? */
443                                 return -EINVAL;
444                         }
445
446                         return -EINVAL;
447                 }
448         default:
449 /*
450                 DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
451 */
452                 return -ENOIOCTLCMD;
453         }
454         return 0;
455 }
456
457 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
458 {
459         struct hexium *hexium = (struct hexium *) dev->ext_priv;
460
461         if (V4L2_STD_PAL == std->id) {
462                 hexium_set_standard(hexium, hexium_pal);
463                 hexium->cur_std = V4L2_STD_PAL;
464                 return 0;
465         } else if (V4L2_STD_NTSC == std->id) {
466                 hexium_set_standard(hexium, hexium_ntsc);
467                 hexium->cur_std = V4L2_STD_NTSC;
468                 return 0;
469         } else if (V4L2_STD_SECAM == std->id) {
470                 hexium_set_standard(hexium, hexium_secam);
471                 hexium->cur_std = V4L2_STD_SECAM;
472                 return 0;
473         }
474
475         return -1;
476 }
477
478 static struct saa7146_extension hexium_extension;
479
480 static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
481         .ext_priv = "Hexium Gemini (4 BNC)",
482         .ext = &hexium_extension,
483 };
484
485 static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
486         .ext_priv = "Hexium Gemini Dual (4 BNC)",
487         .ext = &hexium_extension,
488 };
489
490 static struct pci_device_id pci_tbl[] = {
491         {
492          .vendor = PCI_VENDOR_ID_PHILIPS,
493          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
494          .subvendor = 0x17c8,
495          .subdevice = 0x2401,
496          .driver_data = (unsigned long) &hexium_gemini_4bnc,
497          },
498         {
499          .vendor = PCI_VENDOR_ID_PHILIPS,
500          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
501          .subvendor = 0x17c8,
502          .subdevice = 0x2402,
503          .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
504          },
505         {
506          .vendor = 0,
507          }
508 };
509
510 MODULE_DEVICE_TABLE(pci, pci_tbl);
511
512 static struct saa7146_ext_vv vv_data = {
513         .inputs = HEXIUM_INPUTS,
514         .capabilities = 0,
515         .stds = &hexium_standards[0],
516         .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
517         .std_callback = &std_callback,
518         .ioctls = &ioctls[0],
519         .ioctl = hexium_ioctl,
520 };
521
522 static struct saa7146_extension hexium_extension = {
523         .name = "hexium gemini",
524         .flags = SAA7146_USE_I2C_IRQ,
525
526         .pci_tbl = &pci_tbl[0],
527         .module = THIS_MODULE,
528
529         .attach = hexium_attach,
530         .detach = hexium_detach,
531
532         .irq_mask = 0,
533         .irq_func = NULL,
534 };
535
536 static int __init hexium_init_module(void)
537 {
538         if (0 != saa7146_register_extension(&hexium_extension)) {
539                 DEB_S(("failed to register extension.\n"));
540                 return -ENODEV;
541         }
542
543         return 0;
544 }
545
546 static void __exit hexium_cleanup_module(void)
547 {
548         saa7146_unregister_extension(&hexium_extension);
549 }
550
551 module_init(hexium_init_module);
552 module_exit(hexium_cleanup_module);
553
554 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
555 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
556 MODULE_LICENSE("GPL");