2 * budget-av.c: driver for the SAA7146 based Budget DVB cards
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>
36 #include "dvb_functions.h"
40 struct video_device vd;
45 /****************************************************************************
47 ****************************************************************************/
50 static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg)
54 struct i2c_msg msgs[2];
57 msgs[1].flags = I2C_M_RD;
58 msgs[0].addr = msgs[1].addr=id/2;
60 msgs[0].len = 1; msgs[1].len = 1;
61 msgs[0].buf = mm1; msgs[1].buf = mm2;
63 i2c->xfer(i2c, msgs, 2);
68 static int i2c_readregs(struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 *buf, u8 len)
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 }
76 if (i2c->xfer(i2c, msgs, 2) != 2)
82 static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val)
84 u8 msg[2]={ reg, val };
91 return i2c->xfer (i2c, &msgs, 1);
95 static const u8 saa7113_tab[] = {
116 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
119 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
120 0x5b, 0x83, 0x5e, 0x00,
125 static int saa7113_init (struct budget_av *budget_av)
127 struct budget *budget = &budget_av->budget;
128 const u8 *data = saa7113_tab;
130 if (i2c_writereg (budget->i2c_bus, 0x4a, 0x01, 0x08) != 1) {
131 DEB_D(("saa7113: not found on KNC card\n"));
135 INFO(("saa7113: detected and initializing\n"));
137 while (*data != 0xff) {
138 i2c_writereg(budget->i2c_bus, 0x4a, *data, *(data+1));
142 DEB_D(("saa7113: status=%02x\n",
143 i2c_readreg(budget->i2c_bus, 0x4a, 0x1f)));
149 static int saa7113_setinput (struct budget_av *budget_av, int input)
151 struct budget *budget = &budget_av->budget;
153 if ( 1 != budget_av->has_saa7113 )
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);
165 budget_av->cur_input = input;
170 static int budget_av_detach (struct saa7146_dev *dev)
172 struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
175 DEB_EE(("dev: %p\n",dev));
177 if ( 1 == budget_av->has_saa7113 ) {
178 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
182 saa7146_unregister_device (&budget_av->vd, dev);
185 err = ttpci_budget_deinit (&budget_av->budget);
192 static struct saa7146_ext_vv vv_data;
194 static int budget_av_attach (struct saa7146_dev* dev,
195 struct saa7146_pci_extension_data *info)
197 struct budget_av *budget_av;
198 struct budget_info *bi = info->ext_priv;
202 DEB_EE(("dev: %p\n",dev));
204 if (bi->type != BUDGET_KNC1) {
208 if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
211 memset(budget_av, 0, sizeof(struct budget_av));
213 if ((err = ttpci_budget_init(&budget_av->budget, dev, info))) {
218 dev->ext_priv = budget_av;
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);
225 //test_knc_ci(av7110);
227 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
230 if ( 0 == saa7113_init(budget_av) ) {
231 budget_av->has_saa7113 = 1;
233 if ( 0 != saa7146_vv_init(dev,&vv_data)) {
234 /* fixme: proper cleanup here */
235 ERR(("cannot init vv subsystem.\n"));
239 if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1",
242 /* fixme: proper cleanup here */
243 ERR(("cannot register capture v4l2 device.\n"));
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);
251 saa7113_setinput (budget_av, 0);
253 budget_av->has_saa7113 = 0;
255 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
258 /* fixme: find some sane values here... */
259 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
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);
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]);
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 },
283 static struct saa7146_extension_ioctls ioctls[] = {
284 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
285 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
286 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
291 static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
293 struct saa7146_dev *dev = fh->dev;
294 struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
296 struct saa7146_vv *vv = dev->vv_data;
299 case VIDIOC_ENUMINPUT:
301 struct v4l2_input *i = arg;
303 DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
304 if( i->index < 0 || i->index >= KNC1_INPUTS) {
307 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
312 int *input = (int *)arg;
314 *input = budget_av->cur_input;
316 DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
321 int input = *(int *)arg;
322 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
323 return saa7113_setinput (budget_av, input);
327 DEB2(printk("does not handle this ioctl.\n"));
334 static struct saa7146_standard standard[] = {
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
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,
348 static struct saa7146_ext_vv vv_data = {
350 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
352 .stds = &standard[0],
353 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
354 .ioctls = &ioctls[0],
360 static struct saa7146_extension budget_extension;
363 MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1);
365 static struct pci_device_id pci_tbl [] = {
366 MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56),
372 MODULE_DEVICE_TABLE(pci, pci_tbl);
374 static struct saa7146_extension budget_extension = {
375 .name = "budget dvb /w video in\0",
378 .module = THIS_MODULE,
379 .attach = budget_av_attach,
380 .detach = budget_av_detach,
383 .irq_func = ttpci_budget_irq10_handler,
387 static int __init budget_av_init(void)
391 if (saa7146_register_extension(&budget_extension))
398 static void __exit budget_av_exit(void)
401 saa7146_unregister_extension(&budget_extension);
404 module_init(budget_av_init);
405 module_exit(budget_av_exit);
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)");