ef08a658ca821ff2fa49b307bc3a3464140ee419
[linux-flexiantxendom0-3.2.10.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 };
43
44 /****************************************************************************
45  * INITIALIZATION
46  ****************************************************************************/
47
48
49 static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg)
50 {
51         u8 mm1[] = {0x00};
52         u8 mm2[] = {0x00};
53         struct i2c_msg msgs[2];
54
55         msgs[0].flags = 0;
56         msgs[1].flags = I2C_M_RD;
57         msgs[0].addr = msgs[1].addr=id/2;
58         mm1[0] = reg;
59         msgs[0].len = 1; msgs[1].len = 1;
60         msgs[0].buf = mm1; msgs[1].buf = mm2;
61
62         i2c->xfer(i2c, msgs, 2);
63
64         return mm2[0];
65 }
66
67
68 static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val)
69 {
70         u8 msg[2]={ reg, val }; 
71         struct i2c_msg msgs;
72
73         msgs.flags=0;
74         msgs.addr=id/2;
75         msgs.len=2;
76         msgs.buf=msg;
77         return i2c->xfer (i2c, &msgs, 1);
78 }
79
80
81 static const u8 saa7113_tab[] = {
82         0x01, 0x08,
83         0x02, 0xc0,
84         0x03, 0x33,
85         0x04, 0x00,
86         0x05, 0x00,
87         0x06, 0xeb,
88         0x07, 0xe0,
89         0x08, 0x28,
90         0x09, 0x00,
91         0x0a, 0x80,
92         0x0b, 0x47,
93         0x0c, 0x40,
94         0x0d, 0x00,
95         0x0e, 0x01,
96         0x0f, 0x44,
97
98         0x10, 0x08,
99         0x11, 0x0c,
100         0x12, 0x7b,
101         0x13, 0x00,
102         0x15, 0x00,  0x16, 0x00,  0x17, 0x00,
103
104         0x57, 0xff, 
105         0x40, 0x82,  0x58, 0x00,  0x59, 0x54,  0x5a, 0x07,
106         0x5b, 0x83,  0x5e, 0x00,
107         0xff
108 };
109
110
111 static int saa7113_init (struct budget_av *budget_av)
112 {
113         struct budget *budget = &budget_av->budget;
114         const u8 *data = saa7113_tab;
115
116         if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) {
117                 DEB_D(("saa7113: not found on KNC card\n"));
118                 return -ENODEV;
119         }
120
121         INFO(("saa7113: detected and initializing\n"));
122
123         while (*data != 0xff) {
124                 i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1));
125                 data += 2;
126         }
127
128         DEB_D(("saa7113: status=%02x\n",
129               i2c_readreg(budget->i2c_bus, 0x4a, 0x1f)));
130
131         return 0;
132 }
133
134
135 static int saa7113_setinput (struct budget_av *budget_av, int input)
136 {
137         struct budget *budget = &budget_av->budget;
138
139         if (input == 1) {
140                 i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc7);
141                 i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x80);
142         } else if (input == 0) {
143                 i2c_writereg(budget->i2c_bus, 0x4a, 0x02, 0xc0);
144                 i2c_writereg(budget->i2c_bus, 0x4a, 0x09, 0x00);
145         } else
146                 return -EINVAL;
147
148         budget_av->cur_input = input;
149         return 0;
150 }
151
152
153 static int budget_av_detach (struct saa7146_dev *dev)
154 {
155         struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
156         int err;
157
158         DEB_EE(("dev: %p\n",dev));
159
160         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
161
162         dvb_delay(200);
163
164         saa7146_unregister_device (&budget_av->vd, dev);
165
166         err = ttpci_budget_deinit (&budget_av->budget);
167
168         kfree (budget_av);
169
170         return err;
171 }
172
173 static struct saa7146_ext_vv vv_data;
174
175 static int budget_av_attach (struct saa7146_dev* dev,
176                       struct saa7146_pci_extension_data *info)
177 {
178         struct budget_av *budget_av;
179         struct budget_info *bi = info->ext_priv;
180         int err;
181
182         DEB_EE(("dev: %p\n",dev));
183
184         if (bi->type != BUDGET_KNC1) {
185                 return -ENODEV;
186         }
187
188         if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
189                 return -ENOMEM;
190
191         memset(budget_av, 0, sizeof(struct budget_av));
192
193         if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) {
194                 kfree(budget_av);
195                 return err;
196         }
197
198         dev->ext_priv = budget_av;
199
200         /* knc1 initialization */
201         saa7146_write(dev, DD1_STREAM_B, 0x04000000);
202         saa7146_write(dev, DD1_INIT, 0x07000600);
203         saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
204
205         //test_knc_ci(av7110);
206
207         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
208         dvb_delay(500);
209
210         if ((err = saa7113_init (budget_av))) {
211                 /* fixme: proper cleanup here */
212                 ERR(("cannot init saa7113.\n"));
213                 return err;
214         }
215
216         if ( 0 != saa7146_vv_init(dev,&vv_data)) {
217                 /* fixme: proper cleanup here */
218                 ERR(("cannot init vv subsystem.\n"));
219                 return err;
220         }
221
222         if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1",
223                                            VFL_TYPE_GRABBER)))
224         {
225                 /* fixme: proper cleanup here */
226                 ERR(("cannot register capture v4l2 device.\n"));
227                 return err;
228         }
229
230         /* beware: this modifies dev->vv ... */
231         saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
232                                         SAA7146_HPS_SYNC_PORT_A);
233
234         saa7113_setinput (budget_av, 0);
235
236         /* what is this? since we don't support open()/close()
237            notifications, we simply put this into the release handler... */
238 /*
239         saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
240         set_current_state(TASK_INTERRUPTIBLE);
241         schedule_timeout (20);
242 */
243         /* fixme: find some sane values here... */
244         saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
245
246         return 0;
247 }
248
249
250
251 #define KNC1_INPUTS 2
252 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
253         { 0,    "Composite", V4L2_INPUT_TYPE_TUNER,  1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 
254         { 1,    "S-Video",   V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
255 };
256
257
258 static struct saa7146_extension_ioctls ioctls[] = {
259         { VIDIOC_ENUMINPUT,     SAA7146_EXCLUSIVE },
260         { VIDIOC_G_INPUT,       SAA7146_EXCLUSIVE },
261         { VIDIOC_S_INPUT,       SAA7146_EXCLUSIVE },
262         { 0,                    0 }
263 };
264
265
266 static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
267 {
268         struct saa7146_dev *dev = fh->dev;
269         struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
270 /*
271         struct saa7146_vv *vv = dev->vv_data; 
272 */      
273         switch(cmd) {
274         case VIDIOC_ENUMINPUT:
275         {
276                 struct v4l2_input *i = arg;
277                 
278                 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
279                 if( i->index < 0 || i->index >= KNC1_INPUTS) {
280                         return -EINVAL;
281                 }
282                 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
283                 return 0;
284         }
285         case VIDIOC_G_INPUT:
286         {
287                 int *input = (int *)arg;
288
289                 *input = budget_av->cur_input;
290
291                 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
292                 return 0;               
293         }       
294         case VIDIOC_S_INPUT:
295         {
296                 int input = *(int *)arg;
297                 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
298                 return saa7113_setinput (budget_av, input);
299         }
300         default:
301 /*
302                 DEB2(printk("does not handle this ioctl.\n"));
303 */
304                 return -ENOIOCTLCMD;
305         }
306         return 0;
307 }
308
309 static struct saa7146_standard standard[] = {
310         {
311                 .name   = "PAL",        .id     = V4L2_STD_PAL,
312                 .v_offset       = 0x17, .v_field        = 288,  .v_calc         = 576,
313                 .h_offset       = 0x14, .h_pixels       = 680,  .h_calc         = 680+1,
314                 .v_max_out      = 576,  .h_max_out      = 768,
315         }, {
316                 .name   = "NTSC",       .id     = V4L2_STD_NTSC,
317                 .v_offset       = 0x16, .v_field        = 240,  .v_calc         = 480,
318                 .h_offset       = 0x06, .h_pixels       = 708,  .h_calc         = 708+1,
319                 .v_max_out      = 480,  .h_max_out      = 640,
320         }
321 };
322
323 static struct saa7146_ext_vv vv_data = {
324         .inputs         = 2,
325         .capabilities   = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
326         .flags          = 0,
327         .stds           = &standard[0],
328         .num_stds       = sizeof(standard)/sizeof(struct saa7146_standard),
329         .ioctls         = &ioctls[0],
330         .ioctl          = av_ioctl,
331 };
332
333
334
335 static struct saa7146_extension budget_extension;
336
337
338 MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1);
339
340 static struct pci_device_id pci_tbl [] = {
341         MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56),
342         {
343                 .vendor    = 0,
344         }
345 };
346
347 MODULE_DEVICE_TABLE(pci, pci_tbl);
348
349 static struct saa7146_extension budget_extension = {
350         .name           = "budget dvb /w video in\0",
351         .pci_tbl        = pci_tbl,
352
353         .module         = THIS_MODULE,
354         .attach         = budget_av_attach,
355         .detach         = budget_av_detach,
356
357         .irq_mask       = MASK_10,
358         .irq_func       = ttpci_budget_irq10_handler,
359 };      
360
361
362 static int __init budget_av_init(void) 
363 {
364         DEB_EE((".\n"));
365
366         if (saa7146_register_extension(&budget_extension))
367                 return -ENODEV;
368         
369         return 0;
370 }
371
372
373 static void __exit budget_av_exit(void)
374 {
375         DEB_EE((".\n"));
376         saa7146_unregister_extension(&budget_extension); 
377 }
378
379 module_init(budget_av_init);
380 module_exit(budget_av_exit);
381
382 MODULE_LICENSE("GPL");
383 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
384 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
385                    "budget PCI DVB w/ analog input (e.g. the KNC cards)");
386