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 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
8 * Andrew de Quincey <adq_dvb@lidskialf.net>
9 *
10 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
11 *
12 * Copyright (C) 1999-2002 Ralph Metzler
13 * & Marcus Metzler for convergence integrated media GmbH
14 *
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.
19 *
20 *
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.
25 *
26 *
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
31 *
32 *
33 * the project's page is at http://www.linuxtv.org/dvb/
34 */
35
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>
47
48 #include "dvb_ca_en50221.h"
49
50 #define DEBICICAM 0x02420000
51
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;
60 };
61
62 int enable_ci = 0;
63
64
65 /****************************************************************************
66 * INITIALIZATION
67 ****************************************************************************/
68
69
70 static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg)
71 {
72 u8 mm1[] = {0x00};
73 u8 mm2[] = {0x00};
74 struct i2c_msg msgs[2];
75
76 msgs[0].flags = 0;
77 msgs[1].flags = I2C_M_RD;
78 msgs[0].addr = msgs[1].addr=id/2;
79 mm1[0] = reg;
80 msgs[0].len = 1;
81 msgs[1].len = 1;
82 msgs[0].buf = mm1;
83 msgs[1].buf = mm2;
84
85 i2c_transfer(i2c, msgs, 2);
86
87 return mm2[0];
88 }
89
90 static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 *buf, u8 len)
91 {
92 u8 mm1[] = { reg };
93 struct i2c_msg msgs[2] = {
94 { .addr = id/2, .flags = 0, .buf = mm1, .len = 1 },
95 { .addr = id/2, .flags = I2C_M_RD, .buf = buf, .len = len }
96 };
97
98 if (i2c_transfer(i2c, msgs, 2) != 2)
99 return -EIO;
100
101 return 0;
102 }
103
104
105 static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
106 {
107 u8 msg[2]={ reg, val };
108 struct i2c_msg msgs;
109
110 msgs.flags=0;
111 msgs.addr=id/2;
112 msgs.len=2;
113 msgs.buf=msg;
114 return i2c_transfer(i2c, &msgs, 1);
115 }
116
117 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
118 {
119 struct budget_av *budget_av = (struct budget_av *) ca->data;
120 int result;
121
122 if (slot != 0)
123 return -EINVAL;
124
125 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
126 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
127
128 if (result == -ETIMEDOUT)
129 budget_av->slot_status = 0;
130 return result;
131 }
132
133 static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
134 {
135 struct budget_av *budget_av = (struct budget_av *) ca->data;
136 int result;
137
138 if (slot != 0)
139 return -EINVAL;
140
141 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
142 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
143
144 if (result == -ETIMEDOUT)
145 budget_av->slot_status = 0;
146 return result;
147 }
148
149 static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
150 {
151 struct budget_av *budget_av = (struct budget_av *) ca->data;
152 int result;
153
154 if (slot != 0)
155 return -EINVAL;
156
157 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
158 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
159
160 if (result == -ETIMEDOUT)
161 budget_av->slot_status = 0;
162 return result;
163 }
164
165 static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
166 {
167 struct budget_av *budget_av = (struct budget_av *) ca->data;
168 int result;
169
170 if (slot != 0)
171 return -EINVAL;
172
173 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
174 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
175
176 if (result == -ETIMEDOUT)
177 budget_av->slot_status = 0;
178 return result;
179 }
180
181 static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
182 {
183 struct budget_av *budget_av = (struct budget_av *) ca->data;
184 struct saa7146_dev *saa = budget_av->budget.dev;
185
186 if (slot != 0)
187 return -EINVAL;
188
189 dprintk(1, "ciintf_slot_reset\n");
190
191 /* reset the card */
192 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
193 msleep(100);
194 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
195 msleep(2000); /* horrendous I know, but its the only way to be absolutely sure without an IRQ line! */
196
197 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
198 return 0;
199 }
200
201 static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
202 {
203 struct budget_av *budget_av = (struct budget_av *) ca->data;
204 struct saa7146_dev *saa = budget_av->budget.dev;
205
206 if (slot != 0)
207 return -EINVAL;
208
209 dprintk(1, "ciintf_slot_shutdown\n");
210
211 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
212 budget_av->slot_status = 0;
213 return 0;
214 }
215
216 static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
217 {
218 struct budget_av *budget_av = (struct budget_av *) ca->data;
219 struct saa7146_dev *saa = budget_av->budget.dev;
220
221 if (slot != 0)
222 return -EINVAL;
223
224 dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
225
226 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
227 return 0;
228 }
229
230 static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
231 {
232 struct budget_av *budget_av = (struct budget_av *) ca->data;
233 struct saa7146_dev *saa = budget_av->budget.dev;
234 int cam = 0;
235
236 if (slot != 0)
237 return -EINVAL;
238
239 if (!budget_av->slot_status) {
240 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
241 udelay(1);
242 cam = saa7146_read(saa, PSR) & MASK_06;
243 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
244
245 if (cam)
246 budget_av->slot_status = 1;
247 } else if (!open) {
248 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
249 if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
250 budget_av->slot_status = 0;
251 }
252
253 if (budget_av->slot_status == 1)
254 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
255
256 return 0;
257 }
258
259 static int ciintf_init(struct budget_av *budget_av)
260 {
261 struct saa7146_dev *saa = budget_av->budget.dev;
262 int result;
263
264 memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
265
266 /* setup GPIOs */
267 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
268 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
269 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
270
271 /* Reset the card */
272 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
273 msleep(50);
274 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
275 msleep(100);
276
277 /* Enable DEBI pins */
278 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
279
280 /* register CI interface */
281 budget_av->ca.owner = THIS_MODULE;
282 budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
283 budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
284 budget_av->ca.read_cam_control = ciintf_read_cam_control;
285 budget_av->ca.write_cam_control = ciintf_write_cam_control;
286 budget_av->ca.slot_reset = ciintf_slot_reset;
287 budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
288 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
289 budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
290 budget_av->ca.data = budget_av;
291 if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter,
292 &budget_av->ca, 0, 1)) != 0) {
293 printk("budget_av: CI interface detected, but initialisation failed.\n");
294 goto error;
295 }
296 // success!
297 printk("ciintf_init: CI interface initialised\n");
298 budget_av->budget.ci_present = 1;
299 return 0;
300
301 error:
302 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
303 return result;
304 }
305
306 static void ciintf_deinit(struct budget_av *budget_av)
307 {
308 struct saa7146_dev *saa = budget_av->budget.dev;
309
310 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
311 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
312 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
313 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
314
315 /* release the CA device */
316 dvb_ca_en50221_release(&budget_av->ca);
317
318 /* disable DEBI pins */
319 saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
320 }
321
322
323 static const u8 saa7113_tab[] = {
324 0x01, 0x08,
325 0x02, 0xc0,
326 0x03, 0x33,
327 0x04, 0x00,
328 0x05, 0x00,
329 0x06, 0xeb,
330 0x07, 0xe0,
331 0x08, 0x28,
332 0x09, 0x00,
333 0x0a, 0x80,
334 0x0b, 0x47,
335 0x0c, 0x40,
336 0x0d, 0x00,
337 0x0e, 0x01,
338 0x0f, 0x44,
339
340 0x10, 0x08,
341 0x11, 0x0c,
342 0x12, 0x7b,
343 0x13, 0x00,
344 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
345
346 0x57, 0xff,
347 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
348 0x5b, 0x83, 0x5e, 0x00,
349 0xff
350 };
351
352
353 static int saa7113_init (struct budget_av *budget_av)
354 {
355 struct budget *budget = &budget_av->budget;
356 const u8 *data = saa7113_tab;
357
358 if (i2c_writereg (&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
359 dprintk(1, "saa7113 not found on KNC card\n");
360 return -ENODEV;
361 }
362
363 dprintk(1, "saa7113 detected and initializing\n");
364
365 while (*data != 0xff) {
366 i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data+1));
367 data += 2;
368 }
369
370 dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
371
372 return 0;
373 }
374
375
376 static int saa7113_setinput (struct budget_av *budget_av, int input)
377 {
378 struct budget *budget = &budget_av->budget;
379
380 if ( 1 != budget_av->has_saa7113 )
381 return -ENODEV;
382
383 if (input == 1) {
384 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
385 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
386 } else if (input == 0) {
387 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
388 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
389 } else
390 return -EINVAL;
391
392 budget_av->cur_input = input;
393 return 0;
394 }
395
396
397 static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
398 {
399 u8 aclk = 0;
400 u8 bclk = 0;
401 u8 m1;
402
403 aclk = 0xb5;
404 if (srate < 2000000)
405 bclk = 0x86;
406 else if (srate < 5000000)
407 bclk = 0x89;
408 else if (srate < 15000000)
409 bclk = 0x8f;
410 else if (srate < 45000000)
411 bclk = 0x95;
412
413 m1 = 0x14;
414 if (srate < 4000000)
415 m1 = 0x10;
416
417 stv0299_writereg(fe, 0x13, aclk);
418 stv0299_writereg(fe, 0x14, bclk);
419 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
420 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
421 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
422 stv0299_writereg(fe, 0x0f, 0x80 | m1);
423
424 return 0;
425 }
426
427 static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
428 struct dvb_frontend_parameters *params)
429 {
430 struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv;
431 u32 div;
432 u8 buf[4];
433 struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
434
435 if ((params->frequency < 950000) || (params->frequency > 2150000))
436 return -EINVAL;
437
438 div = (params->frequency + (125 - 1)) / 125; // round correctly
439 buf[0] = (div >> 8) & 0x7f;
440 buf[1] = div & 0xff;
441 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
442 buf[3] = 0x20;
443
444 if (params->u.qpsk.symbol_rate < 4000000)
445 buf[3] |= 1;
446
447 if (params->frequency < 1250000)
448 buf[3] |= 0;
449 else if (params->frequency < 1550000)
450 buf[3] |= 0x40;
451 else if (params->frequency < 2050000)
452 buf[3] |= 0x80;
453 else if (params->frequency < 2150000)
454 buf[3] |= 0xC0;
455
456 if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1)
457 return -EIO;
458 return 0;
459 }
460
461 static u8 typhoon_cinergy1200s_inittab[] = {
462 0x01, 0x15,
463 0x02, 0x30,
464 0x03, 0x00,
465 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
466 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
467 0x06, 0x40, /* DAC not used, set to high impendance mode */
468 0x07, 0x00, /* DAC LSB */
469 0x08, 0x40, /* DiSEqC off */
470 0x09, 0x00, /* FIFO */
471 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
472 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
473 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
474 0x10, 0x3f, // AGC2 0x3d
475 0x11, 0x84,
476 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
477 0x15, 0xc9, // lock detector threshold
478 0x16, 0x00,
479 0x17, 0x00,
480 0x18, 0x00,
481 0x19, 0x00,
482 0x1a, 0x00,
483 0x1f, 0x50,
484 0x20, 0x00,
485 0x21, 0x00,
486 0x22, 0x00,
487 0x23, 0x00,
488 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
489 0x29, 0x1e, // 1/2 threshold
490 0x2a, 0x14, // 2/3 threshold
491 0x2b, 0x0f, // 3/4 threshold
492 0x2c, 0x09, // 5/6 threshold
493 0x2d, 0x05, // 7/8 threshold
494 0x2e, 0x01,
495 0x31, 0x1f, // test all FECs
496 0x32, 0x19, // viterbi and synchro search
497 0x33, 0xfc, // rs control
498 0x34, 0x93, // error control
499 0x0f, 0x92,
500 0xff, 0xff
501 };
502
503 static struct stv0299_config typhoon_config = {
504 .demod_address = 0x68,
505 .inittab = typhoon_cinergy1200s_inittab,
506 .mclk = 88000000UL,
507 .invert = 0,
508 .enhanced_tuning = 0,
509 .skip_reinit = 0,
510 .lock_output = STV0229_LOCKOUTPUT_1,
511 .volt13_op0_op1 = STV0299_VOLT13_OP0,
512 .min_delay_ms = 100,
513 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
514 .pll_set = philips_su1278_ty_ci_pll_set,
515 };
516
517
518 static struct stv0299_config cinergy_1200s_config = {
519 .demod_address = 0x68,
520 .inittab = typhoon_cinergy1200s_inittab,
521 .mclk = 88000000UL,
522 .invert = 0,
523 .enhanced_tuning = 0,
524 .skip_reinit = 0,
525 .lock_output = STV0229_LOCKOUTPUT_0,
526 .volt13_op0_op1 = STV0299_VOLT13_OP0,
527 .min_delay_ms = 100,
528 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
529 .pll_set = philips_su1278_ty_ci_pll_set,
530 };
531
532
533 static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
534 {
535 struct budget *budget = (struct budget *) fe->dvb->priv;
536 u8 buf[4];
537 struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
538
539 #define TUNER_MUL 62500
540
541 u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
542
543 buf[0] = (div >> 8) & 0x7f;
544 buf[1] = div & 0xff;
545 buf[2] = 0x8e;
546 buf[3] = (params->frequency < 174500000 ? 0xa1 :
547 params->frequency < 454000000 ? 0x92 : 0x34);
548
549 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
550 return -EIO;
551 return 0;
552 }
553
554 static struct tda10021_config philips_cu1216_config = {
555 .demod_address = 0x0c,
556 .pll_set = philips_cu1216_pll_set,
557 };
558
559
560
561
562 static int philips_tu1216_pll_init(struct dvb_frontend *fe)
563 {
564 struct budget *budget = (struct budget *) fe->dvb->priv;
565 static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
566 struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
567
568 // setup PLL configuration
569 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
570 return -EIO;
571 msleep(1);
572
573 return 0;
574 }
575
576 static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
577 {
578 struct budget *budget = (struct budget *) fe->dvb->priv;
579 u8 tuner_buf[4];
580 struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
581 sizeof(tuner_buf) };
582 int tuner_frequency = 0;
583 u8 band, cp, filter;
584
585 // determine charge pump
586 tuner_frequency = params->frequency + 36166000;
587 if (tuner_frequency < 87000000)
588 return -EINVAL;
589 else if (tuner_frequency < 130000000)
590 cp = 3;
591 else if (tuner_frequency < 160000000)
592 cp = 5;
593 else if (tuner_frequency < 200000000)
594 cp = 6;
595 else if (tuner_frequency < 290000000)
596 cp = 3;
597 else if (tuner_frequency < 420000000)
598 cp = 5;
599 else if (tuner_frequency < 480000000)
600 cp = 6;
601 else if (tuner_frequency < 620000000)
602 cp = 3;
603 else if (tuner_frequency < 830000000)
604 cp = 5;
605 else if (tuner_frequency < 895000000)
606 cp = 7;
607 else
608 return -EINVAL;
609
610 // determine band
611 if (params->frequency < 49000000)
612 return -EINVAL;
613 else if (params->frequency < 161000000)
614 band = 1;
615 else if (params->frequency < 444000000)
616 band = 2;
617 else if (params->frequency < 861000000)
618 band = 4;
619 else
620 return -EINVAL;
621
622 // setup PLL filter
623 switch (params->u.ofdm.bandwidth) {
624 case BANDWIDTH_6_MHZ:
625 filter = 0;
626 break;
627
628 case BANDWIDTH_7_MHZ:
629 filter = 0;
630 break;
631
632 case BANDWIDTH_8_MHZ:
633 filter = 1;
634 break;
635
636 default:
637 return -EINVAL;
638 }
639
640 // calculate divisor
641 // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
642 tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
643
644 // setup tuner buffer
645 tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
646 tuner_buf[1] = tuner_frequency & 0xff;
647 tuner_buf[2] = 0xca;
648 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
649
650 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
651 return -EIO;
652
653 msleep(1);
654 return 0;
655 }
656
657 static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
658 const struct firmware **fw, char *name)
659 {
660 struct budget *budget = (struct budget *) fe->dvb->priv;
661
662 return request_firmware(fw, name, &budget->dev->pci->dev);
663 }
664
665 struct tda1004x_config philips_tu1216_config = {
666
667 .demod_address = 0x8,
668 .invert = 1,
669 .invert_oclk = 1,
670 .pll_init = philips_tu1216_pll_init,
671 .pll_set = philips_tu1216_pll_set,
672 .request_firmware = philips_tu1216_request_firmware,
673 };
674
675
676
677
678 static u8 read_pwm(struct budget_av *budget_av)
679 {
680 u8 b = 0xff;
681 u8 pwm;
682 struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
683 {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
684 };
685
686 if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
687 || (pwm == 0xff))
688 pwm = 0x48;
689
690 return pwm;
691 }
692
693
694 static void frontend_init(struct budget_av *budget_av)
695 {
696 switch (budget_av->budget.dev->pci->subsystem_device) {
697 case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059))
698 budget_av->budget.dvb_frontend =
699 stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap);
700 if (budget_av->budget.dvb_frontend != NULL) {
701 break;
702 }
703 break;
704
705 case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034))
706 budget_av->budget.dvb_frontend =
707 tda10021_attach(&philips_cu1216_config,
708 &budget_av->budget.i2c_adap, read_pwm(budget_av));
709 if (budget_av->budget.dvb_frontend != NULL) {
710 break;
711 }
712 break;
713
714 case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt))
715 budget_av->budget.dvb_frontend =
716 tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
717 if (budget_av->budget.dvb_frontend != NULL) {
718 break;
719 }
720 break;
721
722 case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059))
723 budget_av->budget.dvb_frontend =
724 stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap);
725 if (budget_av->budget.dvb_frontend != NULL) {
726 break;
727 }
728 break;
729
730 case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034))
731 budget_av->budget.dvb_frontend =
732 tda10021_attach(&philips_cu1216_config,
733 &budget_av->budget.i2c_adap, read_pwm(budget_av));
734 if (budget_av->budget.dvb_frontend) {
735 break;
736 }
737 break;
738
739 case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt))
740 budget_av->budget.dvb_frontend =
741 tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
742 if (budget_av->budget.dvb_frontend) {
743 break;
744 }
745 break;
746 }
747
748 if (budget_av->budget.dvb_frontend == NULL) {
749 printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
750 budget_av->budget.dev->pci->vendor,
751 budget_av->budget.dev->pci->device,
752 budget_av->budget.dev->pci->subsystem_vendor,
753 budget_av->budget.dev->pci->subsystem_device);
754 } else {
755 if (dvb_register_frontend
756 (budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) {
757 printk("budget-av: Frontend registration failed!\n");
758 if (budget_av->budget.dvb_frontend->ops->release)
759 budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
760 budget_av->budget.dvb_frontend = NULL;
761 }
762 }
763 }
764
765
766 static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
767 {
768 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
769
770 dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
771
772 if (*isr & MASK_10)
773 ttpci_budget_irq10_handler(dev, isr);
774 }
775
776 static int budget_av_detach (struct saa7146_dev *dev)
777 {
778 struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
779 int err;
780
781 dprintk(2, "dev: %p\n", dev);
782
783 if ( 1 == budget_av->has_saa7113 ) {
784 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
785
786 msleep(200);
787
788 saa7146_unregister_device (&budget_av->vd, dev);
789 }
790
791 if (budget_av->budget.ci_present)
792 ciintf_deinit(budget_av);
793
794 if (budget_av->budget.dvb_frontend != NULL)
795 dvb_unregister_frontend(budget_av->budget.dvb_frontend);
796 err = ttpci_budget_deinit (&budget_av->budget);
797
798 kfree (budget_av);
799
800 return err;
801 }
802
803 static struct saa7146_ext_vv vv_data;
804
805 static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
806 {
807 struct budget_av *budget_av;
808 u8 *mac;
809 int err;
810
811 dprintk(2, "dev: %p\n", dev);
812
813 if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
814 return -ENOMEM;
815
816 memset(budget_av, 0, sizeof(struct budget_av));
817
818 budget_av->budget.ci_present = 0;
819
820 dev->ext_priv = budget_av;
821
822 if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
823 kfree(budget_av);
824 return err;
825 }
826
827 /* knc1 initialization */
828 saa7146_write(dev, DD1_STREAM_B, 0x04000000);
829 saa7146_write(dev, DD1_INIT, 0x07000600);
830 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
831
832 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
833 msleep(500);
834
835 if ( 0 == saa7113_init(budget_av) ) {
836 budget_av->has_saa7113 = 1;
837
838 if ( 0 != saa7146_vv_init(dev,&vv_data)) {
839 /* fixme: proper cleanup here */
840 ERR(("cannot init vv subsystem.\n"));
841 return err;
842 }
843
844 if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
845 /* fixme: proper cleanup here */
846 ERR(("cannot register capture v4l2 device.\n"));
847 return err;
848 }
849
850 /* beware: this modifies dev->vv ... */
851 saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
852 SAA7146_HPS_SYNC_PORT_A);
853
854 saa7113_setinput (budget_av, 0);
855 } else {
856 budget_av->has_saa7113 = 0;
857
858 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
859 }
860
861 /* fixme: find some sane values here... */
862 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
863
864 mac = budget_av->budget.dvb_adapter->proposed_mac;
865 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
866 printk("KNC1-%d: Could not read MAC from KNC1 card\n",
867 budget_av->budget.dvb_adapter->num);
868 memset(mac, 0, 6);
869 } else {
870 printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
871 budget_av->budget.dvb_adapter->num,
872 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
873 }
874
875 budget_av->budget.dvb_adapter->priv = budget_av;
876 frontend_init(budget_av);
877
878 if (enable_ci)
879 ciintf_init(budget_av);
880
881 return 0;
882 }
883
884 #define KNC1_INPUTS 2
885 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
886 { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
887 { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
888 };
889
890
891 static struct saa7146_extension_ioctls ioctls[] = {
892 { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
893 { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
894 { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
895 { 0, 0 }
896 };
897
898
899 static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
900 {
901 struct saa7146_dev *dev = fh->dev;
902 struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
903
904 switch(cmd) {
905 case VIDIOC_ENUMINPUT:{
906 struct v4l2_input *i = arg;
907
908 dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
909 if( i->index < 0 || i->index >= KNC1_INPUTS) {
910 return -EINVAL;
911 }
912 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
913 return 0;
914 }
915 case VIDIOC_G_INPUT:{
916 int *input = (int *)arg;
917
918 *input = budget_av->cur_input;
919
920 dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
921 return 0;
922 }
923 case VIDIOC_S_INPUT:{
924 int input = *(int *)arg;
925 dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
926 return saa7113_setinput (budget_av, input);
927 }
928 default:
929 return -ENOIOCTLCMD;
930 }
931 return 0;
932 }
933
934 static struct saa7146_standard standard[] = {
935 {.name = "PAL",.id = V4L2_STD_PAL,
936 .v_offset = 0x17, .v_field = 288,
937 .h_offset = 0x14, .h_pixels = 680,
938 .v_max_out = 576,.h_max_out = 768 },
939
940 {.name = "NTSC",.id = V4L2_STD_NTSC,
941 .v_offset = 0x16, .v_field = 240,
942 .h_offset = 0x06, .h_pixels = 708,
943 .v_max_out = 480,.h_max_out = 640, },
944 };
945
946 static struct saa7146_ext_vv vv_data = {
947 .inputs = 2,
948 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
949 .flags = 0,
950 .stds = &standard[0],
951 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
952 .ioctls = &ioctls[0],
953 .ioctl = av_ioctl,
954 };
955
956 static struct saa7146_extension budget_extension;
957
958 MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
959 MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
960 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
961 MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
962 MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
963 MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
964
965 static struct pci_device_id pci_tbl [] = {
966 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
967 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
968 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
969 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
970 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
971 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
972 {
973 .vendor = 0,
974 }
975 };
976
977 MODULE_DEVICE_TABLE(pci, pci_tbl);
978
979 static struct saa7146_extension budget_extension = {
980 .name = "budget dvb /w video in\0",
981 .pci_tbl = pci_tbl,
982
983 .module = THIS_MODULE,
984 .attach = budget_av_attach,
985 .detach = budget_av_detach,
986
987 .irq_mask = MASK_10,
988 .irq_func = budget_av_irq,
989 };
990
991 static int __init budget_av_init(void)
992 {
993 return saa7146_register_extension(&budget_extension);
994 }
995
996 static void __exit budget_av_exit(void)
997 {
998 saa7146_unregister_extension(&budget_extension);
999 }
1000
1001 module_init(budget_av_init);
1002 module_exit(budget_av_exit);
1003
1004 MODULE_LICENSE("GPL");
1005 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1006 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1007 "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
1008 module_param_named(enable_ci, enable_ci, int, 0644);
1009 MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");
1010
|
This page was automatically generated by the
LXR engine.
|