2 hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards
4 Visit http://www.mihu.de/linux/saa7146/ and follow the link
5 to "hexium" for further details about this card.
7 Copyright (C) 2003 Michael Hunold <michael@mihu.de>
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.
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.
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.
24 #define DEBUG_VARIABLE debug
26 #include <media/saa7146_vv.h>
29 module_param(debug
, int, 0);
30 MODULE_PARM_DESC(debug
, "debug verbosity");
32 /* global variables */
33 static int hexium_num
;
35 #define HEXIUM_GEMINI 4
36 #define HEXIUM_GEMINI_DUAL 5
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 },
51 #define HEXIUM_AUDIOS 0
59 #define HEXIUM_CONTROLS 1
60 static struct v4l2_queryctrl hexium_controls
[] = {
61 { V4L2_CID_PRIVATE_BASE
, V4L2_CTRL_TYPE_BOOLEAN
, "B/W", 0, 1, 1, 0, 0 },
64 #define HEXIUM_GEMINI_V_1_0 1
65 #define HEXIUM_GEMINI_DUAL_V_1_0 2
71 struct video_device
*video_dev
;
72 struct i2c_adapter i2c_adapter
;
74 int cur_input
; /* current input */
75 v4l2_std_id cur_std
; /* current standard */
76 int cur_bw
; /* current black/white status */
79 /* Samsung KS0127B decoder default registers */
80 static u8 hexium_ks0127b
[0x100]={
81 /*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
82 /*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
83 /*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
84 /*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
85 /*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 /*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
87 /*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
88 /*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
89 /*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90 /*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
91 /*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
92 /*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
93 /*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
94 /*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
95 /*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96 /*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
97 /*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
98 /*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
99 /*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100 /*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
101 /*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102 /*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
103 /*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104 /*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
105 /*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
106 /*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
107 /*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
108 /*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
109 /*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110 /*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
111 /*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
112 /*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
115 static struct hexium_data hexium_pal
[] = {
116 { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
119 static struct hexium_data hexium_pal_bw
[] = {
120 { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
123 static struct hexium_data hexium_ntsc
[] = {
124 { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
127 static struct hexium_data hexium_ntsc_bw
[] = {
128 { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
131 static struct hexium_data hexium_secam
[] = {
132 { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
135 static struct hexium_data hexium_input_select
[] = {
147 static struct saa7146_standard hexium_standards
[] = {
149 .name
= "PAL", .id
= V4L2_STD_PAL
,
150 .v_offset
= 28, .v_field
= 288,
151 .h_offset
= 1, .h_pixels
= 680,
152 .v_max_out
= 576, .h_max_out
= 768,
154 .name
= "NTSC", .id
= V4L2_STD_NTSC
,
155 .v_offset
= 28, .v_field
= 240,
156 .h_offset
= 1, .h_pixels
= 640,
157 .v_max_out
= 480, .h_max_out
= 640,
159 .name
= "SECAM", .id
= V4L2_STD_SECAM
,
160 .v_offset
= 28, .v_field
= 288,
161 .h_offset
= 1, .h_pixels
= 720,
162 .v_max_out
= 576, .h_max_out
= 768,
166 /* bring hardware to a sane state. this has to be done, just in case someone
167 wants to capture from this device before it has been properly initialized.
168 the capture engine would badly fail, because no valid signal arrives on the
169 saa7146, thus leading to timeouts and stuff. */
170 static int hexium_init_done(struct saa7146_dev
*dev
)
172 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
173 union i2c_smbus_data data
;
176 DEB_D(("hexium_init_done called.\n"));
178 /* initialize the helper ics to useful values */
179 for (i
= 0; i
< sizeof(hexium_ks0127b
); i
++) {
180 data
.byte
= hexium_ks0127b
[i
];
181 if (0 != i2c_smbus_xfer(&hexium
->i2c_adapter
, 0x6c, 0, I2C_SMBUS_WRITE
, i
, I2C_SMBUS_BYTE_DATA
, &data
)) {
182 printk("hexium_gemini: hexium_init_done() failed for address 0x%02x\n", i
);
189 static int hexium_set_input(struct hexium
*hexium
, int input
)
191 union i2c_smbus_data data
;
195 data
.byte
= hexium_input_select
[input
].byte
;
196 if (0 != i2c_smbus_xfer(&hexium
->i2c_adapter
, 0x6c, 0, I2C_SMBUS_WRITE
, hexium_input_select
[input
].adr
, I2C_SMBUS_BYTE_DATA
, &data
)) {
203 static int hexium_set_standard(struct hexium
*hexium
, struct hexium_data
*vdec
)
205 union i2c_smbus_data data
;
210 while (vdec
[i
].adr
!= -1) {
211 data
.byte
= vdec
[i
].byte
;
212 if (0 != i2c_smbus_xfer(&hexium
->i2c_adapter
, 0x6c, 0, I2C_SMBUS_WRITE
, vdec
[i
].adr
, I2C_SMBUS_BYTE_DATA
, &data
)) {
213 printk("hexium_init_done: hexium_set_standard() failed for address 0x%02x\n", i
);
221 static int vidioc_enum_input(struct file
*file
, void *fh
, struct v4l2_input
*i
)
223 DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i
->index
));
225 if (i
->index
>= HEXIUM_INPUTS
)
228 memcpy(i
, &hexium_inputs
[i
->index
], sizeof(struct v4l2_input
));
230 DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i
->index
));
234 static int vidioc_g_input(struct file
*file
, void *fh
, unsigned int *input
)
236 struct saa7146_dev
*dev
= ((struct saa7146_fh
*)fh
)->dev
;
237 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
239 *input
= hexium
->cur_input
;
241 DEB_D(("VIDIOC_G_INPUT: %d\n", *input
));
245 static int vidioc_s_input(struct file
*file
, void *fh
, unsigned int input
)
247 struct saa7146_dev
*dev
= ((struct saa7146_fh
*)fh
)->dev
;
248 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
250 DEB_EE(("VIDIOC_S_INPUT %d.\n", input
));
252 if (input
>= HEXIUM_INPUTS
)
255 hexium
->cur_input
= input
;
256 hexium_set_input(hexium
, input
);
260 /* the saa7146 provides some controls (brightness, contrast, saturation)
261 which gets registered *after* this function. because of this we have
262 to return with a value != 0 even if the function succeded.. */
263 static int vidioc_queryctrl(struct file
*file
, void *fh
, struct v4l2_queryctrl
*qc
)
265 struct saa7146_dev
*dev
= ((struct saa7146_fh
*)fh
)->dev
;
268 for (i
= HEXIUM_CONTROLS
- 1; i
>= 0; i
--) {
269 if (hexium_controls
[i
].id
== qc
->id
) {
270 *qc
= hexium_controls
[i
];
271 DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc
->id
));
275 return dev
->ext_vv_data
->core_ops
->vidioc_queryctrl(file
, fh
, qc
);
278 static int vidioc_g_ctrl(struct file
*file
, void *fh
, struct v4l2_control
*vc
)
280 struct saa7146_dev
*dev
= ((struct saa7146_fh
*)fh
)->dev
;
281 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
284 for (i
= HEXIUM_CONTROLS
- 1; i
>= 0; i
--) {
285 if (hexium_controls
[i
].id
== vc
->id
)
290 return dev
->ext_vv_data
->core_ops
->vidioc_g_ctrl(file
, fh
, vc
);
292 if (vc
->id
== V4L2_CID_PRIVATE_BASE
) {
293 vc
->value
= hexium
->cur_bw
;
294 DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc
->value
));
300 static int vidioc_s_ctrl(struct file
*file
, void *fh
, struct v4l2_control
*vc
)
302 struct saa7146_dev
*dev
= ((struct saa7146_fh
*)fh
)->dev
;
303 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
306 for (i
= HEXIUM_CONTROLS
- 1; i
>= 0; i
--) {
307 if (hexium_controls
[i
].id
== vc
->id
)
312 return dev
->ext_vv_data
->core_ops
->vidioc_s_ctrl(file
, fh
, vc
);
314 if (vc
->id
== V4L2_CID_PRIVATE_BASE
)
315 hexium
->cur_bw
= vc
->value
;
317 DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium
->cur_bw
));
319 if (0 == hexium
->cur_bw
&& V4L2_STD_PAL
== hexium
->cur_std
) {
320 hexium_set_standard(hexium
, hexium_pal
);
323 if (0 == hexium
->cur_bw
&& V4L2_STD_NTSC
== hexium
->cur_std
) {
324 hexium_set_standard(hexium
, hexium_ntsc
);
327 if (0 == hexium
->cur_bw
&& V4L2_STD_SECAM
== hexium
->cur_std
) {
328 hexium_set_standard(hexium
, hexium_secam
);
331 if (1 == hexium
->cur_bw
&& V4L2_STD_PAL
== hexium
->cur_std
) {
332 hexium_set_standard(hexium
, hexium_pal_bw
);
335 if (1 == hexium
->cur_bw
&& V4L2_STD_NTSC
== hexium
->cur_std
) {
336 hexium_set_standard(hexium
, hexium_ntsc_bw
);
339 if (1 == hexium
->cur_bw
&& V4L2_STD_SECAM
== hexium
->cur_std
)
346 static struct saa7146_ext_vv vv_data
;
348 /* this function only gets called when the probing was successful */
349 static int hexium_attach(struct saa7146_dev
*dev
, struct saa7146_pci_extension_data
*info
)
351 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
356 hexium
= kzalloc(sizeof(struct hexium
), GFP_KERNEL
);
357 if (NULL
== hexium
) {
358 printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
361 dev
->ext_priv
= hexium
;
363 /* enable i2c-port pins */
364 saa7146_write(dev
, MC1
, (MASK_08
| MASK_24
| MASK_10
| MASK_26
));
366 hexium
->i2c_adapter
= (struct i2c_adapter
) {
367 .class = I2C_CLASS_TV_ANALOG
,
368 .name
= "hexium gemini",
370 saa7146_i2c_adapter_prepare(dev
, &hexium
->i2c_adapter
, SAA7146_I2C_BUS_BIT_RATE_480
);
371 if (i2c_add_adapter(&hexium
->i2c_adapter
) < 0) {
372 DEB_S(("cannot register i2c-device. skipping.\n"));
377 /* set HWControl GPIO number 2 */
378 saa7146_setgpio(dev
, 2, SAA7146_GPIO_OUTHI
);
380 saa7146_write(dev
, DD1_INIT
, 0x07000700);
381 saa7146_write(dev
, DD1_STREAM_B
, 0x00000000);
382 saa7146_write(dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
385 hexium
->cur_input
= 0;
386 hexium_init_done(dev
);
388 hexium_set_standard(hexium
, hexium_pal
);
389 hexium
->cur_std
= V4L2_STD_PAL
;
391 hexium_set_input(hexium
, 0);
392 hexium
->cur_input
= 0;
394 saa7146_vv_init(dev
, &vv_data
);
395 vv_data
.ops
.vidioc_queryctrl
= vidioc_queryctrl
;
396 vv_data
.ops
.vidioc_g_ctrl
= vidioc_g_ctrl
;
397 vv_data
.ops
.vidioc_s_ctrl
= vidioc_s_ctrl
;
398 vv_data
.ops
.vidioc_enum_input
= vidioc_enum_input
;
399 vv_data
.ops
.vidioc_g_input
= vidioc_g_input
;
400 vv_data
.ops
.vidioc_s_input
= vidioc_s_input
;
401 ret
= saa7146_register_device(&hexium
->video_dev
, dev
, "hexium gemini", VFL_TYPE_GRABBER
);
403 printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n");
407 printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num
);
413 static int hexium_detach(struct saa7146_dev
*dev
)
415 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
417 DEB_EE(("dev:%p\n", dev
));
419 saa7146_unregister_device(&hexium
->video_dev
, dev
);
420 saa7146_vv_release(dev
);
424 i2c_del_adapter(&hexium
->i2c_adapter
);
429 static int std_callback(struct saa7146_dev
*dev
, struct saa7146_standard
*std
)
431 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
433 if (V4L2_STD_PAL
== std
->id
) {
434 hexium_set_standard(hexium
, hexium_pal
);
435 hexium
->cur_std
= V4L2_STD_PAL
;
437 } else if (V4L2_STD_NTSC
== std
->id
) {
438 hexium_set_standard(hexium
, hexium_ntsc
);
439 hexium
->cur_std
= V4L2_STD_NTSC
;
441 } else if (V4L2_STD_SECAM
== std
->id
) {
442 hexium_set_standard(hexium
, hexium_secam
);
443 hexium
->cur_std
= V4L2_STD_SECAM
;
450 static struct saa7146_extension hexium_extension
;
452 static struct saa7146_pci_extension_data hexium_gemini_4bnc
= {
453 .ext_priv
= "Hexium Gemini (4 BNC)",
454 .ext
= &hexium_extension
,
457 static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc
= {
458 .ext_priv
= "Hexium Gemini Dual (4 BNC)",
459 .ext
= &hexium_extension
,
462 static struct pci_device_id pci_tbl
[] = {
464 .vendor
= PCI_VENDOR_ID_PHILIPS
,
465 .device
= PCI_DEVICE_ID_PHILIPS_SAA7146
,
468 .driver_data
= (unsigned long) &hexium_gemini_4bnc
,
471 .vendor
= PCI_VENDOR_ID_PHILIPS
,
472 .device
= PCI_DEVICE_ID_PHILIPS_SAA7146
,
475 .driver_data
= (unsigned long) &hexium_gemini_dual_4bnc
,
482 MODULE_DEVICE_TABLE(pci
, pci_tbl
);
484 static struct saa7146_ext_vv vv_data
= {
485 .inputs
= HEXIUM_INPUTS
,
487 .stds
= &hexium_standards
[0],
488 .num_stds
= sizeof(hexium_standards
) / sizeof(struct saa7146_standard
),
489 .std_callback
= &std_callback
,
492 static struct saa7146_extension hexium_extension
= {
493 .name
= "hexium gemini",
494 .flags
= SAA7146_USE_I2C_IRQ
,
496 .pci_tbl
= &pci_tbl
[0],
497 .module
= THIS_MODULE
,
499 .attach
= hexium_attach
,
500 .detach
= hexium_detach
,
506 static int __init
hexium_init_module(void)
508 if (0 != saa7146_register_extension(&hexium_extension
)) {
509 DEB_S(("failed to register extension.\n"));
516 static void __exit
hexium_cleanup_module(void)
518 saa7146_unregister_extension(&hexium_extension
);
521 module_init(hexium_init_module
);
522 module_exit(hexium_cleanup_module
);
524 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
525 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
526 MODULE_LICENSE("GPL");