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