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