[PATCH] dvb: bt8xx: whitespace cleanup
[deliverable/linux.git] / drivers / media / dvb / ttpci / budget-av.c
CommitLineData
1da177e4
LT
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;
fdc53a6d 300 if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
1da177e4
LT
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) {
2d4f2c2e
JS
704 case 0x0011: // KNC1 DVB-S Plus budget with AV IN (stv0299/Philips SU1278(tsa5059))
705 saa7146_write(budget_av->budget.dev, GPIO_CTRL, 0x50000000); // Enable / PowerON Frontend
1da177e4 706 case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059))
2d4f2c2e 707 case 0x0010: // KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059))
1da177e4
LT
708 budget_av->budget.dvb_frontend =
709 stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap);
710 if (budget_av->budget.dvb_frontend != NULL) {
711 break;
712 }
713 break;
714
2d4f2c2e
JS
715 case 0x0021: // KNC1 DVB-C Plus budget with AV IN (tda10021/Philips CU1216(tua6034))
716 saa7146_write(budget_av->budget.dev, GPIO_CTRL, 0x50000000); // Enable / PowerON Frontend
1da177e4
LT
717 case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034))
718 budget_av->budget.dvb_frontend =
719 tda10021_attach(&philips_cu1216_config,
720 &budget_av->budget.i2c_adap, read_pwm(budget_av));
721 if (budget_av->budget.dvb_frontend != NULL) {
722 break;
723 }
724 break;
725
2d4f2c2e
JS
726 case 0x0031: // KNC1 DVB-T Plus budget with AV IN (tda10046/Philips TU1216(tda6651tt))
727 saa7146_write(budget_av->budget.dev, GPIO_CTRL, 0x50000000); // Enable / PowerON Frontend
1da177e4
LT
728 case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt))
729 budget_av->budget.dvb_frontend =
730 tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
731 if (budget_av->budget.dvb_frontend != NULL) {
732 break;
733 }
734 break;
735
736 case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059))
737 budget_av->budget.dvb_frontend =
738 stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap);
739 if (budget_av->budget.dvb_frontend != NULL) {
740 break;
741 }
742 break;
743
744 case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034))
745 budget_av->budget.dvb_frontend =
746 tda10021_attach(&philips_cu1216_config,
747 &budget_av->budget.i2c_adap, read_pwm(budget_av));
748 if (budget_av->budget.dvb_frontend) {
749 break;
750 }
751 break;
752
753 case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt))
754 budget_av->budget.dvb_frontend =
755 tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
756 if (budget_av->budget.dvb_frontend) {
757 break;
758 }
759 break;
760 }
761
762 if (budget_av->budget.dvb_frontend == NULL) {
763 printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
764 budget_av->budget.dev->pci->vendor,
765 budget_av->budget.dev->pci->device,
766 budget_av->budget.dev->pci->subsystem_vendor,
767 budget_av->budget.dev->pci->subsystem_device);
768 } else {
769 if (dvb_register_frontend
fdc53a6d 770 (&budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) {
1da177e4
LT
771 printk("budget-av: Frontend registration failed!\n");
772 if (budget_av->budget.dvb_frontend->ops->release)
773 budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
774 budget_av->budget.dvb_frontend = NULL;
775 }
776 }
777}
778
779
780static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
781{
782 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
783
784 dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
785
786 if (*isr & MASK_10)
787 ttpci_budget_irq10_handler(dev, isr);
788}
789
790static int budget_av_detach(struct saa7146_dev *dev)
791{
792 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
793 int err;
794
795 dprintk(2, "dev: %p\n", dev);
796
797 if (1 == budget_av->has_saa7113) {
798 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
799
800 msleep(200);
801
802 saa7146_unregister_device(&budget_av->vd, dev);
803 }
804
805 if (budget_av->budget.ci_present)
806 ciintf_deinit(budget_av);
807
808 if (budget_av->budget.dvb_frontend != NULL)
809 dvb_unregister_frontend(budget_av->budget.dvb_frontend);
810 err = ttpci_budget_deinit(&budget_av->budget);
811
812 kfree(budget_av);
813
814 return err;
815}
816
817static struct saa7146_ext_vv vv_data;
818
819static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
820{
821 struct budget_av *budget_av;
822 u8 *mac;
823 int err;
824
825 dprintk(2, "dev: %p\n", dev);
826
827 if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
828 return -ENOMEM;
829
830 memset(budget_av, 0, sizeof(struct budget_av));
831
832 budget_av->budget.ci_present = 0;
833
834 dev->ext_priv = budget_av;
835
836 if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
837 kfree(budget_av);
838 return err;
839 }
840
841 /* knc1 initialization */
842 saa7146_write(dev, DD1_STREAM_B, 0x04000000);
843 saa7146_write(dev, DD1_INIT, 0x07000600);
844 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
845
846 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
847 msleep(500);
848
849 if (0 == saa7113_init(budget_av)) {
850 budget_av->has_saa7113 = 1;
851
852 if (0 != saa7146_vv_init(dev, &vv_data)) {
853 /* fixme: proper cleanup here */
854 ERR(("cannot init vv subsystem.\n"));
855 return err;
856 }
857
858 if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
859 /* fixme: proper cleanup here */
860 ERR(("cannot register capture v4l2 device.\n"));
861 return err;
862 }
863
864 /* beware: this modifies dev->vv ... */
865 saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
866 SAA7146_HPS_SYNC_PORT_A);
867
868 saa7113_setinput(budget_av, 0);
869 } else {
870 budget_av->has_saa7113 = 0;
871
872 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
873 }
874
875 /* fixme: find some sane values here... */
876 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
877
fdc53a6d 878 mac = budget_av->budget.dvb_adapter.proposed_mac;
1da177e4
LT
879 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
880 printk("KNC1-%d: Could not read MAC from KNC1 card\n",
fdc53a6d 881 budget_av->budget.dvb_adapter.num);
1da177e4
LT
882 memset(mac, 0, 6);
883 } else {
884 printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
fdc53a6d 885 budget_av->budget.dvb_adapter.num,
1da177e4
LT
886 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
887 }
888
fdc53a6d 889 budget_av->budget.dvb_adapter.priv = budget_av;
1da177e4
LT
890 frontend_init(budget_av);
891
892 if (enable_ci)
893 ciintf_init(budget_av);
894
895 return 0;
896}
897
898#define KNC1_INPUTS 2
899static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
900 {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
901 {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
902};
903
904static struct saa7146_extension_ioctls ioctls[] = {
905 {VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
906 {VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
907 {VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
908 {0, 0}
909};
910
911static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
912{
913 struct saa7146_dev *dev = fh->dev;
914 struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
915
916 switch (cmd) {
917 case VIDIOC_ENUMINPUT:{
918 struct v4l2_input *i = arg;
919
920 dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
921 if (i->index < 0 || i->index >= KNC1_INPUTS) {
922 return -EINVAL;
923 }
924 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
925 return 0;
926 }
927 case VIDIOC_G_INPUT:{
928 int *input = (int *) arg;
929
930 *input = budget_av->cur_input;
931
932 dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
933 return 0;
934 }
935 case VIDIOC_S_INPUT:{
936 int input = *(int *) arg;
937 dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
938 return saa7113_setinput(budget_av, input);
939 }
940 default:
941 return -ENOIOCTLCMD;
942 }
943 return 0;
944}
945
946static struct saa7146_standard standard[] = {
947 {.name = "PAL",.id = V4L2_STD_PAL,
948 .v_offset = 0x17,.v_field = 288,
949 .h_offset = 0x14,.h_pixels = 680,
950 .v_max_out = 576,.h_max_out = 768 },
951
952 {.name = "NTSC",.id = V4L2_STD_NTSC,
953 .v_offset = 0x16,.v_field = 240,
954 .h_offset = 0x06,.h_pixels = 708,
955 .v_max_out = 480,.h_max_out = 640, },
956};
957
958static struct saa7146_ext_vv vv_data = {
959 .inputs = 2,
960 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
961 .flags = 0,
962 .stds = &standard[0],
963 .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
964 .ioctls = &ioctls[0],
965 .ioctl = av_ioctl,
966};
967
968static struct saa7146_extension budget_extension;
969
970MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
971MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
972MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
2d4f2c2e
JS
973MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
974MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
975MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
1da177e4
LT
976MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
977MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
978MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
979
980static struct pci_device_id pci_tbl[] = {
981 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
2d4f2c2e
JS
982 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
983 MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
1da177e4 984 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
2d4f2c2e 985 MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
1da177e4 986 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
2d4f2c2e 987 MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
1da177e4
LT
988 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
989 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
990 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
991 {
992 .vendor = 0,
993 }
994};
995
996MODULE_DEVICE_TABLE(pci, pci_tbl);
997
998static struct saa7146_extension budget_extension = {
999 .name = "budget dvb /w video in\0",
1000 .pci_tbl = pci_tbl,
1001
1002 .module = THIS_MODULE,
1003 .attach = budget_av_attach,
1004 .detach = budget_av_detach,
1005
1006 .irq_mask = MASK_10,
1007 .irq_func = budget_av_irq,
1008};
1009
1010static int __init budget_av_init(void)
1011{
1012 return saa7146_register_extension(&budget_extension);
1013}
1014
1015static void __exit budget_av_exit(void)
1016{
1017 saa7146_unregister_extension(&budget_extension);
1018}
1019
1020module_init(budget_av_init);
1021module_exit(budget_av_exit);
1022
1023MODULE_LICENSE("GPL");
1024MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1025MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
1026 "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
1027module_param_named(enable_ci, enable_ci, int, 0644);
1028MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");
This page took 0.098768 seconds and 5 git commands to generate.