Merge with Linux 2.5.74.
[linux-2.6/linux-mips.git] / drivers / media / dvb / ttpci / budget-av.c
blobb120262a7aeed1e442257001b02be5ea8c6426ae
1 /*
2 * budget-av.c: driver for the SAA7146 based Budget DVB cards
3 * with analog video in
5 * Compiled from various sources by Michael Hunold <michael@mihu.de>
7 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
9 * Copyright (C) 1999-2002 Ralph Metzler
10 * & Marcus Metzler for convergence integrated media GmbH
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.
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.
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
30 * the project's page is at http://www.linuxtv.org/dvb/
33 #include <media/saa7146_vv.h>
35 #include "budget.h"
36 #include "dvb_functions.h"
38 struct budget_av {
39 struct budget budget;
40 struct video_device vd;
41 int cur_input;
44 /****************************************************************************
45 * INITIALIZATION
46 ****************************************************************************/
49 static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg)
51 u8 mm1[] = {0x00};
52 u8 mm2[] = {0x00};
53 struct i2c_msg msgs[2];
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;
62 i2c->xfer(i2c, msgs, 2);
64 return mm2[0];
68 static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val)
70 u8 msg[2]={ reg, val };
71 struct i2c_msg msgs;
73 msgs.flags=0;
74 msgs.addr=id/2;
75 msgs.len=2;
76 msgs.buf=msg;
77 return i2c->xfer (i2c, &msgs, 1);
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,
98 0x10, 0x08,
99 0x11, 0x0c,
100 0x12, 0x7b,
101 0x13, 0x00,
102 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
104 0x57, 0xff,
105 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
106 0x5b, 0x83, 0x5e, 0x00,
107 0xff
111 static int saa7113_init (struct budget_av *budget_av)
113 struct budget *budget = &budget_av->budget;
114 const u8 *data = saa7113_tab;
116 if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) {
117 DEB_D(("saa7113: not found on KNC card\n"));
118 return -ENODEV;
121 INFO(("saa7113: detected and initializing\n"));
123 while (*data != 0xff) {
124 i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1));
125 data += 2;
128 DEB_D(("saa7113: status=%02x\n",
129 i2c_readreg(budget->i2c_bus, 0x4a, 0x1f)));
131 return 0;
135 static int saa7113_setinput (struct budget_av *budget_av, int input)
137 struct budget *budget = &budget_av->budget;
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;
148 budget_av->cur_input = input;
149 return 0;
153 static int budget_av_detach (struct saa7146_dev *dev)
155 struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
156 int err;
158 DEB_EE(("dev: %p\n",dev));
160 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
162 dvb_delay(200);
164 saa7146_unregister_device (&budget_av->vd, dev);
166 err = ttpci_budget_deinit (&budget_av->budget);
168 kfree (budget_av);
170 return err;
174 static int budget_av_attach (struct saa7146_dev* dev,
175 struct saa7146_pci_extension_data *info)
177 struct budget_av *budget_av;
178 struct budget_info *bi = info->ext_priv;
179 int err;
181 DEB_EE(("dev: %p\n",dev));
183 if (bi->type != BUDGET_KNC1) {
184 return -ENODEV;
187 if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
188 return -ENOMEM;
190 memset(budget_av, 0, sizeof(struct budget_av));
192 if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) {
193 kfree(budget_av);
194 return err;
197 dev->ext_priv = budget_av;
199 /* knc1 initialization */
200 saa7146_write(dev, DD1_STREAM_B, 0x04000000);
201 saa7146_write(dev, DD1_INIT, 0x07000600);
202 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
204 //test_knc_ci(av7110);
206 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
207 dvb_delay(500);
209 if ((err = saa7113_init (budget_av))) {
210 budget_av_detach(dev);
211 return err;
214 saa7146_vv_init(dev);
215 if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1",
216 VFL_TYPE_GRABBER)))
218 ERR(("cannot register capture v4l2 device.\n"));
219 budget_av_detach(dev);
220 return err;
223 /* beware: this modifies dev->vv ... */
224 saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
225 SAA7146_HPS_SYNC_PORT_A);
227 saa7113_setinput (budget_av, 0);
229 /* what is this? since we don't support open()/close()
230 notifications, we simply put this into the release handler... */
232 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
233 set_current_state(TASK_INTERRUPTIBLE);
234 schedule_timeout (20);
236 /* fixme: find some sane values here... */
237 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
239 return 0;
244 #define KNC1_INPUTS 2
245 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
246 { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
247 { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
251 static struct saa7146_extension_ioctls ioctls[] = {
252 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
253 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
254 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
255 { 0, 0 }
259 static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg)
261 struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
263 struct saa7146_vv *vv = dev->vv_data;
265 switch(cmd) {
266 case VIDIOC_ENUMINPUT:
268 struct v4l2_input *i = arg;
270 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
271 if( i->index < 0 || i->index >= KNC1_INPUTS) {
272 return -EINVAL;
274 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
275 return 0;
277 case VIDIOC_G_INPUT:
279 int *input = (int *)arg;
281 *input = budget_av->cur_input;
283 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
284 return 0;
286 case VIDIOC_S_INPUT:
288 int input = *(int *)arg;
289 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
290 return saa7113_setinput (budget_av, input);
292 default:
294 DEB2(printk("does not handle this ioctl.\n"));
296 return -ENOIOCTLCMD;
298 return 0;
301 static struct saa7146_standard standard[] = {
302 { "PAL", V4L2_STD_PAL, SAA7146_PAL_VALUES },
303 { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES },
307 static struct saa7146_ext_vv vv_data = {
308 .inputs = 2,
309 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
310 .flags = 0,
311 .stds = &standard[0],
312 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
313 .ioctls = &ioctls[0],
314 .ioctl = av_ioctl,
319 static struct saa7146_extension budget_extension;
322 MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1);
324 static struct pci_device_id pci_tbl [] = {
325 MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56),
327 .vendor = 0,
331 MODULE_DEVICE_TABLE(pci, pci_tbl);
333 static struct saa7146_extension budget_extension = {
334 .name = "budget dvb /w video in\0",
335 .pci_tbl = pci_tbl,
337 .module = THIS_MODULE,
338 .attach = budget_av_attach,
339 .detach = budget_av_detach,
341 .ext_vv_data = &vv_data,
343 .irq_mask = MASK_10,
344 .irq_func = ttpci_budget_irq10_handler,
348 static int __init budget_av_init(void)
350 DEB_EE((".\n"));
352 if (saa7146_register_extension(&budget_extension))
353 return -ENODEV;
355 return 0;
359 static void __exit budget_av_exit(void)
361 DEB_EE((".\n"));
362 saa7146_unregister_extension(&budget_extension);
365 module_init(budget_av_init);
366 module_exit(budget_av_exit);
368 MODULE_LICENSE("GPL");
369 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
370 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
371 "budget PCI DVB w/ analog input (e.g. the KNC cards)");