ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / dvb / ttpci / budget-av.c
1 /*
2  * budget-av.c: driver for the SAA7146 based Budget DVB cards
3  *              with analog video in 
4  *
5  * Compiled from various sources by Michael Hunold <michael@mihu.de> 
6  *
7  * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
8  *
9  * Copyright (C) 1999-2002 Ralph  Metzler 
10  *                       & Marcus Metzler for convergence integrated media GmbH
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
28  * 
29  *
30  * the project's page is at http://www.linuxtv.org/dvb/
31  */
32
33 #include <media/saa7146_vv.h>
34
35 #include "budget.h"
36 #include "dvb_functions.h"
37
38 struct budget_av {
39         struct budget budget;
40         struct video_device vd;
41         int cur_input;
42         int has_saa7113;
43 };
44
45 /****************************************************************************
46  * INITIALIZATION
47  ****************************************************************************/
48
49
50 static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg)
51 {
52         u8 mm1[] = {0x00};
53         u8 mm2[] = {0x00};
54         struct i2c_msg msgs[2];
55
56         msgs[0].flags = 0;
57         msgs[1].flags = I2C_M_RD;
58         msgs[0].addr = msgs[1].addr=id/2;
59         mm1[0] = reg;
60         msgs[0].len = 1; msgs[1].len = 1;
61         msgs[0].buf = mm1; msgs[1].buf = mm2;
62
63         i2c->xfer(i2c, msgs, 2);
64
65         return mm2[0];
66 }
67
68 static int i2c_readregs(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 *buf, u8 len)
69 {
70         u8 mm1[] = { reg };
71         struct i2c_msg msgs[2] = {
72                 { .addr = id/2, .flags = 0, .buf = mm1, .len = 1 },
73                 { .addr = id/2, .flags = I2C_M_RD, .buf = buf, .len = len }
74         };
75
76         if (i2c->xfer(i2c, msgs, 2) != 2)
77                 return -EIO;
78         return 0;
79 }
80
81
82 static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val)
83 {
84         u8 msg[2]={ reg, val }; 
85         struct i2c_msg msgs;
86
87         msgs.flags=0;
88         msgs.addr=id/2;
89         msgs.len=2;
90         msgs.buf=msg;
91         return i2c->xfer (i2c, &msgs, 1);
92 }
93
94
95 static const u8 saa7113_tab[] = {
96         0x01, 0x08,
97         0x02, 0xc0,
98         0x03, 0x33,
99         0x04, 0x00,
100         0x05, 0x00,
101         0x06, 0xeb,
102         0x07, 0xe0,
103         0x08, 0x28,
104         0x09, 0x00,
105         0x0a, 0x80,
106         0x0b, 0x47,
107         0x0c, 0x40,
108         0x0d, 0x00,
109         0x0e, 0x01,
110         0x0f, 0x44,
111
112         0x10, 0x08,
113         0x11, 0x0c,
114         0x12, 0x7b,
115         0x13, 0x00,
116         0x15, 0x00,  0x16, 0x00,  0x17, 0x00,
117
118         0x57, 0xff, 
119         0x40, 0x82,  0x58, 0x00,  0x59, 0x54,  0x5a, 0x07,
120         0x5b, 0x83,  0x5e, 0x00,
121         0xff
122 };
123
124
125 static int saa7113_init (struct budget_av *budget_av)
126 {
127         struct budget *budget = &budget_av->budget;
128         const u8 *data = saa7113_tab;
129
130         if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) {
131                 DEB_D(("saa7113: not found on KNC card\n"));
132                 return -ENODEV;
133         }
134
135         INFO(("saa7113: detected and initializing\n"));
136
137         while (*data != 0xff) {
138                 i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1));
139                 data += 2;
140         }
141
142         DEB_D(("saa7113: status=%02x\n",
143               i2c_readreg(budget->i2c_bus, 0x4a, 0x1f)));
144
145         return 0;
146 }
147
148
149 static int saa7113_setinput (struct budget_av *budget_av, int input)
150 {
151         struct budget *budget = &budget_av->budget;
152
153         if ( 1 != budget_av->has_saa7113 )
154                 return -ENODEV;
155
156         if (input == 1) {
157                 i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7);
158                 i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80);
159         } else if (input == 0) {
160                 i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0);
161                 i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00);
162         } else
163                 return -EINVAL;
164
165         budget_av->cur_input = input;
166         return 0;
167 }
168
169
170 static int budget_av_detach (struct saa7146_dev *dev)
171 {
172         struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
173         int err;
174
175         DEB_EE(("dev: %p\n",dev));
176
177         if ( 1 == budget_av->has_saa7113 ) {
178         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
179
180         dvb_delay(200);
181
182         saa7146_unregister_device (&budget_av->vd, dev);
183         }
184
185         err = ttpci_budget_deinit (&budget_av->budget);
186
187         kfree (budget_av);
188
189         return err;
190 }
191
192 static struct saa7146_ext_vv vv_data;
193
194 static int budget_av_attach (struct saa7146_dev* dev,
195                       struct saa7146_pci_extension_data *info)
196 {
197         struct budget_av *budget_av;
198         struct budget_info *bi = info->ext_priv;
199         u8 *mac;
200         int err;
201
202         DEB_EE(("dev: %p\n",dev));
203
204         if (bi->type != BUDGET_KNC1) {
205                 return -ENODEV;
206         }
207
208         if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
209                 return -ENOMEM;
210
211         memset(budget_av, 0, sizeof(struct budget_av));
212
213         if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) {
214                 kfree(budget_av);
215                 return err;
216         }
217
218         dev->ext_priv = budget_av;
219
220         /* knc1 initialization */
221         saa7146_write(dev, DD1_STREAM_B, 0x04000000);
222         saa7146_write(dev, DD1_INIT, 0x07000600);
223         saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
224
225         //test_knc_ci(av7110);
226
227         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
228         dvb_delay(500);
229
230         if ( 0 == saa7113_init(budget_av) ) {
231                 budget_av->has_saa7113 = 1;
232
233         if ( 0 != saa7146_vv_init(dev,&vv_data)) {
234                 /* fixme: proper cleanup here */
235                 ERR(("cannot init vv subsystem.\n"));
236                 return err;
237         }
238
239         if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1",
240                                            VFL_TYPE_GRABBER)))
241         {
242                 /* fixme: proper cleanup here */
243                 ERR(("cannot register capture v4l2 device.\n"));
244                 return err;
245         }
246
247         /* beware: this modifies dev->vv ... */
248         saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
249                                         SAA7146_HPS_SYNC_PORT_A);
250
251         saa7113_setinput (budget_av, 0);
252         } else {
253                 budget_av->has_saa7113 = 0;
254
255         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
256         }
257
258         /* fixme: find some sane values here... */
259         saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
260
261         mac = budget_av->budget.dvb_adapter->proposed_mac;
262         if (i2c_readregs(budget_av->budget.i2c_bus, 0xa0, 0x30, mac, 6)) {
263                 printk("KNC1-%d: Could not read MAC from KNC1 card\n",
264                                 budget_av->budget.dvb_adapter->num);
265                 memset(mac, 0, 6);
266         }
267         else
268                 printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
269                                 budget_av->budget.dvb_adapter->num,
270                                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
271         return 0;
272 }
273
274
275
276 #define KNC1_INPUTS 2
277 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
278         { 0,    "Composite", V4L2_INPUT_TYPE_TUNER,  1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 
279         { 1,    "S-Video",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
280 };
281
282
283 static struct saa7146_extension_ioctls ioctls[] = {
284         { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
285         { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
286         { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
287         { 0,                    0 }
288 };
289
290
291 static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
292 {
293         struct saa7146_dev *dev = fh->dev;
294         struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
295 /*
296         struct saa7146_vv *vv = dev->vv_data; 
297 */      
298         switch(cmd) {
299         case VIDIOC_ENUMINPUT:
300         {
301                 struct v4l2_input *i = arg;
302                 
303                 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
304                 if( i->index < 0 || i->index >= KNC1_INPUTS) {
305                         return -EINVAL;
306                 }
307                 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
308                 return 0;
309         }
310         case VIDIOC_G_INPUT:
311         {
312                 int *input = (int *)arg;
313
314                 *input = budget_av->cur_input;
315
316                 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
317                 return 0;               
318         }       
319         case VIDIOC_S_INPUT:
320         {
321                 int input = *(int *)arg;
322                 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
323                 return saa7113_setinput (budget_av, input);
324         }
325         default:
326 /*
327                 DEB2(printk("does not handle this ioctl.\n"));
328 */
329                 return -ENOIOCTLCMD;
330         }
331         return 0;
332 }
333
334 static struct saa7146_standard standard[] = {
335         {
336                 .name   = "PAL",        .id     = V4L2_STD_PAL,
337                 .v_offset       = 0x17, .v_field        = 288,
338                 .h_offset       = 0x14, .h_pixels       = 680,                
339                 .v_max_out      = 576,  .h_max_out      = 768
340         }, {
341                 .name   = "NTSC",       .id     = V4L2_STD_NTSC,
342                 .v_offset       = 0x16, .v_field        = 240,
343                 .h_offset       = 0x06, .h_pixels       = 708,
344                 .v_max_out      = 480,  .h_max_out      = 640,
345         }
346 };
347
348 static struct saa7146_ext_vv vv_data = {
349         .inputs         = 2,
350         .capabilities   = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
351         .flags          = 0,
352         .stds           = &standard[0],
353         .num_stds       = sizeof(standard)/sizeof(struct saa7146_standard),
354         .ioctls         = &ioctls[0],
355         .ioctl          = av_ioctl,
356 };
357
358
359
360 static struct saa7146_extension budget_extension;
361
362
363 MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1);
364
365 static struct pci_device_id pci_tbl [] = {
366         MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56),
367         {
368                 .vendor    = 0,
369         }
370 };
371
372 MODULE_DEVICE_TABLE(pci, pci_tbl);
373
374 static struct saa7146_extension budget_extension = {
375         .name           = "budget dvb /w video in\0",
376         .pci_tbl        = pci_tbl,
377
378         .module         = THIS_MODULE,
379         .attach         = budget_av_attach,
380         .detach         = budget_av_detach,
381
382         .irq_mask       = MASK_10,
383         .irq_func       = ttpci_budget_irq10_handler,
384 };      
385
386
387 static int __init budget_av_init(void) 
388 {
389         DEB_EE((".\n"));
390
391         if (saa7146_register_extension(&budget_extension))
392                 return -ENODEV;
393         
394         return 0;
395 }
396
397
398 static void __exit budget_av_exit(void)
399 {
400         DEB_EE((".\n"));
401         saa7146_unregister_extension(&budget_extension); 
402 }
403
404 module_init(budget_av_init);
405 module_exit(budget_av_exit);
406
407 MODULE_LICENSE("GPL");
408 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
409 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
410                    "budget PCI DVB w/ analog input (e.g. the KNC cards)");
411