blob: 5ee729846a9f1dea9654c27980dec9f8d8bb87cc [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 TDA10021 - Single Chip Cable Channel Receiver driver module
Michael Opdenacker59c51592007-05-09 08:57:56 +02003 used on the Siemens DVB-C cards
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
6 Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08007 Support for TDA10021
Linus Torvalds1da177e2005-04-16 15:20:36 -07008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/delay.h>
25#include <linux/errno.h>
26#include <linux/init.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/string.h>
30#include <linux/slab.h>
31
32#include "dvb_frontend.h"
Hartmut Birraa323ac2007-04-21 19:37:17 -030033#include "tda1002x.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35
36struct tda10021_state {
37 struct i2c_adapter* i2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 /* configuration settings */
Hartmut Birraa323ac2007-04-21 19:37:17 -030039 const struct tda1002x_config* config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 struct dvb_frontend frontend;
41
42 u8 pwm;
43 u8 reg0;
44};
45
46
47#if 0
48#define dprintk(x...) printk(x)
49#else
50#define dprintk(x...)
51#endif
52
53static int verbose;
54
55#define XIN 57840000UL
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57#define FIN (XIN >> 4)
58
59static int tda10021_inittab_size = 0x40;
60static u8 tda10021_inittab[0x40]=
61{
62 0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,
63 0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,
Hartmut Birrfd9c66e2007-04-21 19:17:49 -030064 0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,
66 0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
67 0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,
68 0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0x00,
69 0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
70};
71
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -030072static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080074 u8 buf[] = { reg, data };
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080076 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78 ret = i2c_transfer (state->i2c, &msg, 1);
79 if (ret != 1)
80 printk("DVB: TDA10021(%d): %s, writereg error "
81 "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
82 state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
83
84 msleep(10);
85 return (ret != 1) ? -EREMOTEIO : 0;
86}
87
88static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
89{
90 u8 b0 [] = { reg };
91 u8 b1 [] = { 0 };
92 struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
Michael Krufky50c25ff2006-01-09 15:25:34 -020093 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 int ret;
95
96 ret = i2c_transfer (state->i2c, msg, 2);
Hartmut Birrdc120b072007-04-21 19:44:10 -030097 // Don't print an error message if the id is read.
98 if (ret != 2 && reg != 0x1a)
Jon Burgess88bdcc52005-09-27 21:45:26 -070099 printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
100 __FUNCTION__, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 return b1[0];
102}
103
104//get access to tuner
105static int lock_tuner(struct tda10021_state* state)
106{
107 u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] | 0x80 };
108 struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
109
110 if(i2c_transfer(state->i2c, &msg, 1) != 1)
111 {
112 printk("tda10021: lock tuner fails\n");
113 return -EREMOTEIO;
114 }
115 return 0;
116}
117
118//release access from tuner
119static int unlock_tuner(struct tda10021_state* state)
120{
121 u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] & 0x7f };
122 struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
123
124 if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
125 {
126 printk("tda10021: unlock tuner fails\n");
127 return -EREMOTEIO;
128 }
129 return 0;
130}
131
132static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
133 fe_spectral_inversion_t inversion)
134{
135 reg0 |= state->reg0 & 0x63;
136
Hartmut Birrdc120b072007-04-21 19:44:10 -0300137 if ((INVERSION_ON == inversion) ^ (state->config->invert == 0))
138 reg0 &= ~0x20;
139 else
140 reg0 |= 0x20;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300142 _tda10021_writereg (state, 0x00, reg0 & 0xfe);
143 _tda10021_writereg (state, 0x00, reg0 | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
145 state->reg0 = reg0;
146 return 0;
147}
148
149static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate)
150{
151 s32 BDR;
152 s32 BDRI;
153 s16 SFIL=0;
154 u16 NDEC = 0;
155 u32 tmp, ratio;
156
157 if (symbolrate > XIN/2)
158 symbolrate = XIN/2;
159 if (symbolrate < 500000)
160 symbolrate = 500000;
161
162 if (symbolrate < XIN/16) NDEC = 1;
163 if (symbolrate < XIN/32) NDEC = 2;
164 if (symbolrate < XIN/64) NDEC = 3;
165
166 if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;
167 if (symbolrate < (u32)(XIN/16)) SFIL = 0;
168 if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;
169 if (symbolrate < (u32)(XIN/32)) SFIL = 0;
170 if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;
171 if (symbolrate < (u32)(XIN/64)) SFIL = 0;
172 if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;
173
174 symbolrate <<= NDEC;
175 ratio = (symbolrate << 4) / FIN;
176 tmp = ((symbolrate << 4) % FIN) << 8;
177 ratio = (ratio << 8) + tmp / FIN;
178 tmp = (tmp % FIN) << 8;
179 ratio = (ratio << 8) + (tmp + FIN/2) / FIN;
180
181 BDR = ratio;
182 BDRI = (((XIN << 5) / symbolrate) + 1) / 2;
183
184 if (BDRI > 0xFF)
185 BDRI = 0xFF;
186
187 SFIL = (SFIL << 4) | tda10021_inittab[0x0E];
188
189 NDEC = (NDEC << 6) | tda10021_inittab[0x03];
190
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300191 _tda10021_writereg (state, 0x03, NDEC);
192 _tda10021_writereg (state, 0x0a, BDR&0xff);
193 _tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
194 _tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300196 _tda10021_writereg (state, 0x0d, BDRI);
197 _tda10021_writereg (state, 0x0e, SFIL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
199 return 0;
200}
201
202static int tda10021_init (struct dvb_frontend *fe)
203{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700204 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 int i;
206
207 dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
208
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300209 //_tda10021_writereg (fe, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
211 for (i=0; i<tda10021_inittab_size; i++)
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300212 _tda10021_writereg (state, i, tda10021_inittab[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300214 _tda10021_writereg (state, 0x34, state->pwm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216 //Comment by markus
217 //0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
218 //0x2A[4] == BYPPLL -> Power down mode (default 1)
219 //0x2A[5] == LCK -> PLL Lock Flag
220 //0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
221
222 //Activate PLL
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300223 _tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 return 0;
225}
226
227static int tda10021_set_parameters (struct dvb_frontend *fe,
228 struct dvb_frontend_parameters *p)
229{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700230 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
232 //table for QAM4-QAM256 ready QAM4 QAM16 QAM32 QAM64 QAM128 QAM256
233 //CONF
234 static const u8 reg0x00 [] = { 0x14, 0x00, 0x04, 0x08, 0x0c, 0x10 };
235 //AGCREF value
236 static const u8 reg0x01 [] = { 0x78, 0x8c, 0x8c, 0x6a, 0x78, 0x5c };
237 //LTHR value
238 static const u8 reg0x05 [] = { 0x78, 0x87, 0x64, 0x46, 0x36, 0x26 };
239 //MSETH
240 static const u8 reg0x08 [] = { 0x8c, 0xa2, 0x74, 0x43, 0x34, 0x23 };
241 //AREF
242 static const u8 reg0x09 [] = { 0x96, 0x91, 0x96, 0x6a, 0x7e, 0x6b };
243
244 int qam = p->u.qam.modulation;
245
246 if (qam < 0 || qam > 5)
247 return -EINVAL;
248
Hartmut Birrdc120b072007-04-21 19:44:10 -0300249 if (p->inversion != INVERSION_ON && p->inversion != INVERSION_OFF)
250 return -EINVAL;
251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
253
Patrick Boettcherdea74862006-05-14 05:01:31 -0300254 if (fe->ops.tuner_ops.set_params) {
255 fe->ops.tuner_ops.set_params(fe, p);
256 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quinceyf1e80912006-04-18 17:47:10 -0300257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259 tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300260 _tda10021_writereg (state, 0x34, state->pwm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300262 _tda10021_writereg (state, 0x01, reg0x01[qam]);
263 _tda10021_writereg (state, 0x05, reg0x05[qam]);
264 _tda10021_writereg (state, 0x08, reg0x08[qam]);
265 _tda10021_writereg (state, 0x09, reg0x09[qam]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
267 tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
268
269 return 0;
270}
271
272static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
273{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700274 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 int sync;
276
277 *status = 0;
278 //0x11[0] == EQALGO -> Equalizer algorithms state
279 //0x11[1] == CARLOCK -> Carrier locked
280 //0x11[2] == FSYNC -> Frame synchronisation
281 //0x11[3] == FEL -> Front End locked
282 //0x11[6] == NODVB -> DVB Mode Information
283 sync = tda10021_readreg (state, 0x11);
284
285 if (sync & 2)
286 *status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
287
288 if (sync & 4)
289 *status |= FE_HAS_SYNC|FE_HAS_VITERBI;
290
291 if (sync & 8)
292 *status |= FE_HAS_LOCK;
293
294 return 0;
295}
296
297static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
298{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700299 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 u32 _ber = tda10021_readreg(state, 0x14) |
302 (tda10021_readreg(state, 0x15) << 8) |
303 ((tda10021_readreg(state, 0x16) & 0x0f) << 16);
Hartmut Birr3de0e182007-10-31 01:50:47 -0300304 _tda10021_writereg(state, 0x10, (tda10021_readreg(state, 0x10) & ~0xc0)
305 | (tda10021_inittab[0x10] & 0xc0));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 *ber = 10 * _ber;
307
308 return 0;
309}
310
311static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
312{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700313 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
315 u8 gain = tda10021_readreg(state, 0x17);
316 *strength = (gain << 8) | gain;
317
318 return 0;
319}
320
321static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
322{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700323 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
325 u8 quality = ~tda10021_readreg(state, 0x18);
326 *snr = (quality << 8) | quality;
327
328 return 0;
329}
330
331static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
332{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700333 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335 *ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
336 if (*ucblocks == 0x7f)
337 *ucblocks = 0xffffffff;
338
339 /* reset uncorrected block counter */
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300340 _tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
341 _tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343 return 0;
344}
345
346static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
347{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700348 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 int sync;
350 s8 afc = 0;
351
352 sync = tda10021_readreg(state, 0x11);
353 afc = tda10021_readreg(state, 0x19);
354 if (verbose) {
355 /* AFC only valid when carrier has been recovered */
356 printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
357 "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
358 state->frontend.dvb->num, afc,
359 -((s32)p->u.qam.symbol_rate * afc) >> 10);
360 }
361
Hartmut Birrdc120b072007-04-21 19:44:10 -0300362 p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
364
365 p->u.qam.fec_inner = FEC_NONE;
366 p->frequency = ((p->frequency + 31250) / 62500) * 62500;
367
368 if (sync & 2)
369 p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
370
371 return 0;
372}
373
Andrew de Quinceyf1e80912006-04-18 17:47:10 -0300374static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
375{
376 struct tda10021_state* state = fe->demodulator_priv;
377
378 if (enable) {
379 lock_tuner(state);
380 } else {
381 unlock_tuner(state);
382 }
383 return 0;
384}
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386static int tda10021_sleep(struct dvb_frontend* fe)
387{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700388 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300390 _tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
391 _tda10021_writereg (state, 0x00, 0x80); /* standby */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393 return 0;
394}
395
396static void tda10021_release(struct dvb_frontend* fe)
397{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700398 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 kfree(state);
400}
401
402static struct dvb_frontend_ops tda10021_ops;
403
Hartmut Birraa323ac2007-04-21 19:37:17 -0300404struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 struct i2c_adapter* i2c,
406 u8 pwm)
407{
408 struct tda10021_state* state = NULL;
Hartmut Birrdc120b072007-04-21 19:44:10 -0300409 u8 id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
411 /* allocate memory for the internal state */
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700412 state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 if (state == NULL) goto error;
414
415 /* setup the state */
416 state->config = config;
417 state->i2c = i2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 state->pwm = pwm;
419 state->reg0 = tda10021_inittab[0];
420
421 /* check if the demod is there */
Hartmut Birrdc120b072007-04-21 19:44:10 -0300422 id = tda10021_readreg(state, 0x1a);
423 if ((id & 0xf0) != 0x70) goto error;
424
425 printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n",
426 state->config->demod_address, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
428 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300429 memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 state->frontend.demodulator_priv = state;
431 return &state->frontend;
432
433error:
434 kfree(state);
435 return NULL;
436}
437
438static struct dvb_frontend_ops tda10021_ops = {
439
440 .info = {
441 .name = "Philips TDA10021 DVB-C",
442 .type = FE_QAM,
443 .frequency_stepsize = 62500,
Hartmut Birra18255b2007-08-09 00:01:51 -0300444 .frequency_min = 47000000,
445 .frequency_max = 862000000,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
447 .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
Mauro Carvalho Chehabacf28212007-04-27 12:31:06 -0300448 #if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 .frequency_tolerance = ???,
450 .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
451 #endif
452 .caps = 0x400 | //FE_CAN_QAM_4
453 FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
454 FE_CAN_QAM_128 | FE_CAN_QAM_256 |
455 FE_CAN_FEC_AUTO
456 },
457
458 .release = tda10021_release,
459
460 .init = tda10021_init,
461 .sleep = tda10021_sleep,
Andrew de Quinceyf1e80912006-04-18 17:47:10 -0300462 .i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 .set_frontend = tda10021_set_parameters,
465 .get_frontend = tda10021_get_frontend,
466
467 .read_status = tda10021_read_status,
468 .read_ber = tda10021_read_ber,
469 .read_signal_strength = tda10021_read_signal_strength,
470 .read_snr = tda10021_read_snr,
471 .read_ucblocks = tda10021_read_ucblocks,
472};
473
474module_param(verbose, int, 0644);
475MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
476
477MODULE_DESCRIPTION("Philips TDA10021 DVB-C demodulator driver");
478MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Markus Schulz");
479MODULE_LICENSE("GPL");
480
481EXPORT_SYMBOL(tda10021_attach);