Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / 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;
29 module_param(debug, int, 0);
30 MODULE_PARM_DESC(debug, "debug verbosity");
31
32 /* global variables */
33 static int hexium_num;
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 = kzalloc(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         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         hexium->i2c_adapter = (struct i2c_adapter) {
254                 .class = I2C_CLASS_TV_ANALOG,
255                 .name = "hexium gemini",
256         };
257         saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
258         if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
259                 DEB_S(("cannot register i2c-device. skipping.\n"));
260                 kfree(hexium);
261                 return -EFAULT;
262         }
263
264         /*  set HWControl GPIO number 2 */
265         saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
266
267         saa7146_write(dev, DD1_INIT, 0x07000700);
268         saa7146_write(dev, DD1_STREAM_B, 0x00000000);
269         saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
270
271         /* the rest */
272         hexium->cur_input = 0;
273         hexium_init_done(dev);
274
275         hexium_set_standard(hexium, hexium_pal);
276         hexium->cur_std = V4L2_STD_PAL;
277
278         hexium_set_input(hexium, 0);
279         hexium->cur_input = 0;
280
281         saa7146_vv_init(dev, &vv_data);
282         if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) {
283                 printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
284                 return -1;
285         }
286
287         printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num);
288         hexium_num++;
289
290         return 0;
291 }
292
293 static int hexium_detach(struct saa7146_dev *dev)
294 {
295         struct hexium *hexium = (struct hexium *) dev->ext_priv;
296
297         DEB_EE(("dev:%p\n", dev));
298
299         saa7146_unregister_device(&hexium->video_dev, dev);
300         saa7146_vv_release(dev);
301
302         hexium_num--;
303
304         i2c_del_adapter(&hexium->i2c_adapter);
305         kfree(hexium);
306         return 0;
307 }
308
309 static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
310 {
311         struct saa7146_dev *dev = fh->dev;
312         struct hexium *hexium = (struct hexium *) dev->ext_priv;
313 /*
314         struct saa7146_vv *vv = dev->vv_data;
315 */
316         switch (cmd) {
317         case VIDIOC_ENUMINPUT:
318                 {
319                         struct v4l2_input *i = arg;
320                         DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
321
322                         if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
323                                 return -EINVAL;
324                         }
325
326                         memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
327
328                         DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
329                         return 0;
330                 }
331         case VIDIOC_G_INPUT:
332                 {
333                         int *input = (int *) arg;
334                         *input = hexium->cur_input;
335
336                         DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
337                         return 0;
338                 }
339         case VIDIOC_S_INPUT:
340                 {
341                         int input = *(int *) arg;
342
343                         DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
344
345                         if (input < 0 || input >= HEXIUM_INPUTS) {
346                                 return -EINVAL;
347                         }
348
349                         hexium->cur_input = input;
350                         hexium_set_input(hexium, input);
351
352                         return 0;
353                 }
354                 /* the saa7146 provides some controls (brightness, contrast, saturation)
355                    which gets registered *after* this function. because of this we have
356                    to return with a value != 0 even if the function succeded.. */
357         case VIDIOC_QUERYCTRL:
358                 {
359                         struct v4l2_queryctrl *qc = arg;
360                         int i;
361
362                         for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
363                                 if (hexium_controls[i].id == qc->id) {
364                                         *qc = hexium_controls[i];
365                                         DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
366                                         return 0;
367                                 }
368                         }
369                         return -EAGAIN;
370                 }
371         case VIDIOC_G_CTRL:
372                 {
373                         struct v4l2_control *vc = arg;
374                         int i;
375
376                         for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
377                                 if (hexium_controls[i].id == vc->id) {
378                                         break;
379                                 }
380                         }
381
382                         if (i < 0) {
383                                 return -EAGAIN;
384                         }
385
386                         switch (vc->id) {
387                         case V4L2_CID_PRIVATE_BASE:{
388                                         vc->value = hexium->cur_bw;
389                                         DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
390                                         return 0;
391                                 }
392                         }
393                         return -EINVAL;
394                 }
395
396         case VIDIOC_S_CTRL:
397                 {
398                         struct v4l2_control *vc = arg;
399                         int i = 0;
400
401                         for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
402                                 if (hexium_controls[i].id == vc->id) {
403                                         break;
404                                 }
405                         }
406
407                         if (i < 0) {
408                                 return -EAGAIN;
409                         }
410
411                         switch (vc->id) {
412                         case V4L2_CID_PRIVATE_BASE:{
413                                         hexium->cur_bw = vc->value;
414                                         break;
415                                 }
416                         }
417
418                         DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
419
420                         if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
421                                 hexium_set_standard(hexium, hexium_pal);
422                                 return 0;
423                         }
424                         if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
425                                 hexium_set_standard(hexium, hexium_ntsc);
426                                 return 0;
427                         }
428                         if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
429                                 hexium_set_standard(hexium, hexium_secam);
430                                 return 0;
431                         }
432                         if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
433                                 hexium_set_standard(hexium, hexium_pal_bw);
434                                 return 0;
435                         }
436                         if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
437                                 hexium_set_standard(hexium, hexium_ntsc_bw);
438                                 return 0;
439                         }
440                         if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
441                                 /* fixme: is there no bw secam mode? */
442                                 return -EINVAL;
443                         }
444
445                         return -EINVAL;
446                 }
447         default:
448 /*
449                 DEB_D(("hexium_ioctl() does not handle this ioctl.\n"));
450 */
451                 return -ENOIOCTLCMD;
452         }
453         return 0;
454 }
455
456 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
457 {
458         struct hexium *hexium = (struct hexium *) dev->ext_priv;
459
460         if (V4L2_STD_PAL == std->id) {
461                 hexium_set_standard(hexium, hexium_pal);
462                 hexium->cur_std = V4L2_STD_PAL;
463                 return 0;
464         } else if (V4L2_STD_NTSC == std->id) {
465                 hexium_set_standard(hexium, hexium_ntsc);
466                 hexium->cur_std = V4L2_STD_NTSC;
467                 return 0;
468         } else if (V4L2_STD_SECAM == std->id) {
469                 hexium_set_standard(hexium, hexium_secam);
470                 hexium->cur_std = V4L2_STD_SECAM;
471                 return 0;
472         }
473
474         return -1;
475 }
476
477 static struct saa7146_extension hexium_extension;
478
479 static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
480         .ext_priv = "Hexium Gemini (4 BNC)",
481         .ext = &hexium_extension,
482 };
483
484 static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
485         .ext_priv = "Hexium Gemini Dual (4 BNC)",
486         .ext = &hexium_extension,
487 };
488
489 static struct pci_device_id pci_tbl[] = {
490         {
491          .vendor = PCI_VENDOR_ID_PHILIPS,
492          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
493          .subvendor = 0x17c8,
494          .subdevice = 0x2401,
495          .driver_data = (unsigned long) &hexium_gemini_4bnc,
496          },
497         {
498          .vendor = PCI_VENDOR_ID_PHILIPS,
499          .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
500          .subvendor = 0x17c8,
501          .subdevice = 0x2402,
502          .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
503          },
504         {
505          .vendor = 0,
506          }
507 };
508
509 MODULE_DEVICE_TABLE(pci, pci_tbl);
510
511 static struct saa7146_ext_vv vv_data = {
512         .inputs = HEXIUM_INPUTS,
513         .capabilities = 0,
514         .stds = &hexium_standards[0],
515         .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
516         .std_callback = &std_callback,
517         .ioctls = &ioctls[0],
518         .ioctl = hexium_ioctl,
519 };
520
521 static struct saa7146_extension hexium_extension = {
522         .name = "hexium gemini",
523         .flags = SAA7146_USE_I2C_IRQ,
524
525         .pci_tbl = &pci_tbl[0],
526         .module = THIS_MODULE,
527
528         .attach = hexium_attach,
529         .detach = hexium_detach,
530
531         .irq_mask = 0,
532         .irq_func = NULL,
533 };
534
535 static int __init hexium_init_module(void)
536 {
537         if (0 != saa7146_register_extension(&hexium_extension)) {
538                 DEB_S(("failed to register extension.\n"));
539                 return -ENODEV;
540         }
541
542         return 0;
543 }
544
545 static void __exit hexium_cleanup_module(void)
546 {
547         saa7146_unregister_extension(&hexium_extension);
548 }
549
550 module_init(hexium_init_module);
551 module_exit(hexium_cleanup_module);
552
553 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
554 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
555 MODULE_LICENSE("GPL");