1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * budget-av.ko: driver for the SAA7146 based Budget DVB cards
4 * with analog video input (and optionally with CI)
5 *
6 * Compiled from various sources by Michael Hunold <michael@mihu.de>
7 *
8 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
9 * Andrew de Quincey <adq_dvb@lidskialf.net>
10 *
11 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
12 *
13 * Copyright (C) 1999-2002 Ralph Metzler
14 * & Marcus Metzler for convergence integrated media GmbH
15 *
16 * the project's page is at https://linuxtv.org
17 */
18
19
20 #include "budget.h"
21 #include "stv0299.h"
22 #include "stb0899_drv.h"
23 #include "stb0899_reg.h"
24 #include "stb0899_cfg.h"
25 #include "tda8261.h"
26 #include "tda8261_cfg.h"
27 #include "tda1002x.h"
28 #include "tda1004x.h"
29 #include "tua6100.h"
30 #include "dvb-pll.h"
31 #include <media/drv-intf/saa7146_vv.h>
32 #include <linux/module.h>
33 #include <linux/etherdevice.h>
34 #include <linux/errno.h>
35 #include <linux/slab.h>
36 #include <linux/interrupt.h>
37 #include <linux/input.h>
38 #include <linux/spinlock.h>
39 #include <linux/workqueue.h>
40
41 #include <media/dvb_ca_en50221.h>
42
43 #define DEBICICAM 0x02420000
44
45 #define SLOTSTATUS_NONE 1
46 #define SLOTSTATUS_PRESENT 2
47 #define SLOTSTATUS_RESET 4
48 #define SLOTSTATUS_READY 8
49 #define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
50
51 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
52
53 struct budget_av {
54 struct budget budget;
55 struct video_device vd;
56 int cur_input;
57 int has_saa7113;
58 struct work_struct ciintf_irq_bh_work;
59 int slot_status;
60 struct dvb_ca_en50221 ca;
61 u8 reinitialise_demod:1;
62 };
63
64 static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
65
66 /*
67 * GPIO Connections:
68 * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
69 * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
70 * 2 - CI Card Enable (Active Low)
71 * 3 - CI Card Detect
72 */
73
74 /****************************************************************************
75 * INITIALIZATION
76 ****************************************************************************/
77
i2c_readreg(struct i2c_adapter * i2c,u8 id,u8 reg)78 static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
79 {
80 u8 mm1[] = { 0x00 };
81 u8 mm2[] = { 0x00 };
82 struct i2c_msg msgs[2];
83
84 msgs[0].flags = 0;
85 msgs[1].flags = I2C_M_RD;
86 msgs[0].addr = msgs[1].addr = id / 2;
87 mm1[0] = reg;
88 msgs[0].len = 1;
89 msgs[1].len = 1;
90 msgs[0].buf = mm1;
91 msgs[1].buf = mm2;
92
93 i2c_transfer(i2c, msgs, 2);
94
95 return mm2[0];
96 }
97
i2c_readregs(struct i2c_adapter * i2c,u8 id,u8 reg,u8 * buf,u8 len)98 static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 *buf, u8 len)
99 {
100 u8 mm1[] = { reg };
101 struct i2c_msg msgs[2] = {
102 {.addr = id / 2, .flags = 0, .buf = mm1, .len = 1},
103 {.addr = id / 2, .flags = I2C_M_RD, .buf = buf, .len = len}
104 };
105
106 if (i2c_transfer(i2c, msgs, 2) != 2)
107 return -EIO;
108
109 return 0;
110 }
111
i2c_writereg(struct i2c_adapter * i2c,u8 id,u8 reg,u8 val)112 static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
113 {
114 u8 msg[2] = { reg, val };
115 struct i2c_msg msgs;
116
117 msgs.flags = 0;
118 msgs.addr = id / 2;
119 msgs.len = 2;
120 msgs.buf = msg;
121 return i2c_transfer(i2c, &msgs, 1);
122 }
123
ciintf_read_attribute_mem(struct dvb_ca_en50221 * ca,int slot,int address)124 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
125 {
126 struct budget_av *budget_av = ca->data;
127 int result;
128
129 if (slot != 0)
130 return -EINVAL;
131
132 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
133 udelay(1);
134
135 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
136 if (result == -ETIMEDOUT) {
137 ciintf_slot_shutdown(ca, slot);
138 pr_info("cam ejected 1\n");
139 }
140 return result;
141 }
142
ciintf_write_attribute_mem(struct dvb_ca_en50221 * ca,int slot,int address,u8 value)143 static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
144 {
145 struct budget_av *budget_av = ca->data;
146 int result;
147
148 if (slot != 0)
149 return -EINVAL;
150
151 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
152 udelay(1);
153
154 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
155 if (result == -ETIMEDOUT) {
156 ciintf_slot_shutdown(ca, slot);
157 pr_info("cam ejected 2\n");
158 }
159 return result;
160 }
161
ciintf_read_cam_control(struct dvb_ca_en50221 * ca,int slot,u8 address)162 static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
163 {
164 struct budget_av *budget_av = ca->data;
165 int result;
166
167 if (slot != 0)
168 return -EINVAL;
169
170 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
171 udelay(1);
172
173 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
174 if (result == -ETIMEDOUT) {
175 ciintf_slot_shutdown(ca, slot);
176 pr_info("cam ejected 3\n");
177 return -ETIMEDOUT;
178 }
179 return result;
180 }
181
ciintf_write_cam_control(struct dvb_ca_en50221 * ca,int slot,u8 address,u8 value)182 static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
183 {
184 struct budget_av *budget_av = ca->data;
185 int result;
186
187 if (slot != 0)
188 return -EINVAL;
189
190 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
191 udelay(1);
192
193 result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
194 if (result == -ETIMEDOUT) {
195 ciintf_slot_shutdown(ca, slot);
196 pr_info("cam ejected 5\n");
197 }
198 return result;
199 }
200
ciintf_slot_reset(struct dvb_ca_en50221 * ca,int slot)201 static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
202 {
203 struct budget_av *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, "ci slot reset\n");
210 budget_av->slot_status = SLOTSTATUS_RESET;
211
212 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
213
214 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
215 msleep(2);
216 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
217 msleep(20); /* 20 ms Vcc settling time */
218
219 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
220 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
221 msleep(20);
222
223 /* reinitialise the frontend if necessary */
224 if (budget_av->reinitialise_demod)
225 dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
226
227 return 0;
228 }
229
ciintf_slot_shutdown(struct dvb_ca_en50221 * ca,int slot)230 static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
231 {
232 struct budget_av *budget_av = ca->data;
233 struct saa7146_dev *saa = budget_av->budget.dev;
234
235 if (slot != 0)
236 return -EINVAL;
237
238 dprintk(1, "ci slot shutdown\n");
239
240 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
241 budget_av->slot_status = SLOTSTATUS_NONE;
242
243 return 0;
244 }
245
ciintf_slot_ts_enable(struct dvb_ca_en50221 * ca,int slot)246 static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
247 {
248 struct budget_av *budget_av = ca->data;
249 struct saa7146_dev *saa = budget_av->budget.dev;
250
251 if (slot != 0)
252 return -EINVAL;
253
254 dprintk(1, "ci slot status: %d\n", budget_av->slot_status);
255
256 ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
257
258 return 0;
259 }
260
ciintf_poll_slot_status(struct dvb_ca_en50221 * ca,int slot,int open)261 static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
262 {
263 struct budget_av *budget_av = ca->data;
264 struct saa7146_dev *saa = budget_av->budget.dev;
265 int result;
266
267 if (slot != 0)
268 return -EINVAL;
269
270 /*
271 * test the card detect line - needs to be done carefully
272 * since it never goes high for some CAMs on this interface (e.g. topuptv)
273 */
274 if (budget_av->slot_status == SLOTSTATUS_NONE) {
275 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
276 udelay(1);
277 if (saa7146_read(saa, PSR) & MASK_06) {
278 if (budget_av->slot_status == SLOTSTATUS_NONE) {
279 budget_av->slot_status = SLOTSTATUS_PRESENT;
280 pr_info("cam inserted A\n");
281 }
282 }
283 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
284 }
285
286 /*
287 * We also try and read from IO memory to work round the above detection bug. If
288 * there is no CAM, we will get a timeout. Only done if there is no cam
289 * present, since this test actually breaks some cams :(
290 *
291 * if the CI interface is not open, we also do the above test since we
292 * don't care if the cam has problems - we'll be resetting it on open() anyway
293 */
294 if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
295 saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
296 result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
297 if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
298 budget_av->slot_status = SLOTSTATUS_PRESENT;
299 pr_info("cam inserted B\n");
300 } else if (result < 0) {
301 if (budget_av->slot_status != SLOTSTATUS_NONE) {
302 ciintf_slot_shutdown(ca, slot);
303 pr_info("cam ejected 5\n");
304 return 0;
305 }
306 }
307 }
308
309 /* read from attribute memory in reset/ready state to know when the CAM is ready */
310 if (budget_av->slot_status == SLOTSTATUS_RESET) {
311 result = ciintf_read_attribute_mem(ca, slot, 0);
312 if (result == 0x1d)
313 budget_av->slot_status = SLOTSTATUS_READY;
314 }
315
316 /* work out correct return code */
317 if (budget_av->slot_status != SLOTSTATUS_NONE) {
318 if (budget_av->slot_status & SLOTSTATUS_READY)
319 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
320 return DVB_CA_EN50221_POLL_CAM_PRESENT;
321 }
322 return 0;
323 }
324
ciintf_init(struct budget_av * budget_av)325 static int ciintf_init(struct budget_av *budget_av)
326 {
327 struct saa7146_dev *saa = budget_av->budget.dev;
328 int result;
329
330 memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
331
332 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
333 saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
334 saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
335 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
336
337 /* Enable DEBI pins */
338 saa7146_write(saa, MC1, MASK_27 | MASK_11);
339
340 /* register CI interface */
341 budget_av->ca.owner = THIS_MODULE;
342 budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
343 budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
344 budget_av->ca.read_cam_control = ciintf_read_cam_control;
345 budget_av->ca.write_cam_control = ciintf_write_cam_control;
346 budget_av->ca.slot_reset = ciintf_slot_reset;
347 budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
348 budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
349 budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
350 budget_av->ca.data = budget_av;
351 budget_av->budget.ci_present = 1;
352 budget_av->slot_status = SLOTSTATUS_NONE;
353
354 result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
355 &budget_av->ca, 0, 1);
356 if (result != 0) {
357 pr_err("ci initialisation failed\n");
358 goto error;
359 }
360
361 pr_info("ci interface initialised\n");
362 return 0;
363
364 error:
365 saa7146_write(saa, MC1, MASK_27);
366 return result;
367 }
368
ciintf_deinit(struct budget_av * budget_av)369 static void ciintf_deinit(struct budget_av *budget_av)
370 {
371 struct saa7146_dev *saa = budget_av->budget.dev;
372
373 saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
374 saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
375 saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
376 saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
377
378 /* release the CA device */
379 dvb_ca_en50221_release(&budget_av->ca);
380
381 /* disable DEBI pins */
382 saa7146_write(saa, MC1, MASK_27);
383 }
384
385
386 static const u8 saa7113_tab[] = {
387 0x01, 0x08,
388 0x02, 0xc0,
389 0x03, 0x33,
390 0x04, 0x00,
391 0x05, 0x00,
392 0x06, 0xeb,
393 0x07, 0xe0,
394 0x08, 0x28,
395 0x09, 0x00,
396 0x0a, 0x80,
397 0x0b, 0x47,
398 0x0c, 0x40,
399 0x0d, 0x00,
400 0x0e, 0x01,
401 0x0f, 0x44,
402
403 0x10, 0x08,
404 0x11, 0x0c,
405 0x12, 0x7b,
406 0x13, 0x00,
407 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
408
409 0x57, 0xff,
410 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
411 0x5b, 0x83, 0x5e, 0x00,
412 0xff
413 };
414
saa7113_init(struct budget_av * budget_av)415 static int saa7113_init(struct budget_av *budget_av)
416 {
417 struct budget *budget = &budget_av->budget;
418 struct saa7146_dev *saa = budget->dev;
419 const u8 *data = saa7113_tab;
420
421 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
422 msleep(200);
423
424 if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
425 dprintk(1, "saa7113 not found on KNC card\n");
426 return -ENODEV;
427 }
428
429 dprintk(1, "saa7113 detected and initializing\n");
430
431 while (*data != 0xff) {
432 i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
433 data += 2;
434 }
435
436 dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
437
438 return 0;
439 }
440
saa7113_setinput(struct budget_av * budget_av,int input)441 static int saa7113_setinput(struct budget_av *budget_av, int input)
442 {
443 struct budget *budget = &budget_av->budget;
444
445 if (budget_av->has_saa7113 != 1)
446 return -ENODEV;
447
448 if (input == 1) {
449 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
450 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
451 } else if (input == 0) {
452 i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
453 i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
454 } else {
455 return -EINVAL;
456 }
457
458 budget_av->cur_input = input;
459 return 0;
460 }
461
462
philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend * fe,u32 srate,u32 ratio)463 static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
464 {
465 u8 aclk = 0;
466 u8 bclk = 0;
467 u8 m1;
468
469 aclk = 0xb5;
470 if (srate < 2000000)
471 bclk = 0x86;
472 else if (srate < 5000000)
473 bclk = 0x89;
474 else if (srate < 15000000)
475 bclk = 0x8f;
476 else if (srate < 45000000)
477 bclk = 0x95;
478
479 m1 = 0x14;
480 if (srate < 4000000)
481 m1 = 0x10;
482
483 stv0299_writereg(fe, 0x13, aclk);
484 stv0299_writereg(fe, 0x14, bclk);
485 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
486 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
487 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
488 stv0299_writereg(fe, 0x0f, 0x80 | m1);
489
490 return 0;
491 }
492
philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend * fe)493 static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)
494 {
495 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
496 u32 div;
497 u8 buf[4];
498 struct budget *budget = fe->dvb->priv;
499 struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
500
501 if ((c->frequency < 950000) || (c->frequency > 2150000))
502 return -EINVAL;
503
504 div = (c->frequency + (125 - 1)) / 125; /* round correctly */
505 buf[0] = (div >> 8) & 0x7f;
506 buf[1] = div & 0xff;
507 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
508 buf[3] = 0x20;
509
510 if (c->symbol_rate < 4000000)
511 buf[3] |= 1;
512
513 if (c->frequency < 1250000)
514 buf[3] |= 0;
515 else if (c->frequency < 1550000)
516 buf[3] |= 0x40;
517 else if (c->frequency < 2050000)
518 buf[3] |= 0x80;
519 else if (c->frequency < 2150000)
520 buf[3] |= 0xC0;
521
522 if (fe->ops.i2c_gate_ctrl)
523 fe->ops.i2c_gate_ctrl(fe, 1);
524 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
525 return -EIO;
526 return 0;
527 }
528
529 static u8 typhoon_cinergy1200s_inittab[] = {
530 0x01, 0x15,
531 0x02, 0x30,
532 0x03, 0x00,
533 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
534 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
535 0x06, 0x40, /* DAC not used, set to high impendance mode */
536 0x07, 0x00, /* DAC LSB */
537 0x08, 0x40, /* DiSEqC off */
538 0x09, 0x00, /* FIFO */
539 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
540 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
541 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
542 0x10, 0x3f, // AGC2 0x3d
543 0x11, 0x84,
544 0x12, 0xb9,
545 0x15, 0xc9, // lock detector threshold
546 0x16, 0x00,
547 0x17, 0x00,
548 0x18, 0x00,
549 0x19, 0x00,
550 0x1a, 0x00,
551 0x1f, 0x50,
552 0x20, 0x00,
553 0x21, 0x00,
554 0x22, 0x00,
555 0x23, 0x00,
556 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
557 0x29, 0x1e, // 1/2 threshold
558 0x2a, 0x14, // 2/3 threshold
559 0x2b, 0x0f, // 3/4 threshold
560 0x2c, 0x09, // 5/6 threshold
561 0x2d, 0x05, // 7/8 threshold
562 0x2e, 0x01,
563 0x31, 0x1f, // test all FECs
564 0x32, 0x19, // viterbi and synchro search
565 0x33, 0xfc, // rs control
566 0x34, 0x93, // error control
567 0x0f, 0x92,
568 0xff, 0xff
569 };
570
571 static const struct stv0299_config typhoon_config = {
572 .demod_address = 0x68,
573 .inittab = typhoon_cinergy1200s_inittab,
574 .mclk = 88000000UL,
575 .invert = 0,
576 .skip_reinit = 0,
577 .lock_output = STV0299_LOCKOUTPUT_1,
578 .volt13_op0_op1 = STV0299_VOLT13_OP0,
579 .min_delay_ms = 100,
580 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
581 };
582
583
584 static const struct stv0299_config cinergy_1200s_config = {
585 .demod_address = 0x68,
586 .inittab = typhoon_cinergy1200s_inittab,
587 .mclk = 88000000UL,
588 .invert = 0,
589 .skip_reinit = 0,
590 .lock_output = STV0299_LOCKOUTPUT_0,
591 .volt13_op0_op1 = STV0299_VOLT13_OP0,
592 .min_delay_ms = 100,
593 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
594 };
595
596 static const struct stv0299_config cinergy_1200s_1894_0010_config = {
597 .demod_address = 0x68,
598 .inittab = typhoon_cinergy1200s_inittab,
599 .mclk = 88000000UL,
600 .invert = 1,
601 .skip_reinit = 0,
602 .lock_output = STV0299_LOCKOUTPUT_1,
603 .volt13_op0_op1 = STV0299_VOLT13_OP0,
604 .min_delay_ms = 100,
605 .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
606 };
607
philips_cu1216_tuner_set_params(struct dvb_frontend * fe)608 static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)
609 {
610 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
611 struct budget *budget = fe->dvb->priv;
612 u8 buf[6];
613 struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };
614 int i;
615
616 #define CU1216_IF 36125000
617 #define TUNER_MUL 62500
618
619 u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
620
621 buf[0] = (div >> 8) & 0x7f;
622 buf[1] = div & 0xff;
623 buf[2] = 0xce;
624 buf[3] = (c->frequency < 150000000 ? 0x01 :
625 c->frequency < 445000000 ? 0x02 : 0x04);
626 buf[4] = 0xde;
627 buf[5] = 0x20;
628
629 if (fe->ops.i2c_gate_ctrl)
630 fe->ops.i2c_gate_ctrl(fe, 1);
631 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
632 return -EIO;
633
634 /* wait for the pll lock */
635 msg.flags = I2C_M_RD;
636 msg.len = 1;
637 for (i = 0; i < 20; i++) {
638 if (fe->ops.i2c_gate_ctrl)
639 fe->ops.i2c_gate_ctrl(fe, 1);
640 if (i2c_transfer(&budget->i2c_adap, &msg, 1) == 1 && (buf[0] & 0x40))
641 break;
642 msleep(10);
643 }
644
645 /* switch the charge pump to the lower current */
646 msg.flags = 0;
647 msg.len = 2;
648 msg.buf = &buf[2];
649 buf[2] &= ~0x40;
650 if (fe->ops.i2c_gate_ctrl)
651 fe->ops.i2c_gate_ctrl(fe, 1);
652 if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
653 return -EIO;
654
655 return 0;
656 }
657
658 static struct tda1002x_config philips_cu1216_config = {
659 .demod_address = 0x0c,
660 .invert = 1,
661 };
662
663 static struct tda1002x_config philips_cu1216_config_altaddress = {
664 .demod_address = 0x0d,
665 .invert = 0,
666 };
667
668 static struct tda10023_config philips_cu1216_tda10023_config = {
669 .demod_address = 0x0c,
670 .invert = 1,
671 };
672
philips_tu1216_tuner_init(struct dvb_frontend * fe)673 static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
674 {
675 struct budget *budget = fe->dvb->priv;
676 static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
677 struct i2c_msg tuner_msg = {.addr = 0x60, .flags = 0, .buf = tu1216_init, .len = sizeof(tu1216_init) };
678
679 // setup PLL configuration
680 if (fe->ops.i2c_gate_ctrl)
681 fe->ops.i2c_gate_ctrl(fe, 1);
682 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
683 return -EIO;
684 msleep(1);
685
686 return 0;
687 }
688
philips_tu1216_tuner_set_params(struct dvb_frontend * fe)689 static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)
690 {
691 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
692 struct budget *budget = fe->dvb->priv;
693 u8 tuner_buf[4];
694 struct i2c_msg tuner_msg = {.addr = 0x60, .flags = 0, .buf = tuner_buf, .len =
695 sizeof(tuner_buf) };
696 int tuner_frequency = 0;
697 u8 band, cp, filter;
698
699 // determine charge pump
700 tuner_frequency = c->frequency + 36166000;
701 if (tuner_frequency < 87000000)
702 return -EINVAL;
703 else if (tuner_frequency < 130000000)
704 cp = 3;
705 else if (tuner_frequency < 160000000)
706 cp = 5;
707 else if (tuner_frequency < 200000000)
708 cp = 6;
709 else if (tuner_frequency < 290000000)
710 cp = 3;
711 else if (tuner_frequency < 420000000)
712 cp = 5;
713 else if (tuner_frequency < 480000000)
714 cp = 6;
715 else if (tuner_frequency < 620000000)
716 cp = 3;
717 else if (tuner_frequency < 830000000)
718 cp = 5;
719 else if (tuner_frequency < 895000000)
720 cp = 7;
721 else
722 return -EINVAL;
723
724 // determine band
725 if (c->frequency < 49000000)
726 return -EINVAL;
727 else if (c->frequency < 161000000)
728 band = 1;
729 else if (c->frequency < 444000000)
730 band = 2;
731 else if (c->frequency < 861000000)
732 band = 4;
733 else
734 return -EINVAL;
735
736 // setup PLL filter
737 switch (c->bandwidth_hz) {
738 case 6000000:
739 filter = 0;
740 break;
741
742 case 7000000:
743 filter = 0;
744 break;
745
746 case 8000000:
747 filter = 1;
748 break;
749
750 default:
751 return -EINVAL;
752 }
753
754 // calculate divisor
755 // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
756 tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
757
758 // setup tuner buffer
759 tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
760 tuner_buf[1] = tuner_frequency & 0xff;
761 tuner_buf[2] = 0xca;
762 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
763
764 if (fe->ops.i2c_gate_ctrl)
765 fe->ops.i2c_gate_ctrl(fe, 1);
766 if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
767 return -EIO;
768
769 msleep(1);
770 return 0;
771 }
772
philips_tu1216_request_firmware(struct dvb_frontend * fe,const struct firmware ** fw,char * name)773 static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
774 const struct firmware **fw, char *name)
775 {
776 struct budget *budget = fe->dvb->priv;
777
778 return request_firmware(fw, name, &budget->dev->pci->dev);
779 }
780
781 static struct tda1004x_config philips_tu1216_config = {
782
783 .demod_address = 0x8,
784 .invert = 1,
785 .invert_oclk = 1,
786 .xtal_freq = TDA10046_XTAL_4M,
787 .agc_config = TDA10046_AGC_DEFAULT,
788 .if_freq = TDA10046_FREQ_3617,
789 .request_firmware = philips_tu1216_request_firmware,
790 };
791
792 static u8 philips_sd1878_inittab[] = {
793 0x01, 0x15,
794 0x02, 0x30,
795 0x03, 0x00,
796 0x04, 0x7d,
797 0x05, 0x35,
798 0x06, 0x40,
799 0x07, 0x00,
800 0x08, 0x43,
801 0x09, 0x02,
802 0x0C, 0x51,
803 0x0D, 0x82,
804 0x0E, 0x23,
805 0x10, 0x3f,
806 0x11, 0x84,
807 0x12, 0xb9,
808 0x15, 0xc9,
809 0x16, 0x19,
810 0x17, 0x8c,
811 0x18, 0x59,
812 0x19, 0xf8,
813 0x1a, 0xfe,
814 0x1c, 0x7f,
815 0x1d, 0x00,
816 0x1e, 0x00,
817 0x1f, 0x50,
818 0x20, 0x00,
819 0x21, 0x00,
820 0x22, 0x00,
821 0x23, 0x00,
822 0x28, 0x00,
823 0x29, 0x28,
824 0x2a, 0x14,
825 0x2b, 0x0f,
826 0x2c, 0x09,
827 0x2d, 0x09,
828 0x31, 0x1f,
829 0x32, 0x19,
830 0x33, 0xfc,
831 0x34, 0x93,
832 0xff, 0xff
833 };
834
philips_sd1878_ci_set_symbol_rate(struct dvb_frontend * fe,u32 srate,u32 ratio)835 static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
836 u32 srate, u32 ratio)
837 {
838 u8 aclk = 0;
839 u8 bclk = 0;
840 u8 m1;
841
842 aclk = 0xb5;
843 if (srate < 2000000)
844 bclk = 0x86;
845 else if (srate < 5000000)
846 bclk = 0x89;
847 else if (srate < 15000000)
848 bclk = 0x8f;
849 else if (srate < 45000000)
850 bclk = 0x95;
851
852 m1 = 0x14;
853 if (srate < 4000000)
854 m1 = 0x10;
855
856 stv0299_writereg(fe, 0x0e, 0x23);
857 stv0299_writereg(fe, 0x0f, 0x94);
858 stv0299_writereg(fe, 0x10, 0x39);
859 stv0299_writereg(fe, 0x13, aclk);
860 stv0299_writereg(fe, 0x14, bclk);
861 stv0299_writereg(fe, 0x15, 0xc9);
862 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
863 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
864 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
865 stv0299_writereg(fe, 0x0f, 0x80 | m1);
866
867 return 0;
868 }
869
870 static const struct stv0299_config philips_sd1878_config = {
871 .demod_address = 0x68,
872 .inittab = philips_sd1878_inittab,
873 .mclk = 88000000UL,
874 .invert = 0,
875 .skip_reinit = 0,
876 .lock_output = STV0299_LOCKOUTPUT_1,
877 .volt13_op0_op1 = STV0299_VOLT13_OP0,
878 .min_delay_ms = 100,
879 .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
880 };
881
882 /* KNC1 DVB-S (STB0899) Inittab */
883 static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
884
885 { STB0899_DEV_ID, 0x81 },
886 { STB0899_DISCNTRL1, 0x32 },
887 { STB0899_DISCNTRL2, 0x80 },
888 { STB0899_DISRX_ST0, 0x04 },
889 { STB0899_DISRX_ST1, 0x00 },
890 { STB0899_DISPARITY, 0x00 },
891 { STB0899_DISSTATUS, 0x20 },
892 { STB0899_DISF22, 0x8c },
893 { STB0899_DISF22RX, 0x9a },
894 { STB0899_SYSREG, 0x0b },
895 { STB0899_ACRPRESC, 0x11 },
896 { STB0899_ACRDIV1, 0x0a },
897 { STB0899_ACRDIV2, 0x05 },
898 { STB0899_DACR1, 0x00 },
899 { STB0899_DACR2, 0x00 },
900 { STB0899_OUTCFG, 0x00 },
901 { STB0899_MODECFG, 0x00 },
902 { STB0899_IRQSTATUS_3, 0x30 },
903 { STB0899_IRQSTATUS_2, 0x00 },
904 { STB0899_IRQSTATUS_1, 0x00 },
905 { STB0899_IRQSTATUS_0, 0x00 },
906 { STB0899_IRQMSK_3, 0xf3 },
907 { STB0899_IRQMSK_2, 0xfc },
908 { STB0899_IRQMSK_1, 0xff },
909 { STB0899_IRQMSK_0, 0xff },
910 { STB0899_IRQCFG, 0x00 },
911 { STB0899_I2CCFG, 0x88 },
912 { STB0899_I2CRPT, 0x58 }, /* Repeater=8, Stop=disabled */
913 { STB0899_IOPVALUE5, 0x00 },
914 { STB0899_IOPVALUE4, 0x20 },
915 { STB0899_IOPVALUE3, 0xc9 },
916 { STB0899_IOPVALUE2, 0x90 },
917 { STB0899_IOPVALUE1, 0x40 },
918 { STB0899_IOPVALUE0, 0x00 },
919 { STB0899_GPIO00CFG, 0x82 },
920 { STB0899_GPIO01CFG, 0x82 },
921 { STB0899_GPIO02CFG, 0x82 },
922 { STB0899_GPIO03CFG, 0x82 },
923 { STB0899_GPIO04CFG, 0x82 },
924 { STB0899_GPIO05CFG, 0x82 },
925 { STB0899_GPIO06CFG, 0x82 },
926 { STB0899_GPIO07CFG, 0x82 },
927 { STB0899_GPIO08CFG, 0x82 },
928 { STB0899_GPIO09CFG, 0x82 },
929 { STB0899_GPIO10CFG, 0x82 },
930 { STB0899_GPIO11CFG, 0x82 },
931 { STB0899_GPIO12CFG, 0x82 },
932 { STB0899_GPIO13CFG, 0x82 },
933 { STB0899_GPIO14CFG, 0x82 },
934 { STB0899_GPIO15CFG, 0x82 },
935 { STB0899_GPIO16CFG, 0x82 },
936 { STB0899_GPIO17CFG, 0x82 },
937 { STB0899_GPIO18CFG, 0x82 },
938 { STB0899_GPIO19CFG, 0x82 },
939 { STB0899_GPIO20CFG, 0x82 },
940 { STB0899_SDATCFG, 0xb8 },
941 { STB0899_SCLTCFG, 0xba },
942 { STB0899_AGCRFCFG, 0x08 }, /* 0x1c */
943 { STB0899_GPIO22, 0x82 }, /* AGCBB2CFG */
944 { STB0899_GPIO21, 0x91 }, /* AGCBB1CFG */
945 { STB0899_DIRCLKCFG, 0x82 },
946 { STB0899_CLKOUT27CFG, 0x7e },
947 { STB0899_STDBYCFG, 0x82 },
948 { STB0899_CS0CFG, 0x82 },
949 { STB0899_CS1CFG, 0x82 },
950 { STB0899_DISEQCOCFG, 0x20 },
951 { STB0899_GPIO32CFG, 0x82 },
952 { STB0899_GPIO33CFG, 0x82 },
953 { STB0899_GPIO34CFG, 0x82 },
954 { STB0899_GPIO35CFG, 0x82 },
955 { STB0899_GPIO36CFG, 0x82 },
956 { STB0899_GPIO37CFG, 0x82 },
957 { STB0899_GPIO38CFG, 0x82 },
958 { STB0899_GPIO39CFG, 0x82 },
959 { STB0899_NCOARSE, 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
960 { STB0899_SYNTCTRL, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
961 { STB0899_FILTCTRL, 0x00 },
962 { STB0899_SYSCTRL, 0x00 },
963 { STB0899_STOPCLK1, 0x20 },
964 { STB0899_STOPCLK2, 0x00 },
965 { STB0899_INTBUFSTATUS, 0x00 },
966 { STB0899_INTBUFCTRL, 0x0a },
967 { 0xffff, 0xff },
968 };
969
970 static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
971 { STB0899_DEMOD, 0x00 },
972 { STB0899_RCOMPC, 0xc9 },
973 { STB0899_AGC1CN, 0x41 },
974 { STB0899_AGC1REF, 0x08 },
975 { STB0899_RTC, 0x7a },
976 { STB0899_TMGCFG, 0x4e },
977 { STB0899_AGC2REF, 0x33 },
978 { STB0899_TLSR, 0x84 },
979 { STB0899_CFD, 0xee },
980 { STB0899_ACLC, 0x87 },
981 { STB0899_BCLC, 0x94 },
982 { STB0899_EQON, 0x41 },
983 { STB0899_LDT, 0xdd },
984 { STB0899_LDT2, 0xc9 },
985 { STB0899_EQUALREF, 0xb4 },
986 { STB0899_TMGRAMP, 0x10 },
987 { STB0899_TMGTHD, 0x30 },
988 { STB0899_IDCCOMP, 0xfb },
989 { STB0899_QDCCOMP, 0x03 },
990 { STB0899_POWERI, 0x3b },
991 { STB0899_POWERQ, 0x3d },
992 { STB0899_RCOMP, 0x81 },
993 { STB0899_AGCIQIN, 0x80 },
994 { STB0899_AGC2I1, 0x04 },
995 { STB0899_AGC2I2, 0xf5 },
996 { STB0899_TLIR, 0x25 },
997 { STB0899_RTF, 0x80 },
998 { STB0899_DSTATUS, 0x00 },
999 { STB0899_LDI, 0xca },
1000 { STB0899_CFRM, 0xf1 },
1001 { STB0899_CFRL, 0xf3 },
1002 { STB0899_NIRM, 0x2a },
1003 { STB0899_NIRL, 0x05 },
1004 { STB0899_ISYMB, 0x17 },
1005 { STB0899_QSYMB, 0xfa },
1006 { STB0899_SFRH, 0x2f },
1007 { STB0899_SFRM, 0x68 },
1008 { STB0899_SFRL, 0x40 },
1009 { STB0899_SFRUPH, 0x2f },
1010 { STB0899_SFRUPM, 0x68 },
1011 { STB0899_SFRUPL, 0x40 },
1012 { STB0899_EQUAI1, 0xfd },
1013 { STB0899_EQUAQ1, 0x04 },
1014 { STB0899_EQUAI2, 0x0f },
1015 { STB0899_EQUAQ2, 0xff },
1016 { STB0899_EQUAI3, 0xdf },
1017 { STB0899_EQUAQ3, 0xfa },
1018 { STB0899_EQUAI4, 0x37 },
1019 { STB0899_EQUAQ4, 0x0d },
1020 { STB0899_EQUAI5, 0xbd },
1021 { STB0899_EQUAQ5, 0xf7 },
1022 { STB0899_DSTATUS2, 0x00 },
1023 { STB0899_VSTATUS, 0x00 },
1024 { STB0899_VERROR, 0xff },
1025 { STB0899_IQSWAP, 0x2a },
1026 { STB0899_ECNT1M, 0x00 },
1027 { STB0899_ECNT1L, 0x00 },
1028 { STB0899_ECNT2M, 0x00 },
1029 { STB0899_ECNT2L, 0x00 },
1030 { STB0899_ECNT3M, 0x00 },
1031 { STB0899_ECNT3L, 0x00 },
1032 { STB0899_FECAUTO1, 0x06 },
1033 { STB0899_FECM, 0x01 },
1034 { STB0899_VTH12, 0xf0 },
1035 { STB0899_VTH23, 0xa0 },
1036 { STB0899_VTH34, 0x78 },
1037 { STB0899_VTH56, 0x4e },
1038 { STB0899_VTH67, 0x48 },
1039 { STB0899_VTH78, 0x38 },
1040 { STB0899_PRVIT, 0xff },
1041 { STB0899_VITSYNC, 0x19 },
1042 { STB0899_RSULC, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
1043 { STB0899_TSULC, 0x42 },
1044 { STB0899_RSLLC, 0x40 },
1045 { STB0899_TSLPL, 0x12 },
1046 { STB0899_TSCFGH, 0x0c },
1047 { STB0899_TSCFGM, 0x00 },
1048 { STB0899_TSCFGL, 0x0c },
1049 { STB0899_TSOUT, 0x4d }, /* 0x0d for CAM */
1050 { STB0899_RSSYNCDEL, 0x00 },
1051 { STB0899_TSINHDELH, 0x02 },
1052 { STB0899_TSINHDELM, 0x00 },
1053 { STB0899_TSINHDELL, 0x00 },
1054 { STB0899_TSLLSTKM, 0x00 },
1055 { STB0899_TSLLSTKL, 0x00 },
1056 { STB0899_TSULSTKM, 0x00 },
1057 { STB0899_TSULSTKL, 0xab },
1058 { STB0899_PCKLENUL, 0x00 },
1059 { STB0899_PCKLENLL, 0xcc },
1060 { STB0899_RSPCKLEN, 0xcc },
1061 { STB0899_TSSTATUS, 0x80 },
1062 { STB0899_ERRCTRL1, 0xb6 },
1063 { STB0899_ERRCTRL2, 0x96 },
1064 { STB0899_ERRCTRL3, 0x89 },
1065 { STB0899_DMONMSK1, 0x27 },
1066 { STB0899_DMONMSK0, 0x03 },
1067 { STB0899_DEMAPVIT, 0x5c },
1068 { STB0899_PLPARM, 0x1f },
1069 { STB0899_PDELCTRL, 0x48 },
1070 { STB0899_PDELCTRL2, 0x00 },
1071 { STB0899_BBHCTRL1, 0x00 },
1072 { STB0899_BBHCTRL2, 0x00 },
1073 { STB0899_HYSTTHRESH, 0x77 },
1074 { STB0899_MATCSTM, 0x00 },
1075 { STB0899_MATCSTL, 0x00 },
1076 { STB0899_UPLCSTM, 0x00 },
1077 { STB0899_UPLCSTL, 0x00 },
1078 { STB0899_DFLCSTM, 0x00 },
1079 { STB0899_DFLCSTL, 0x00 },
1080 { STB0899_SYNCCST, 0x00 },
1081 { STB0899_SYNCDCSTM, 0x00 },
1082 { STB0899_SYNCDCSTL, 0x00 },
1083 { STB0899_ISI_ENTRY, 0x00 },
1084 { STB0899_ISI_BIT_EN, 0x00 },
1085 { STB0899_MATSTRM, 0x00 },
1086 { STB0899_MATSTRL, 0x00 },
1087 { STB0899_UPLSTRM, 0x00 },
1088 { STB0899_UPLSTRL, 0x00 },
1089 { STB0899_DFLSTRM, 0x00 },
1090 { STB0899_DFLSTRL, 0x00 },
1091 { STB0899_SYNCSTR, 0x00 },
1092 { STB0899_SYNCDSTRM, 0x00 },
1093 { STB0899_SYNCDSTRL, 0x00 },
1094 { STB0899_CFGPDELSTATUS1, 0x10 },
1095 { STB0899_CFGPDELSTATUS2, 0x00 },
1096 { STB0899_BBFERRORM, 0x00 },
1097 { STB0899_BBFERRORL, 0x00 },
1098 { STB0899_UPKTERRORM, 0x00 },
1099 { STB0899_UPKTERRORL, 0x00 },
1100 { 0xffff, 0xff },
1101 };
1102
1103 /* STB0899 demodulator config for the KNC1 and clones */
1104 static struct stb0899_config knc1_dvbs2_config = {
1105 .init_dev = knc1_stb0899_s1_init_1,
1106 .init_s2_demod = stb0899_s2_init_2,
1107 .init_s1_demod = knc1_stb0899_s1_init_3,
1108 .init_s2_fec = stb0899_s2_init_4,
1109 .init_tst = stb0899_s1_init_5,
1110
1111 .postproc = NULL,
1112
1113 .demod_address = 0x68,
1114 // .ts_output_mode = STB0899_OUT_PARALLEL, /* types = SERIAL/PARALLEL */
1115 .block_sync_mode = STB0899_SYNC_FORCED, /* DSS, SYNC_FORCED/UNSYNCED */
1116 // .ts_pfbit_toggle = STB0899_MPEG_NORMAL, /* DirecTV, MPEG toggling seq */
1117
1118 .xtal_freq = 27000000,
1119 .inversion = IQ_SWAP_OFF,
1120
1121 .lo_clk = 76500000,
1122 .hi_clk = 90000000,
1123
1124 .esno_ave = STB0899_DVBS2_ESNO_AVE,
1125 .esno_quant = STB0899_DVBS2_ESNO_QUANT,
1126 .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
1127 .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
1128 .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
1129 .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
1130 .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
1131 .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
1132 .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
1133
1134 .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
1135 .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
1136 .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
1137 .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
1138
1139 .tuner_get_frequency = tda8261_get_frequency,
1140 .tuner_set_frequency = tda8261_set_frequency,
1141 .tuner_set_bandwidth = NULL,
1142 .tuner_get_bandwidth = tda8261_get_bandwidth,
1143 .tuner_set_rfsiggain = NULL
1144 };
1145
1146 /*
1147 * SD1878/SHA tuner config
1148 * 1F, Single I/P, Horizontal mount, High Sensitivity
1149 */
1150 static const struct tda8261_config sd1878c_config = {
1151 // .name = "SD1878/SHA",
1152 .addr = 0x60,
1153 .step_size = TDA8261_STEP_1000 /* kHz */
1154 };
1155
read_pwm(struct budget_av * budget_av)1156 static u8 read_pwm(struct budget_av *budget_av)
1157 {
1158 u8 b = 0xff;
1159 u8 pwm;
1160 struct i2c_msg msg[] = { {.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
1161 {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
1162 };
1163
1164 if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
1165 || (pwm == 0xff))
1166 pwm = 0x48;
1167
1168 return pwm;
1169 }
1170
1171 #define SUBID_DVBS_KNC1 0x0010
1172 #define SUBID_DVBS_KNC1_PLUS 0x0011
1173 #define SUBID_DVBS_TYPHOON 0x4f56
1174 #define SUBID_DVBS_CINERGY1200 0x1154
1175 #define SUBID_DVBS_CYNERGY1200N 0x1155
1176 #define SUBID_DVBS_TV_STAR 0x0014
1177 #define SUBID_DVBS_TV_STAR_PLUS_X4 0x0015
1178 #define SUBID_DVBS_TV_STAR_CI 0x0016
1179 #define SUBID_DVBS2_KNC1 0x0018
1180 #define SUBID_DVBS2_KNC1_OEM 0x0019
1181 #define SUBID_DVBS_EASYWATCH_1 0x001a
1182 #define SUBID_DVBS_EASYWATCH_2 0x001b
1183 #define SUBID_DVBS2_EASYWATCH 0x001d
1184 #define SUBID_DVBS_EASYWATCH 0x001e
1185
1186 #define SUBID_DVBC_EASYWATCH 0x002a
1187 #define SUBID_DVBC_EASYWATCH_MK3 0x002c
1188 #define SUBID_DVBC_KNC1 0x0020
1189 #define SUBID_DVBC_KNC1_PLUS 0x0021
1190 #define SUBID_DVBC_KNC1_MK3 0x0022
1191 #define SUBID_DVBC_KNC1_TDA10024 0x0028
1192 #define SUBID_DVBC_KNC1_PLUS_MK3 0x0023
1193 #define SUBID_DVBC_CINERGY1200 0x1156
1194 #define SUBID_DVBC_CINERGY1200_MK3 0x1176
1195
1196 #define SUBID_DVBT_EASYWATCH 0x003a
1197 #define SUBID_DVBT_KNC1_PLUS 0x0031
1198 #define SUBID_DVBT_KNC1 0x0030
1199 #define SUBID_DVBT_CINERGY1200 0x1157
1200
frontend_init(struct budget_av * budget_av)1201 static void frontend_init(struct budget_av *budget_av)
1202 {
1203 struct saa7146_dev *saa = budget_av->budget.dev;
1204 struct dvb_frontend *fe = NULL;
1205
1206 /* Enable / PowerON Frontend */
1207 saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
1208
1209 /* Wait for PowerON */
1210 msleep(100);
1211
1212 /* additional setup necessary for the PLUS cards */
1213 switch (saa->pci->subsystem_device) {
1214 case SUBID_DVBS_KNC1_PLUS:
1215 case SUBID_DVBC_KNC1_PLUS:
1216 case SUBID_DVBT_KNC1_PLUS:
1217 case SUBID_DVBC_EASYWATCH:
1218 case SUBID_DVBC_KNC1_PLUS_MK3:
1219 case SUBID_DVBS2_KNC1:
1220 case SUBID_DVBS2_KNC1_OEM:
1221 case SUBID_DVBS2_EASYWATCH:
1222 saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
1223 break;
1224 }
1225
1226 switch (saa->pci->subsystem_device) {
1227
1228 case SUBID_DVBS_KNC1:
1229 /*
1230 * maybe that setting is needed for other dvb-s cards as well,
1231 * but so far it has been only confirmed for this type
1232 */
1233 budget_av->reinitialise_demod = 1;
1234 fallthrough;
1235 case SUBID_DVBS_KNC1_PLUS:
1236 case SUBID_DVBS_EASYWATCH_1:
1237 if (saa->pci->subsystem_vendor == 0x1894) {
1238 fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
1239 &budget_av->budget.i2c_adap);
1240 if (fe)
1241 dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
1242 } else {
1243 fe = dvb_attach(stv0299_attach, &typhoon_config,
1244 &budget_av->budget.i2c_adap);
1245 if (fe)
1246 fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
1247 }
1248 break;
1249
1250 case SUBID_DVBS_TV_STAR:
1251 case SUBID_DVBS_TV_STAR_PLUS_X4:
1252 case SUBID_DVBS_TV_STAR_CI:
1253 case SUBID_DVBS_CYNERGY1200N:
1254 case SUBID_DVBS_EASYWATCH:
1255 case SUBID_DVBS_EASYWATCH_2:
1256 fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
1257 &budget_av->budget.i2c_adap);
1258 if (fe)
1259 dvb_attach(dvb_pll_attach, fe, 0x60,
1260 &budget_av->budget.i2c_adap,
1261 DVB_PLL_PHILIPS_SD1878_TDA8261);
1262 break;
1263
1264 case SUBID_DVBS_TYPHOON:
1265 fe = dvb_attach(stv0299_attach, &typhoon_config,
1266 &budget_av->budget.i2c_adap);
1267 if (fe)
1268 fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
1269 break;
1270 case SUBID_DVBS2_KNC1:
1271 case SUBID_DVBS2_KNC1_OEM:
1272 case SUBID_DVBS2_EASYWATCH:
1273 budget_av->reinitialise_demod = 1;
1274 fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap);
1275 if (fe)
1276 dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);
1277
1278 break;
1279 case SUBID_DVBS_CINERGY1200:
1280 fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
1281 &budget_av->budget.i2c_adap);
1282 if (fe)
1283 fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
1284 break;
1285
1286 case SUBID_DVBC_KNC1:
1287 case SUBID_DVBC_KNC1_PLUS:
1288 case SUBID_DVBC_CINERGY1200:
1289 case SUBID_DVBC_EASYWATCH:
1290 budget_av->reinitialise_demod = 1;
1291 budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
1292 fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
1293 &budget_av->budget.i2c_adap,
1294 read_pwm(budget_av));
1295 if (fe == NULL)
1296 fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
1297 &budget_av->budget.i2c_adap,
1298 read_pwm(budget_av));
1299 if (fe)
1300 fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
1301 break;
1302
1303 case SUBID_DVBC_EASYWATCH_MK3:
1304 case SUBID_DVBC_CINERGY1200_MK3:
1305 case SUBID_DVBC_KNC1_MK3:
1306 case SUBID_DVBC_KNC1_TDA10024:
1307 case SUBID_DVBC_KNC1_PLUS_MK3:
1308 budget_av->reinitialise_demod = 1;
1309 budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
1310 fe = dvb_attach(tda10023_attach,
1311 &philips_cu1216_tda10023_config,
1312 &budget_av->budget.i2c_adap,
1313 read_pwm(budget_av));
1314 if (fe)
1315 fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
1316 break;
1317
1318 case SUBID_DVBT_EASYWATCH:
1319 case SUBID_DVBT_KNC1:
1320 case SUBID_DVBT_KNC1_PLUS:
1321 case SUBID_DVBT_CINERGY1200:
1322 budget_av->reinitialise_demod = 1;
1323 fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
1324 &budget_av->budget.i2c_adap);
1325 if (fe) {
1326 fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
1327 fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
1328 }
1329 break;
1330 }
1331
1332 if (fe == NULL) {
1333 pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
1334 saa->pci->vendor,
1335 saa->pci->device,
1336 saa->pci->subsystem_vendor,
1337 saa->pci->subsystem_device);
1338 return;
1339 }
1340
1341 budget_av->budget.dvb_frontend = fe;
1342
1343 if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
1344 budget_av->budget.dvb_frontend)) {
1345 pr_err("Frontend registration failed!\n");
1346 dvb_frontend_detach(budget_av->budget.dvb_frontend);
1347 budget_av->budget.dvb_frontend = NULL;
1348 }
1349 }
1350
1351
budget_av_irq(struct saa7146_dev * dev,u32 * isr)1352 static void budget_av_irq(struct saa7146_dev *dev, u32 *isr)
1353 {
1354 struct budget_av *budget_av = dev->ext_priv;
1355
1356 dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
1357
1358 if (*isr & MASK_10)
1359 ttpci_budget_irq10_handler(dev, isr);
1360 }
1361
budget_av_detach(struct saa7146_dev * dev)1362 static int budget_av_detach(struct saa7146_dev *dev)
1363 {
1364 struct budget_av *budget_av = dev->ext_priv;
1365 int err;
1366
1367 dprintk(2, "dev: %p\n", dev);
1368
1369 if (budget_av->has_saa7113 == 1) {
1370 saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
1371
1372 msleep(200);
1373
1374 saa7146_unregister_device(&budget_av->vd, dev);
1375
1376 saa7146_vv_release(dev);
1377 }
1378
1379 if (budget_av->budget.ci_present)
1380 ciintf_deinit(budget_av);
1381
1382 if (budget_av->budget.dvb_frontend != NULL) {
1383 dvb_unregister_frontend(budget_av->budget.dvb_frontend);
1384 dvb_frontend_detach(budget_av->budget.dvb_frontend);
1385 }
1386 err = ttpci_budget_deinit(&budget_av->budget);
1387
1388 kfree(budget_av);
1389
1390 return err;
1391 }
1392
1393 #define KNC1_INPUTS 2
1394 static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
1395 { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0,
1396 V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
1397 { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0,
1398 V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
1399 };
1400
vidioc_enum_input(struct file * file,void * fh,struct v4l2_input * i)1401 static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
1402 {
1403 dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);
1404 if (i->index >= KNC1_INPUTS)
1405 return -EINVAL;
1406 memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
1407 return 0;
1408 }
1409
vidioc_g_input(struct file * file,void * fh,unsigned int * i)1410 static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
1411 {
1412 struct saa7146_dev *dev = video_drvdata(file);
1413 struct budget_av *budget_av = dev->ext_priv;
1414
1415 *i = budget_av->cur_input;
1416
1417 dprintk(1, "VIDIOC_G_INPUT %d\n", *i);
1418 return 0;
1419 }
1420
vidioc_s_input(struct file * file,void * fh,unsigned int input)1421 static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
1422 {
1423 struct saa7146_dev *dev = video_drvdata(file);
1424 struct budget_av *budget_av = dev->ext_priv;
1425
1426 dprintk(1, "VIDIOC_S_INPUT %d\n", input);
1427 return saa7113_setinput(budget_av, input);
1428 }
1429
1430 static struct saa7146_ext_vv vv_data;
1431
budget_av_attach(struct saa7146_dev * dev,struct saa7146_pci_extension_data * info)1432 static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
1433 {
1434 struct budget_av *budget_av;
1435 u8 *mac;
1436 int err;
1437
1438 dprintk(2, "dev: %p\n", dev);
1439
1440 budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL);
1441 if (!budget_av)
1442 return -ENOMEM;
1443
1444 budget_av->has_saa7113 = 0;
1445 budget_av->budget.ci_present = 0;
1446
1447 dev->ext_priv = budget_av;
1448
1449 err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,
1450 adapter_nr);
1451 if (err) {
1452 kfree(budget_av);
1453 return err;
1454 }
1455
1456 /* knc1 initialization */
1457 saa7146_write(dev, DD1_STREAM_B, 0x04000000);
1458 saa7146_write(dev, DD1_INIT, 0x07000600);
1459 saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
1460
1461 if (saa7113_init(budget_av) == 0) {
1462 budget_av->has_saa7113 = 1;
1463 err = saa7146_vv_init(dev, &vv_data);
1464 if (err != 0) {
1465 ttpci_budget_deinit(&budget_av->budget);
1466 kfree(budget_av);
1467 pr_err("cannot init vv subsystem\n");
1468 return err;
1469 }
1470 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
1471 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
1472 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
1473
1474 err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_VIDEO);
1475 if (err) {
1476 saa7146_vv_release(dev);
1477 ttpci_budget_deinit(&budget_av->budget);
1478 kfree(budget_av);
1479 pr_err("cannot register capture v4l2 device\n");
1480 return err;
1481 }
1482
1483 /* beware: this modifies dev->vv ... */
1484 saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
1485 SAA7146_HPS_SYNC_PORT_A);
1486
1487 saa7113_setinput(budget_av, 0);
1488 }
1489
1490 /* fixme: find some sane values here... */
1491 saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
1492
1493 mac = budget_av->budget.dvb_adapter.proposed_mac;
1494 if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
1495 pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
1496 budget_av->budget.dvb_adapter.num);
1497 eth_zero_addr(mac);
1498 } else {
1499 pr_info("KNC1-%d: MAC addr = %pM\n",
1500 budget_av->budget.dvb_adapter.num, mac);
1501 }
1502
1503 budget_av->budget.dvb_adapter.priv = budget_av;
1504 frontend_init(budget_av);
1505 ciintf_init(budget_av);
1506
1507 ttpci_budget_init_hooks(&budget_av->budget);
1508
1509 return 0;
1510 }
1511
1512 static struct saa7146_standard standard[] = {
1513 {.name = "PAL", .id = V4L2_STD_PAL,
1514 .v_offset = 0x17, .v_field = 288,
1515 .h_offset = 0x14, .h_pixels = 680,
1516 .v_max_out = 576, .h_max_out = 768 },
1517
1518 {.name = "NTSC", .id = V4L2_STD_NTSC,
1519 .v_offset = 0x16, .v_field = 240,
1520 .h_offset = 0x06, .h_pixels = 708,
1521 .v_max_out = 480, .h_max_out = 640, },
1522 };
1523
1524 static struct saa7146_ext_vv vv_data = {
1525 .inputs = 2,
1526 .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
1527 .flags = 0,
1528 .stds = &standard[0],
1529 .num_stds = ARRAY_SIZE(standard),
1530 };
1531
1532 static struct saa7146_extension budget_extension;
1533
1534 MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
1535 MAKE_BUDGET_INFO(knc1s2, "KNC1 DVB-S2", BUDGET_KNC1S2);
1536 MAKE_BUDGET_INFO(sates2, "Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);
1537 MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
1538 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
1539 MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
1540 MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
1541 MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
1542 MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);
1543 MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
1544 MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
1545 MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T);
1546 MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
1547 MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
1548 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
1549 MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
1550 MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
1551 MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
1552 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
1553 MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
1554 MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
1555 MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
1556 MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3);
1557 MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
1558
1559 static const struct pci_device_id pci_tbl[] = {
1560 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
1561 MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
1562 MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
1563 MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
1564 MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
1565 MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
1566 MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
1567 MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
1568 MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
1569 MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),
1570 MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),
1571 MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
1572 MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
1573 MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
1574 MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
1575 MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
1576 MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a),
1577 MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
1578 MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
1579 MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
1580 MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
1581 MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
1582 MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
1583 MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
1584 MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
1585 MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
1586 MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
1587 MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176),
1588 MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
1589 {
1590 .vendor = 0,
1591 }
1592 };
1593
1594 MODULE_DEVICE_TABLE(pci, pci_tbl);
1595
1596 static struct saa7146_extension budget_extension = {
1597 .name = "budget_av",
1598 .flags = SAA7146_USE_I2C_IRQ,
1599
1600 .pci_tbl = pci_tbl,
1601
1602 .module = THIS_MODULE,
1603 .attach = budget_av_attach,
1604 .detach = budget_av_detach,
1605
1606 .irq_mask = MASK_10,
1607 .irq_func = budget_av_irq,
1608 };
1609
budget_av_init(void)1610 static int __init budget_av_init(void)
1611 {
1612 return saa7146_register_extension(&budget_extension);
1613 }
1614
budget_av_exit(void)1615 static void __exit budget_av_exit(void)
1616 {
1617 saa7146_unregister_extension(&budget_extension);
1618 }
1619
1620 module_init(budget_av_init);
1621 module_exit(budget_av_exit);
1622
1623 MODULE_LICENSE("GPL");
1624 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
1625 MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
1626