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