[PATCH] dvb: stv0299: reduce i2c xfer and set register 0x12 from inittab
[linux/fpc-iii.git] / drivers / media / dvb / ttpci / budget-av.c
blobaa75dc03a0b3ae082179ff5c01a4ad2aa52b84bf
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 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
8 * Andrew de Quincey <adq_dvb@lidskialf.net>
10 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
12 * Copyright (C) 1999-2002 Ralph Metzler
13 * & Marcus Metzler for convergence integrated media GmbH
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
33 * the project's page is at http://www.linuxtv.org/dvb/
36 #include "budget.h"
37 #include "stv0299.h"
38 #include "tda10021.h"
39 #include "tda1004x.h"
40 #include <media/saa7146_vv.h>
41 #include <linux/module.h>
42 #include <linux/errno.h>
43 #include <linux/slab.h>
44 #include <linux/interrupt.h>
45 #include <linux/input.h>
46 #include <linux/spinlock.h>
48 #include "dvb_ca_en50221.h"
50 #define DEBICICAM 0x02420000
52 struct budget_av {
53 struct budget budget;
54 struct video_device *vd;
55 int cur_input;
56 int has_saa7113;
57 struct tasklet_struct ciintf_irq_tasklet;
58 int slot_status;
59 struct dvb_ca_en50221 ca;
62 /* GPIO CI Connections:
63 * 0 - Vcc/Reset (Reset is controlled by capacitor)
64 * 1 - Attribute Memory
65 * 2 - Card Enable (Active Low)
66 * 3 - Card Detect
69 /****************************************************************************
70 * INITIALIZATION
71 ****************************************************************************/
73 static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
75 u8 mm1[] = { 0x00 };
76 u8 mm2[] = { 0x00 };
77 struct i2c_msg msgs[2];
79 msgs[0].flags = 0;
80 msgs[1].flags = I2C_M_RD;
81 msgs[0].addr = msgs[1].addr = id / 2;
82 mm1[0] = reg;
83 msgs[0].len = 1;
84 msgs[1].len = 1;
85 msgs[0].buf = mm1;
86 msgs[1].buf = mm2;
88 i2c_transfer(i2c, msgs, 2);
90 return mm2[0];
93 static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
95 u8 mm1[] = { reg };
96 struct i2c_msg msgs[2] = {
97 {.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
98 {.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
101 if (i2c_transfer(i2c, msgs, 2) != 2)
102 return -EIO;
104 return 0;
107 static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
109 u8 msg[2] = { reg, val };
110 struct i2c_msg msgs;
112 msgs.flags = 0;
113 msgs.addr = id / 2;
114 msgs.len = 2;
115 msgs.buf = msg;
116 return i2c_transfer(i2c, &msgs, 1);
119 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
121 struct budget_av *budget_av = (struct budget_av *) ca->data;
122 int result;
124 if (slot != 0)
125 return -EINVAL;
127 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
128 udelay(1);
130 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
132 if (result == -ETIMEDOUT)
133 budget_av->slot_status = 0;
134 return result;
137 static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
139 struct budget_av *budget_av = (struct budget_av *) ca->data;
140 int result;
142 if (slot != 0)
143 return -EINVAL;
145 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
146 udelay(1);
148 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
150 if (result == -ETIMEDOUT)
151 budget_av->slot_status = 0;
152 return result;
155 static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
157 struct budget_av *budget_av = (struct budget_av *) ca->data;
158 int result;
160 if (slot != 0)
161 return -EINVAL;
163 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
164 udelay(1);
166 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
168 if (result == -ETIMEDOUT)
169 budget_av->slot_status = 0;
170 return result;
173 static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
175 struct budget_av *budget_av = (struct budget_av *) ca->data;
176 int result;
178 if (slot != 0)
179 return -EINVAL;
181 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
182 udelay(1);
184 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
186 if (result == -ETIMEDOUT)
187 budget_av->slot_status = 0;
188 return result;
191 static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
193 struct budget_av *budget_av = (struct budget_av *) ca->data;
194 struct saa7146_dev *saa = budget_av->budget.dev;
195 int timeout = 500; // 5 seconds (4.4.6 Ready)
197 if (slot != 0)
198 return -EINVAL;
200 dprintk(1, "ciintf_slot_reset\n");
202 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
204 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
205 msleep(2);
206 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
207 msleep(20); /* 20 ms Vcc settling time */
209 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
211 /* This should have been based on pin 16 READY of the pcmcia port,
212 * but AFAICS it is not routed to the saa7146 */
213 while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
214 msleep(100);
216 if (timeout <= 0)
218 printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
219 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
220 return -ETIMEDOUT;
223 return 0;
226 static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
228 struct budget_av *budget_av = (struct budget_av *) ca->data;
229 struct saa7146_dev *saa = budget_av->budget.dev;
231 if (slot != 0)
232 return -EINVAL;
234 dprintk(1, "ciintf_slot_shutdown\n");
236 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
237 budget_av->slot_status = 0;
238 return 0;
241 static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
243 struct budget_av *budget_av = (struct budget_av *) ca->data;
244 struct saa7146_dev *saa = budget_av->budget.dev;
246 if (slot != 0)
247 return -EINVAL;
249 dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
251 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
252 return 0;
255 static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
257 struct budget_av *budget_av = (struct budget_av *) ca->data;
258 struct saa7146_dev *saa = budget_av->budget.dev;
260 if (slot != 0)
261 return -EINVAL;
263 if (!budget_av->slot_status) {
264 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
265 udelay(1);
266 if (saa7146_read(saa, PSR) & MASK_06)
268 printk(KERN_INFO "budget-av: cam inserted\n");
269 budget_av->slot_status = 1;
271 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
272 } else if (!open) {
273 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
274 if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
276 printk(KERN_INFO "budget-av: cam ejected\n");
277 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
278 budget_av->slot_status = 0;
282 if (budget_av->slot_status == 1)
283 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
285 return 0;
288 static int ciintf_init(struct budget_av *budget_av)
290 struct saa7146_dev *saa = budget_av->budget.dev;
291 int result;
293 memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
295 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
296 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
297 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
298 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
300 /* Enable DEBI pins */
301 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
303 /* register CI interface */
304 budget_av->ca.owner = THIS_MODULE;
305 budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
306 budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
307 budget_av->ca.read_cam_control = ciintf_read_cam_control;
308 budget_av->ca.write_cam_control = ciintf_write_cam_control;
309 budget_av->ca.slot_reset = ciintf_slot_reset;
310 budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
311 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
312 budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
313 budget_av->ca.data = budget_av;
315 if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
316 &budget_av->ca, 0, 1)) != 0) {
317 printk(KERN_ERR "budget-av: ci initialisation failed.\n");
318 goto error;
321 printk(KERN_INFO "budget-av: ci interface initialised.\n");
322 budget_av->budget.ci_present = 1;
323 return 0;
325 error:
326 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
327 return result;
330 static void ciintf_deinit(struct budget_av *budget_av)
332 struct saa7146_dev *saa = budget_av->budget.dev;
334 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
335 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
336 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
337 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
339 /* release the CA device */
340 dvb_ca_en50221_release(&budget_av->ca);
342 /* disable DEBI pins */
343 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
347 static const u8 saa7113_tab[] = {
348 0x01, 0x08,
349 0x02, 0xc0,
350 0x03, 0x33,
351 0x04, 0x00,
352 0x05, 0x00,
353 0x06, 0xeb,
354 0x07, 0xe0,
355 0x08, 0x28,
356 0x09, 0x00,
357 0x0a, 0x80,
358 0x0b, 0x47,
359 0x0c, 0x40,
360 0x0d, 0x00,
361 0x0e, 0x01,
362 0x0f, 0x44,
364 0x10, 0x08,
365 0x11, 0x0c,
366 0x12, 0x7b,
367 0x13, 0x00,
368 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
370 0x57, 0xff,
371 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
372 0x5b, 0x83, 0x5e, 0x00,
373 0xff
376 static int saa7113_init(struct budget_av *budget_av)
378 struct budget *budget = &budget_av->budget;
379 struct saa7146_dev *saa = budget->dev;
380 const u8 *data = saa7113_tab;
382 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
383 msleep(200);
385 if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
386 dprintk(1, "saa7113 not found on KNC card\n");
387 return -ENODEV;
390 dprintk(1, "saa7113 detected and initializing\n");
392 while (*data != 0xff) {
393 i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
394 data += 2;
397 dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
399 return 0;
402 static int saa7113_setinput(struct budget_av *budget_av, int input)
404 struct budget *budget = &budget_av->budget;
406 if (1 != budget_av->has_saa7113)
407 return -ENODEV;
409 if (input == 1) {
410 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
411 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
412 } else if (input == 0) {
413 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
414 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
415 } else
416 return -EINVAL;
418 budget_av->cur_input = input;
419 return 0;
423 static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
425 u8 aclk = 0;
426 u8 bclk = 0;
427 u8 m1;
429 aclk = 0xb5;
430 if (srate < 2000000)
431 bclk = 0x86;
432 else if (srate < 5000000)
433 bclk = 0x89;
434 else if (srate < 15000000)
435 bclk = 0x8f;
436 else if (srate < 45000000)
437 bclk = 0x95;
439 m1 = 0x14;
440 if (srate < 4000000)
441 m1 = 0x10;
443 stv0299_writereg(fe, 0x13, aclk);
444 stv0299_writereg(fe, 0x14, bclk);
445 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
446 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
447 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
448 stv0299_writereg(fe, 0x0f, 0x80 | m1);
450 return 0;
453 static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
454 struct i2c_adapter *i2c,
455 struct dvb_frontend_parameters *params)
457 u32 div;
458 u8 buf[4];
459 struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
461 if ((params->frequency < 950000) || (params->frequency > 2150000))
462 return -EINVAL;
464 div = (params->frequency + (125 - 1)) / 125; // round correctly
465 buf[0] = (div >> 8) & 0x7f;
466 buf[1] = div & 0xff;
467 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
468 buf[3] = 0x20;
470 if (params->u.qpsk.symbol_rate < 4000000)
471 buf[3] |= 1;
473 if (params->frequency < 1250000)
474 buf[3] |= 0;
475 else if (params->frequency < 1550000)
476 buf[3] |= 0x40;
477 else if (params->frequency < 2050000)
478 buf[3] |= 0x80;
479 else if (params->frequency < 2150000)
480 buf[3] |= 0xC0;
482 if (i2c_transfer(i2c, &msg, 1) != 1)
483 return -EIO;
484 return 0;
487 static u8 typhoon_cinergy1200s_inittab[] = {
488 0x01, 0x15,
489 0x02, 0x30,
490 0x03, 0x00,
491 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
492 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
493 0x06, 0x40, /* DAC not used, set to high impendance mode */
494 0x07, 0x00, /* DAC LSB */
495 0x08, 0x40, /* DiSEqC off */
496 0x09, 0x00, /* FIFO */
497 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
498 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
499 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
500 0x10, 0x3f, // AGC2 0x3d
501 0x11, 0x84,
502 0x12, 0xb9,
503 0x15, 0xc9, // lock detector threshold
504 0x16, 0x00,
505 0x17, 0x00,
506 0x18, 0x00,
507 0x19, 0x00,
508 0x1a, 0x00,
509 0x1f, 0x50,
510 0x20, 0x00,
511 0x21, 0x00,
512 0x22, 0x00,
513 0x23, 0x00,
514 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
515 0x29, 0x1e, // 1/2 threshold
516 0x2a, 0x14, // 2/3 threshold
517 0x2b, 0x0f, // 3/4 threshold
518 0x2c, 0x09, // 5/6 threshold
519 0x2d, 0x05, // 7/8 threshold
520 0x2e, 0x01,
521 0x31, 0x1f, // test all FECs
522 0x32, 0x19, // viterbi and synchro search
523 0x33, 0xfc, // rs control
524 0x34, 0x93, // error control
525 0x0f, 0x92,
526 0xff, 0xff
529 static struct stv0299_config typhoon_config = {
530 .demod_address = 0x68,
531 .inittab = typhoon_cinergy1200s_inittab,
532 .mclk = 88000000UL,
533 .invert = 0,
534 .skip_reinit = 0,
535 .lock_output = STV0229_LOCKOUTPUT_1,
536 .volt13_op0_op1 = STV0299_VOLT13_OP0,
537 .min_delay_ms = 100,
538 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
539 .pll_set = philips_su1278_ty_ci_pll_set,
543 static struct stv0299_config cinergy_1200s_config = {
544 .demod_address = 0x68,
545 .inittab = typhoon_cinergy1200s_inittab,
546 .mclk = 88000000UL,
547 .invert = 0,
548 .skip_reinit = 0,
549 .lock_output = STV0229_LOCKOUTPUT_0,
550 .volt13_op0_op1 = STV0299_VOLT13_OP0,
551 .min_delay_ms = 100,
552 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
553 .pll_set = philips_su1278_ty_ci_pll_set,
557 static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
559 struct budget *budget = (struct budget *) fe->dvb->priv;
560 u8 buf[4];
561 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
563 #define TUNER_MUL 62500
565 u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
567 buf[0] = (div >> 8) & 0x7f;
568 buf[1] = div & 0xff;
569 buf[2] = 0x86;
570 buf[3] = (params->frequency < 150000000 ? 0x01 :
571 params->frequency < 445000000 ? 0x02 : 0x04);
573 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
574 return -EIO;
575 return 0;
578 static struct tda10021_config philips_cu1216_config = {
579 .demod_address = 0x0c,
580 .pll_set = philips_cu1216_pll_set,
586 static int philips_tu1216_pll_init(struct dvb_frontend *fe)
588 struct budget *budget = (struct budget *) fe->dvb->priv;
589 static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
590 struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
592 // setup PLL configuration
593 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
594 return -EIO;
595 msleep(1);
597 return 0;
600 static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
602 struct budget *budget = (struct budget *) fe->dvb->priv;
603 u8 tuner_buf[4];
604 struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
605 sizeof(tuner_buf) };
606 int tuner_frequency = 0;
607 u8 band, cp, filter;
609 // determine charge pump
610 tuner_frequency = params->frequency + 36166000;
611 if (tuner_frequency < 87000000)
612 return -EINVAL;
613 else if (tuner_frequency < 130000000)
614 cp = 3;
615 else if (tuner_frequency < 160000000)
616 cp = 5;
617 else if (tuner_frequency < 200000000)
618 cp = 6;
619 else if (tuner_frequency < 290000000)
620 cp = 3;
621 else if (tuner_frequency < 420000000)
622 cp = 5;
623 else if (tuner_frequency < 480000000)
624 cp = 6;
625 else if (tuner_frequency < 620000000)
626 cp = 3;
627 else if (tuner_frequency < 830000000)
628 cp = 5;
629 else if (tuner_frequency < 895000000)
630 cp = 7;
631 else
632 return -EINVAL;
634 // determine band
635 if (params->frequency < 49000000)
636 return -EINVAL;
637 else if (params->frequency < 161000000)
638 band = 1;
639 else if (params->frequency < 444000000)
640 band = 2;
641 else if (params->frequency < 861000000)
642 band = 4;
643 else
644 return -EINVAL;
646 // setup PLL filter
647 switch (params->u.ofdm.bandwidth) {
648 case BANDWIDTH_6_MHZ:
649 filter = 0;
650 break;
652 case BANDWIDTH_7_MHZ:
653 filter = 0;
654 break;
656 case BANDWIDTH_8_MHZ:
657 filter = 1;
658 break;
660 default:
661 return -EINVAL;
664 // calculate divisor
665 // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
666 tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
668 // setup tuner buffer
669 tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
670 tuner_buf[1] = tuner_frequency & 0xff;
671 tuner_buf[2] = 0xca;
672 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
674 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
675 return -EIO;
677 msleep(1);
678 return 0;
681 static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
682 const struct firmware **fw, char *name)
684 struct budget *budget = (struct budget *) fe->dvb->priv;
686 return request_firmware(fw, name, &budget->dev->pci->dev);
689 static struct tda1004x_config philips_tu1216_config = {
691 .demod_address = 0x8,
692 .invert = 1,
693 .invert_oclk = 1,
694 .xtal_freq = TDA10046_XTAL_4M,
695 .agc_config = TDA10046_AGC_DEFAULT,
696 .if_freq = TDA10046_FREQ_3617,
697 .pll_init = philips_tu1216_pll_init,
698 .pll_set = philips_tu1216_pll_set,
699 .pll_sleep = NULL,
700 .request_firmware = philips_tu1216_request_firmware,
706 static u8 read_pwm(struct budget_av *budget_av)
708 u8 b = 0xff;
709 u8 pwm;
710 struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
711 {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
714 if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
715 || (pwm == 0xff))
716 pwm = 0x48;
718 return pwm;
721 #define SUBID_DVBS_KNC1 0x0010
722 #define SUBID_DVBS_KNC1_PLUS 0x0011
723 #define SUBID_DVBS_TYPHOON 0x4f56
724 #define SUBID_DVBS_CINERGY1200 0x1154
726 #define SUBID_DVBC_KNC1 0x0020
727 #define SUBID_DVBC_KNC1_PLUS 0x0021
728 #define SUBID_DVBC_CINERGY1200 0x1156
730 #define SUBID_DVBT_KNC1_PLUS 0x0031
731 #define SUBID_DVBT_KNC1 0x0030
732 #define SUBID_DVBT_CINERGY1200 0x1157
734 static void frontend_init(struct budget_av *budget_av)
736 struct saa7146_dev * saa = budget_av->budget.dev;
737 struct dvb_frontend * fe = NULL;
739 switch (saa->pci->subsystem_device) {
740 case SUBID_DVBS_KNC1_PLUS:
741 case SUBID_DVBC_KNC1_PLUS:
742 case SUBID_DVBT_KNC1_PLUS:
743 // Enable / PowerON Frontend
744 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
745 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
746 break;
749 switch (saa->pci->subsystem_device) {
751 case SUBID_DVBS_KNC1:
752 case SUBID_DVBS_KNC1_PLUS:
753 case SUBID_DVBS_TYPHOON:
754 fe = stv0299_attach(&typhoon_config,
755 &budget_av->budget.i2c_adap);
756 break;
758 case SUBID_DVBS_CINERGY1200:
759 fe = stv0299_attach(&cinergy_1200s_config,
760 &budget_av->budget.i2c_adap);
761 break;
763 case SUBID_DVBC_KNC1:
764 case SUBID_DVBC_KNC1_PLUS:
765 fe = tda10021_attach(&philips_cu1216_config,
766 &budget_av->budget.i2c_adap,
767 read_pwm(budget_av));
768 break;
770 case SUBID_DVBT_KNC1:
771 case SUBID_DVBT_KNC1_PLUS:
772 fe = tda10046_attach(&philips_tu1216_config,
773 &budget_av->budget.i2c_adap);
774 break;
776 case SUBID_DVBC_CINERGY1200:
777 fe = tda10021_attach(&philips_cu1216_config,
778 &budget_av->budget.i2c_adap,
779 read_pwm(budget_av));
780 break;
782 case SUBID_DVBT_CINERGY1200:
783 fe = tda10046_attach(&philips_tu1216_config,
784 &budget_av->budget.i2c_adap);
785 break;
788 if (fe == NULL) {
789 printk(KERN_ERR "budget-av: A frontend driver was not found "
790 "for device %04x/%04x subsystem %04x/%04x\n",
791 saa->pci->vendor,
792 saa->pci->device,
793 saa->pci->subsystem_vendor,
794 saa->pci->subsystem_device);
795 return;
798 budget_av->budget.dvb_frontend = fe;
800 if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
801 budget_av->budget.dvb_frontend)) {
802 printk(KERN_ERR "budget-av: Frontend registration failed!\n");
803 if (budget_av->budget.dvb_frontend->ops->release)
804 budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
805 budget_av->budget.dvb_frontend = NULL;
810 static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
812 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
814 dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
816 if (*isr & MASK_10)
817 ttpci_budget_irq10_handler(dev, isr);
820 static int budget_av_detach(struct saa7146_dev *dev)
822 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
823 int err;
825 dprintk(2, "dev: %p\n", dev);
827 if (1 == budget_av->has_saa7113) {
828 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
830 msleep(200);
832 saa7146_unregister_device(&budget_av->vd, dev);
835 if (budget_av->budget.ci_present)
836 ciintf_deinit(budget_av);
838 if (budget_av->budget.dvb_frontend != NULL)
839 dvb_unregister_frontend(budget_av->budget.dvb_frontend);
840 err = ttpci_budget_deinit(&budget_av->budget);
842 kfree(budget_av);
844 return err;
847 static struct saa7146_ext_vv vv_data;
849 static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
851 struct budget_av *budget_av;
852 u8 *mac;
853 int err;
855 dprintk(2, "dev: %p\n", dev);
857 if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
858 return -ENOMEM;
860 memset(budget_av, 0, sizeof(struct budget_av));
862 budget_av->has_saa7113 = 0;
863 budget_av->budget.ci_present = 0;
865 dev->ext_priv = budget_av;
867 if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
868 kfree(budget_av);
869 return err;
872 /* knc1 initialization */
873 saa7146_write(dev, DD1_STREAM_B, 0x04000000);
874 saa7146_write(dev, DD1_INIT, 0x07000600);
875 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
877 if (saa7113_init(budget_av) == 0) {
878 budget_av->has_saa7113 = 1;
880 if (0 != saa7146_vv_init(dev, &vv_data)) {
881 /* fixme: proper cleanup here */
882 ERR(("cannot init vv subsystem.\n"));
883 return err;
886 if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
887 /* fixme: proper cleanup here */
888 ERR(("cannot register capture v4l2 device.\n"));
889 return err;
892 /* beware: this modifies dev->vv ... */
893 saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
894 SAA7146_HPS_SYNC_PORT_A);
896 saa7113_setinput(budget_av, 0);
897 } else {
898 ciintf_init(budget_av);
901 /* fixme: find some sane values here... */
902 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
904 mac = budget_av->budget.dvb_adapter.proposed_mac;
905 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
906 printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
907 budget_av->budget.dvb_adapter.num);
908 memset(mac, 0, 6);
909 } else {
910 printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
911 budget_av->budget.dvb_adapter.num,
912 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
915 budget_av->budget.dvb_adapter.priv = budget_av;
916 frontend_init(budget_av);
918 return 0;
921 #define KNC1_INPUTS 2
922 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
923 {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
924 {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
927 static struct saa7146_extension_ioctls ioctls[] = {
928 {VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
929 {VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
930 {VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
931 {0, 0}
934 static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
936 struct saa7146_dev *dev = fh->dev;
937 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
939 switch (cmd) {
940 case VIDIOC_ENUMINPUT:{
941 struct v4l2_input *i = arg;
943 dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
944 if (i->index < 0 || i->index >= KNC1_INPUTS) {
945 return -EINVAL;
947 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
948 return 0;
950 case VIDIOC_G_INPUT:{
951 int *input = (int *) arg;
953 *input = budget_av->cur_input;
955 dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
956 return 0;
958 case VIDIOC_S_INPUT:{
959 int input = *(int *) arg;
960 dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
961 return saa7113_setinput(budget_av, input);
963 default:
964 return -ENOIOCTLCMD;
966 return 0;
969 static struct saa7146_standard standard[] = {
970 {.name = "PAL",.id = V4L2_STD_PAL,
971 .v_offset = 0x17,.v_field = 288,
972 .h_offset = 0x14,.h_pixels = 680,
973 .v_max_out = 576,.h_max_out = 768 },
975 {.name = "NTSC",.id = V4L2_STD_NTSC,
976 .v_offset = 0x16,.v_field = 240,
977 .h_offset = 0x06,.h_pixels = 708,
978 .v_max_out = 480,.h_max_out = 640, },
981 static struct saa7146_ext_vv vv_data = {
982 .inputs = 2,
983 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
984 .flags = 0,
985 .stds = &standard[0],
986 .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
987 .ioctls = &ioctls[0],
988 .ioctl = av_ioctl,
991 static struct saa7146_extension budget_extension;
993 MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
994 MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
995 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
996 MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
997 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
998 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
999 MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
1000 MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
1001 MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
1003 static struct pci_device_id pci_tbl[] = {
1004 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
1005 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
1006 MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
1007 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
1008 MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
1009 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
1010 MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
1011 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
1012 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
1013 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
1015 .vendor = 0,
1019 MODULE_DEVICE_TABLE(pci, pci_tbl);
1021 static struct saa7146_extension budget_extension = {
1022 .name = "budget_av",
1023 .pci_tbl = pci_tbl,
1025 .module = THIS_MODULE,
1026 .attach = budget_av_attach,
1027 .detach = budget_av_detach,
1029 .irq_mask = MASK_10,
1030 .irq_func = budget_av_irq,
1033 static int __init budget_av_init(void)
1035 return saa7146_register_extension(&budget_extension);
1038 static void __exit budget_av_exit(void)
1040 saa7146_unregister_extension(&budget_extension);
1043 module_init(budget_av_init);
1044 module_exit(budget_av_exit);
1046 MODULE_LICENSE("GPL");
1047 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1048 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1049 "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");