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>
28 static int debug
= 255;
29 MODULE_PARM(debug
, "i");
30 MODULE_PARM_DESC(debug
, "debug verbosity");
32 /* global variables */
35 #include "hexium_gemini.h"
37 /* bring hardware to a sane state. this has to be done, just in case someone
38 wants to capture from this device before it has been properly initialized.
39 the capture engine would badly fail, because no valid signal arrives on the
40 saa7146, thus leading to timeouts and stuff. */
41 static int hexium_init_done(struct saa7146_dev
*dev
)
43 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
44 union i2c_smbus_data data
;
47 DEB_D(("hexium_init_done called.\n"));
49 /* initialize the helper ics to useful values */
50 for (i
= 0; i
< sizeof(hexium_ks0127b
); i
++) {
51 data
.byte
= hexium_ks0127b
[i
];
52 if (0 != i2c_smbus_xfer(&hexium
->i2c_adapter
, 0x6c, 0, I2C_SMBUS_WRITE
, i
, I2C_SMBUS_BYTE_DATA
, &data
)) {
53 printk("failed for address 0x%02x\n", i
);
60 static int hexium_set_input(struct hexium
*hexium
, int input
)
62 union i2c_smbus_data data
;
66 data
.byte
= hexium_input_select
[input
].byte
;
67 if (0 != i2c_smbus_xfer(&hexium
->i2c_adapter
, 0x6c, 0, I2C_SMBUS_WRITE
, hexium_input_select
[input
].adr
, I2C_SMBUS_BYTE_DATA
, &data
)) {
74 static int hexium_set_standard(struct hexium
*hexium
, struct hexium_data
*vdec
)
76 union i2c_smbus_data data
;
81 while (vdec
[i
].adr
!= -1) {
82 data
.byte
= vdec
[i
].byte
;
83 if (0 != i2c_smbus_xfer(&hexium
->i2c_adapter
, 0x6c, 0, I2C_SMBUS_WRITE
, vdec
[i
].adr
, I2C_SMBUS_BYTE_DATA
, &data
)) {
84 printk("failed for address 0x%02x\n", i
);
92 static struct saa7146_ext_vv vv_data
;
94 /* this function only gets called when the probing was successful */
95 static int hexium_attach(struct saa7146_dev
*dev
, struct saa7146_pci_extension_data
*info
)
97 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
101 hexium
= (struct hexium
*) kmalloc(sizeof(struct hexium
), GFP_KERNEL
);
102 if (NULL
== hexium
) {
103 printk("hexium_v4l2.o: hexium_probe: not enough kernel memory.\n");
106 memset(hexium
, 0x0, sizeof(struct hexium
));
107 (struct hexium
*) dev
->ext_priv
= hexium
;
109 /* FIXME: enable i2c-port pins, video-port-pins
110 video port pins should be enabled here ?! */
111 saa7146_write(dev
, MC1
, (MASK_08
| MASK_24
| MASK_10
| MASK_26
));
113 saa7146_i2c_adapter_prepare(dev
, &hexium
->i2c_adapter
, SAA7146_I2C_BUS_BIT_RATE_480
);
114 if (i2c_add_adapter(&hexium
->i2c_adapter
) < 0) {
115 DEB_S(("cannot register i2c-device. skipping.\n"));
120 /* set HWControl GPIO number 2 */
121 saa7146_setgpio(dev
, 2, SAA7146_GPIO_OUTHI
);
123 saa7146_write(dev
, DD1_INIT
, 0x07000700);
124 saa7146_write(dev
, DD1_STREAM_B
, 0x00000000);
125 saa7146_write(dev
, MC2
, (MASK_09
| MASK_25
| MASK_10
| MASK_26
));
128 hexium
->cur_input
= 0;
129 hexium_init_done(dev
);
131 hexium_set_standard(hexium
, hexium_pal
);
132 hexium
->cur_std
= V4L2_STD_PAL
;
134 hexium_set_input(hexium
, 0);
135 hexium
->cur_input
= 0;
137 saa7146_vv_init(dev
, &vv_data
);
138 if (0 != saa7146_register_device(&hexium
->video_dev
, dev
, "hexium", VFL_TYPE_GRABBER
)) {
139 ERR(("cannot register capture v4l2 device. skipping.\n"));
143 printk("hexium: found 'hexium frame grabber'-%d.\n", hexium_num
);
149 static int hexium_detach(struct saa7146_dev
*dev
)
151 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
153 DEB_EE(("dev:%p\n", dev
));
155 saa7146_unregister_device(&hexium
->video_dev
, dev
);
156 saa7146_vv_release(dev
);
160 i2c_del_adapter(&hexium
->i2c_adapter
);
165 static int hexium_ioctl(struct saa7146_fh
*fh
, unsigned int cmd
, void *arg
)
167 struct saa7146_dev
*dev
= fh
->dev
;
168 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
170 struct saa7146_vv *vv = dev->vv_data;
173 case VIDIOC_ENUMINPUT
:
175 struct v4l2_input
*i
= arg
;
176 DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i
->index
));
178 if (i
->index
< 0 || i
->index
>= HEXIUM_INPUTS
) {
182 memcpy(i
, &hexium_inputs
[i
->index
], sizeof(struct v4l2_input
));
184 DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i
->index
));
189 int *input
= (int *) arg
;
190 *input
= hexium
->cur_input
;
192 DEB_D(("VIDIOC_G_INPUT: %d\n", *input
));
197 int input
= *(int *) arg
;
199 DEB_EE(("VIDIOC_S_INPUT %d.\n", input
));
201 if (input
< 0 || input
>= HEXIUM_INPUTS
) {
205 hexium
->cur_input
= input
;
206 hexium_set_input(hexium
, input
);
210 /* the saa7146 provides some controls (brightness, contrast, saturation)
211 which gets registered *after* this function. because of this we have
212 to return with a value != 0 even if the function succeded.. */
213 case VIDIOC_QUERYCTRL
:
215 struct v4l2_queryctrl
*qc
= arg
;
218 for (i
= HEXIUM_CONTROLS
- 1; i
>= 0; i
--) {
219 if (hexium_controls
[i
].id
== qc
->id
) {
220 *qc
= hexium_controls
[i
];
221 DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc
->id
));
229 struct v4l2_control
*vc
= arg
;
232 for (i
= HEXIUM_CONTROLS
- 1; i
>= 0; i
--) {
233 if (hexium_controls
[i
].id
== vc
->id
) {
243 case V4L2_CID_PRIVATE_BASE
:{
244 vc
->value
= hexium
->cur_bw
;
245 DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc
->value
));
254 struct v4l2_control
*vc
= arg
;
257 for (i
= HEXIUM_CONTROLS
- 1; i
>= 0; i
--) {
258 if (hexium_controls
[i
].id
== vc
->id
) {
268 case V4L2_CID_PRIVATE_BASE
:{
269 hexium
->cur_bw
= vc
->value
;
274 DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium
->cur_bw
));
276 if (0 == hexium
->cur_bw
&& V4L2_STD_PAL
== hexium
->cur_std
) {
277 hexium_set_standard(hexium
, hexium_pal
);
280 if (0 == hexium
->cur_bw
&& V4L2_STD_NTSC
== hexium
->cur_std
) {
281 hexium_set_standard(hexium
, hexium_ntsc
);
284 if (0 == hexium
->cur_bw
&& V4L2_STD_SECAM
== hexium
->cur_std
) {
285 hexium_set_standard(hexium
, hexium_secam
);
288 if (1 == hexium
->cur_bw
&& V4L2_STD_PAL
== hexium
->cur_std
) {
289 hexium_set_standard(hexium
, hexium_pal_bw
);
292 if (1 == hexium
->cur_bw
&& V4L2_STD_NTSC
== hexium
->cur_std
) {
293 hexium_set_standard(hexium
, hexium_ntsc_bw
);
296 if (1 == hexium
->cur_bw
&& V4L2_STD_SECAM
== hexium
->cur_std
) {
297 /* fixme: is there no bw secam mode? */
305 DEB_D(("v4l2_ioctl does not handle this ioctl.\n"));
312 static int std_callback(struct saa7146_dev
*dev
, struct saa7146_standard
*std
)
314 struct hexium
*hexium
= (struct hexium
*) dev
->ext_priv
;
316 if (V4L2_STD_PAL
== std
->id
) {
317 hexium_set_standard(hexium
, hexium_pal
);
318 hexium
->cur_std
= V4L2_STD_PAL
;
320 } else if (V4L2_STD_NTSC
== std
->id
) {
321 hexium_set_standard(hexium
, hexium_ntsc
);
322 hexium
->cur_std
= V4L2_STD_NTSC
;
324 } else if (V4L2_STD_SECAM
== std
->id
) {
325 hexium_set_standard(hexium
, hexium_secam
);
326 hexium
->cur_std
= V4L2_STD_SECAM
;
333 static struct saa7146_extension hexium_extension
;
335 static struct saa7146_pci_extension_data hexium_gemini_4bnc
= {
336 .ext_priv
= "Hexium Gemini (4 BNC)",
337 .ext
= &hexium_extension
,
340 static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc
= {
341 .ext_priv
= "Hexium Gemini Dual (4 BNC)",
342 .ext
= &hexium_extension
,
345 static struct pci_device_id pci_tbl
[] = {
347 .vendor
= PCI_VENDOR_ID_PHILIPS
,
348 .device
= PCI_DEVICE_ID_PHILIPS_SAA7146
,
351 .driver_data
= (unsigned long) &hexium_gemini_4bnc
,
354 .vendor
= PCI_VENDOR_ID_PHILIPS
,
355 .device
= PCI_DEVICE_ID_PHILIPS_SAA7146
,
358 .driver_data
= (unsigned long) &hexium_gemini_dual_4bnc
,
365 MODULE_DEVICE_TABLE(pci
, pci_tbl
);
367 static struct saa7146_ext_vv vv_data
= {
368 .inputs
= HEXIUM_INPUTS
,
370 .stds
= &hexium_standards
[0],
371 .num_stds
= sizeof(hexium_standards
) / sizeof(struct saa7146_standard
),
372 .std_callback
= &std_callback
,
373 .ioctls
= &ioctls
[0],
374 .ioctl
= hexium_ioctl
,
377 static struct saa7146_extension hexium_extension
= {
378 .name
= "hexium gemini",
379 .flags
= SAA7146_USE_I2C_IRQ
,
381 .pci_tbl
= &pci_tbl
[0],
382 .module
= THIS_MODULE
,
384 .attach
= hexium_attach
,
385 .detach
= hexium_detach
,
391 int __init
hexium_init_module(void)
393 if (0 != saa7146_register_extension(&hexium_extension
)) {
394 DEB_S(("failed to register extension.\n"));
401 void __exit
hexium_cleanup_module(void)
403 saa7146_unregister_extension(&hexium_extension
);
406 module_init(hexium_init_module
);
407 module_exit(hexium_cleanup_module
);
409 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
410 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
411 MODULE_LICENSE("GPL");