[PATCH] Add two drivers for Hexium frame grabber cards
[linux-2.6/history.git] / drivers / media / video / hexium_orion.c
blob013460263749b3b4ac95db41438fbc00df5fc00e
1 /*
2 hexium_orion.c - v4l2 driver for the Hexium Orion 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 */
33 int hexium_num = 0;
35 #include "hexium_orion.h"
37 /* this is only called for old HV-PCI6/Orion cards
38 without eeprom */
39 static int hexium_probe(struct saa7146_dev *dev)
41 struct hexium *hexium = 0;
42 union i2c_smbus_data data;
43 int err = 0;
45 DEB_EE((".\n"));
47 /* there are no hexium orion cards with revision 0 saa7146s */
48 if (0 == dev->revision) {
49 return -EFAULT;
52 hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
53 if (NULL == hexium) {
54 printk("hexium_orion.o: hexium_probe: not enough kernel memory.\n");
55 return -ENOMEM;
57 memset(hexium, 0x0, sizeof(struct hexium));
59 /* FIXME: enable i2c-port pins, video-port-pins
60 video port pins should be enabled here ?! */
61 saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
63 saa7146_write(dev, DD1_INIT, 0x02000200);
64 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
65 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
67 saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
68 if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
69 DEB_S(("cannot register i2c-device. skipping.\n"));
70 kfree(hexium);
71 return -EFAULT;
74 /* set SAA7110 control GPIO 0 */
75 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
76 /* set HWControl GPIO number 2 */
77 saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
79 mdelay(10);
81 /* detect newer Hexium Orion cards by subsystem ids */
82 if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
83 printk("hexium_orion.o: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
84 /* we store the pointer in our private data field */
85 (struct hexium *) dev->ext_priv = hexium;
86 hexium->type = HEXIUM_ORION_1SVHS_3BNC;
87 return 0;
90 if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
91 printk("hexium_orion.o: device is a Hexium Orion w/ 4 BNC inputs.\n");
92 /* we store the pointer in our private data field */
93 (struct hexium *) dev->ext_priv = hexium;
94 hexium->type = HEXIUM_ORION_4BNC;
95 return 0;
98 /* check if this is an old hexium Orion card by looking at
99 a saa7110 at address 0x4e */
100 if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
101 printk("hexium_orion.o: device is a Hexium HV-PCI6/Orion (old).\n");
102 /* we store the pointer in our private data field */
103 (struct hexium *) dev->ext_priv = hexium;
104 hexium->type = HEXIUM_HV_PCI6_ORION;
105 return 0;
108 i2c_del_adapter(&hexium->i2c_adapter);
109 kfree(hexium);
110 return -EFAULT;
113 /* bring hardware to a sane state. this has to be done, just in case someone
114 wants to capture from this device before it has been properly initialized.
115 the capture engine would badly fail, because no valid signal arrives on the
116 saa7146, thus leading to timeouts and stuff. */
117 static int hexium_init_done(struct saa7146_dev *dev)
119 struct hexium *hexium = (struct hexium *) dev->ext_priv;
120 union i2c_smbus_data data;
121 int i = 0;
123 DEB_D(("hexium_init_done called.\n"));
125 /* initialize the helper ics to useful values */
126 for (i = 0; i < sizeof(hexium_saa7110); i++) {
127 data.byte = hexium_saa7110[i];
128 if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
129 printk("hexium_orion: failed for address 0x%02x\n", i);
133 return 0;
136 static struct saa7146_ext_vv vv_data;
138 /* this function only gets called when the probing was successful */
139 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
141 struct hexium *hexium = (struct hexium *) dev->ext_priv;
143 DEB_EE((".\n"));
145 saa7146_vv_init(dev, &vv_data);
146 if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) {
147 ERR(("cannot register capture v4l2 device. skipping.\n"));
148 return -1;
151 printk("hexium_orion.o: found 'hexium orion' frame grabber-%d.\n", hexium_num);
152 hexium_num++;
154 /* the rest */
155 hexium->cur_input = 0;
156 hexium_init_done(dev);
158 return 0;
161 static int hexium_detach(struct saa7146_dev *dev)
163 struct hexium *hexium = (struct hexium *) dev->ext_priv;
165 DEB_EE(("dev:%p\n", dev));
167 saa7146_unregister_device(&hexium->video_dev, dev);
168 saa7146_vv_release(dev);
170 hexium_num--;
172 i2c_del_adapter(&hexium->i2c_adapter);
173 kfree(hexium);
174 return 0;
177 static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
179 struct saa7146_dev *dev = fh->dev;
180 struct hexium *hexium = (struct hexium *) dev->ext_priv;
182 struct saa7146_vv *vv = dev->vv_data;
184 switch (cmd) {
185 case VIDIOC_ENUMINPUT:
187 struct v4l2_input *i = arg;
188 DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
190 if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
191 return -EINVAL;
194 memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
196 DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
197 return 0;
199 case VIDIOC_G_INPUT:
201 int *input = (int *) arg;
202 *input = hexium->cur_input;
204 DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
205 return 0;
207 case VIDIOC_S_INPUT:
209 int input = *(int *) arg;
211 if (input < 0 || input >= HEXIUM_INPUTS) {
212 return -EINVAL;
215 hexium->cur_input = input;
217 /* fixme: switch input here, switch audio, too! */
218 // saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
219 printk("hexium_orion.o: VIDIOC_S_INPUT: fixme switch input.\n");
221 return 0;
223 default:
225 DEB_D(("v4l2_ioctl does not handle this ioctl.\n"));
227 return -ENOIOCTLCMD;
229 return 0;
232 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
234 return 0;
237 static struct saa7146_extension extension;
239 static struct saa7146_pci_extension_data hexium_hv_pci6 = {
240 .ext_priv = "Hexium HV-PCI6 / Orion",
241 .ext = &extension,
244 static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
245 .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
246 .ext = &extension,
249 static struct saa7146_pci_extension_data hexium_orion_4bnc = {
250 .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
251 .ext = &extension,
254 static struct pci_device_id pci_tbl[] = {
256 .vendor = PCI_VENDOR_ID_PHILIPS,
257 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
258 .subvendor = 0x0000,
259 .subdevice = 0x0000,
260 .driver_data = (unsigned long) &hexium_hv_pci6,
263 .vendor = PCI_VENDOR_ID_PHILIPS,
264 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
265 .subvendor = 0x17c8,
266 .subdevice = 0x0101,
267 .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
270 .vendor = PCI_VENDOR_ID_PHILIPS,
271 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
272 .subvendor = 0x17c8,
273 .subdevice = 0x2101,
274 .driver_data = (unsigned long) &hexium_orion_4bnc,
277 .vendor = 0,
281 MODULE_DEVICE_TABLE(pci, pci_tbl);
283 static struct saa7146_ext_vv vv_data = {
284 .inputs = HEXIUM_INPUTS,
285 .capabilities = 0,
286 .stds = &hexium_standards[0],
287 .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
288 .std_callback = &std_callback,
289 .ioctls = &ioctls[0],
290 .ioctl = hexium_ioctl,
293 static struct saa7146_extension extension = {
294 .name = "hexium HV-PCI6/Orion",
295 .flags = 0, // SAA7146_USE_I2C_IRQ,
297 .pci_tbl = &pci_tbl[0],
298 .module = THIS_MODULE,
300 .probe = hexium_probe,
301 .attach = hexium_attach,
302 .detach = hexium_detach,
304 .irq_mask = 0,
305 .irq_func = NULL,
308 int __init hexium_init_module(void)
310 if (0 != saa7146_register_extension(&extension)) {
311 DEB_S(("failed to register extension.\n"));
312 return -ENODEV;
315 return 0;
318 void __exit hexium_cleanup_module(void)
320 saa7146_unregister_extension(&extension);
323 module_init(hexium_init_module);
324 module_exit(hexium_cleanup_module);
326 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
327 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
328 MODULE_LICENSE("GPL");