commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / drivers / media / video / hexium_orion.c
1 /*
2     hexium_orion.c - v4l2 driver for the Hexium Orion 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 = 0;
29 MODULE_PARM(debug, "i");
30 MODULE_PARM_DESC(debug, "debug verbosity");
31
32 /* global variables */
33 int hexium_num = 0;
34
35 #include "hexium_orion.h"
36
37 /* this is only called for old HV-PCI6/Orion cards
38    without eeprom */
39 static int hexium_probe(struct saa7146_dev *dev)
40 {
41         struct hexium *hexium = 0;
42         union i2c_smbus_data data;
43         int err = 0;
44
45         DEB_EE((".\n"));
46
47         /* there are no hexium orion cards with revision 0 saa7146s */
48         if (0 == dev->revision) {
49                 return -EFAULT;
50         }
51
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;
56         }
57         memset(hexium, 0x0, sizeof(struct hexium));
58
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));
62
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));
66
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;
72         }
73
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);
78
79         mdelay(10);
80
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;
88         }
89
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;
96         }
97
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;
106         }
107
108         i2c_del_adapter(&hexium->i2c_adapter);
109         kfree(hexium);
110         return -EFAULT;
111 }
112
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)
118 {
119         struct hexium *hexium = (struct hexium *) dev->ext_priv;
120         union i2c_smbus_data data;
121         int i = 0;
122
123         DEB_D(("hexium_init_done called.\n"));
124
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);
130                 }
131         }
132
133         return 0;
134 }
135
136 static struct saa7146_ext_vv vv_data;
137
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)
140 {
141         struct hexium *hexium = (struct hexium *) dev->ext_priv;
142
143         DEB_EE((".\n"));
144
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;
149         }
150
151         printk("hexium_orion.o: found 'hexium orion' frame grabber-%d.\n", hexium_num);
152         hexium_num++;
153
154         /* the rest */
155         hexium->cur_input = 0;
156         hexium_init_done(dev);
157
158         return 0;
159 }
160
161 static int hexium_detach(struct saa7146_dev *dev)
162 {
163         struct hexium *hexium = (struct hexium *) dev->ext_priv;
164
165         DEB_EE(("dev:%p\n", dev));
166
167         saa7146_unregister_device(&hexium->video_dev, dev);
168         saa7146_vv_release(dev);
169
170         hexium_num--;
171
172         i2c_del_adapter(&hexium->i2c_adapter);
173         kfree(hexium);
174         return 0;
175 }
176
177 static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
178 {
179         struct saa7146_dev *dev = fh->dev;
180         struct hexium *hexium = (struct hexium *) dev->ext_priv;
181 /*
182         struct saa7146_vv *vv = dev->vv_data; 
183 */
184         switch (cmd) {
185         case VIDIOC_ENUMINPUT:
186                 {
187                         struct v4l2_input *i = arg;
188                         DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
189
190                         if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
191                                 return -EINVAL;
192                         }
193
194                         memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
195
196                         DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
197                         return 0;
198                 }
199         case VIDIOC_G_INPUT:
200                 {
201                         int *input = (int *) arg;
202                         *input = hexium->cur_input;
203
204                         DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
205                         return 0;
206                 }
207         case VIDIOC_S_INPUT:
208                 {
209                         int input = *(int *) arg;
210
211                         if (input < 0 || input >= HEXIUM_INPUTS) {
212                                 return -EINVAL;
213                         }
214
215                         hexium->cur_input = input;
216
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");
220
221                         return 0;
222                 }
223         default:
224 /*
225                 DEB_D(("v4l2_ioctl does not handle this ioctl.\n"));
226 */
227                 return -ENOIOCTLCMD;
228         }
229         return 0;
230 }
231
232 static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
233 {
234         return 0;
235 }
236
237 static struct saa7146_extension extension;
238
239 static struct saa7146_pci_extension_data hexium_hv_pci6 = {
240         .ext_priv = "Hexium HV-PCI6 / Orion",
241         .ext = &extension,
242 };
243
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,
247 };
248
249 static struct saa7146_pci_extension_data hexium_orion_4bnc = {
250         .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
251         .ext = &extension,
252 };
253
254 static struct pci_device_id pci_tbl[] = {
255         {
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,
261          },
262         {
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,
268          },
269         {
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,
275          },
276         {
277          .vendor = 0,
278          }
279 };
280
281 MODULE_DEVICE_TABLE(pci, pci_tbl);
282
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,
291 };
292
293 static struct saa7146_extension extension = {
294         .name = "hexium HV-PCI6/Orion",
295         .flags = 0,             // SAA7146_USE_I2C_IRQ,
296
297         .pci_tbl = &pci_tbl[0],
298         .module = THIS_MODULE,
299
300         .probe = hexium_probe,
301         .attach = hexium_attach,
302         .detach = hexium_detach,
303
304         .irq_mask = 0,
305         .irq_func = NULL,
306 };
307
308 int __init hexium_init_module(void)
309 {
310         if (0 != saa7146_register_extension(&extension)) {
311                 DEB_S(("failed to register extension.\n"));
312                 return -ENODEV;
313         }
314
315         return 0;
316 }
317
318 void __exit hexium_cleanup_module(void)
319 {
320         saa7146_unregister_extension(&extension);
321 }
322
323 module_init(hexium_init_module);
324 module_exit(hexium_cleanup_module);
325
326 MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
327 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
328 MODULE_LICENSE("GPL");