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