blob: 304f1f9b800836bbbb44bab2c7c47c8c668afa4b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 TDA10021 - Single Chip Cable Channel Receiver driver module
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08003 used on the 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
56#define DISABLE_INVERSION(reg0) do { reg0 |= 0x20; } while (0)
57#define ENABLE_INVERSION(reg0) do { reg0 &= ~0x20; } while (0)
58#define HAS_INVERSION(reg0) (!(reg0 & 0x20))
59
60#define FIN (XIN >> 4)
61
62static int tda10021_inittab_size = 0x40;
63static u8 tda10021_inittab[0x40]=
64{
65 0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,
66 0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,
Hartmut Birrfd9c66e2007-04-21 19:17:49 -030067 0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,
69 0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
70 0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,
71 0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0x00,
72 0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
73};
74
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -030075static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
Linus Torvalds1da177e2005-04-16 15:20:36 -070076{
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080077 u8 buf[] = { reg, data };
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -080079 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
81 ret = i2c_transfer (state->i2c, &msg, 1);
82 if (ret != 1)
83 printk("DVB: TDA10021(%d): %s, writereg error "
84 "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
85 state->frontend.dvb->num, __FUNCTION__, reg, data, ret);
86
87 msleep(10);
88 return (ret != 1) ? -EREMOTEIO : 0;
89}
90
91static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
92{
93 u8 b0 [] = { reg };
94 u8 b1 [] = { 0 };
95 struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
Michael Krufky50c25ff2006-01-09 15:25:34 -020096 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 int ret;
98
99 ret = i2c_transfer (state->i2c, msg, 2);
100 if (ret != 2)
Jon Burgess88bdcc52005-09-27 21:45:26 -0700101 printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
102 __FUNCTION__, ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 return b1[0];
104}
105
106//get access to tuner
107static int lock_tuner(struct tda10021_state* state)
108{
109 u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] | 0x80 };
110 struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
111
112 if(i2c_transfer(state->i2c, &msg, 1) != 1)
113 {
114 printk("tda10021: lock tuner fails\n");
115 return -EREMOTEIO;
116 }
117 return 0;
118}
119
120//release access from tuner
121static int unlock_tuner(struct tda10021_state* state)
122{
123 u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] & 0x7f };
124 struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
125
126 if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
127 {
128 printk("tda10021: unlock tuner fails\n");
129 return -EREMOTEIO;
130 }
131 return 0;
132}
133
134static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
135 fe_spectral_inversion_t inversion)
136{
137 reg0 |= state->reg0 & 0x63;
138
139 if (INVERSION_ON == inversion)
140 ENABLE_INVERSION(reg0);
141 else if (INVERSION_OFF == inversion)
142 DISABLE_INVERSION(reg0);
143
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300144 _tda10021_writereg (state, 0x00, reg0 & 0xfe);
145 _tda10021_writereg (state, 0x00, reg0 | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
147 state->reg0 = reg0;
148 return 0;
149}
150
151static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate)
152{
153 s32 BDR;
154 s32 BDRI;
155 s16 SFIL=0;
156 u16 NDEC = 0;
157 u32 tmp, ratio;
158
159 if (symbolrate > XIN/2)
160 symbolrate = XIN/2;
161 if (symbolrate < 500000)
162 symbolrate = 500000;
163
164 if (symbolrate < XIN/16) NDEC = 1;
165 if (symbolrate < XIN/32) NDEC = 2;
166 if (symbolrate < XIN/64) NDEC = 3;
167
168 if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;
169 if (symbolrate < (u32)(XIN/16)) SFIL = 0;
170 if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;
171 if (symbolrate < (u32)(XIN/32)) SFIL = 0;
172 if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;
173 if (symbolrate < (u32)(XIN/64)) SFIL = 0;
174 if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;
175
176 symbolrate <<= NDEC;
177 ratio = (symbolrate << 4) / FIN;
178 tmp = ((symbolrate << 4) % FIN) << 8;
179 ratio = (ratio << 8) + tmp / FIN;
180 tmp = (tmp % FIN) << 8;
181 ratio = (ratio << 8) + (tmp + FIN/2) / FIN;
182
183 BDR = ratio;
184 BDRI = (((XIN << 5) / symbolrate) + 1) / 2;
185
186 if (BDRI > 0xFF)
187 BDRI = 0xFF;
188
189 SFIL = (SFIL << 4) | tda10021_inittab[0x0E];
190
191 NDEC = (NDEC << 6) | tda10021_inittab[0x03];
192
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300193 _tda10021_writereg (state, 0x03, NDEC);
194 _tda10021_writereg (state, 0x0a, BDR&0xff);
195 _tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
196 _tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300198 _tda10021_writereg (state, 0x0d, BDRI);
199 _tda10021_writereg (state, 0x0e, SFIL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201 return 0;
202}
203
204static int tda10021_init (struct dvb_frontend *fe)
205{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700206 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 int i;
208
209 dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
210
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300211 //_tda10021_writereg (fe, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 for (i=0; i<tda10021_inittab_size; i++)
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300214 _tda10021_writereg (state, i, tda10021_inittab[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300216 _tda10021_writereg (state, 0x34, state->pwm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218 //Comment by markus
219 //0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
220 //0x2A[4] == BYPPLL -> Power down mode (default 1)
221 //0x2A[5] == LCK -> PLL Lock Flag
222 //0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
223
224 //Activate PLL
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300225 _tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 return 0;
227}
228
229static int tda10021_set_parameters (struct dvb_frontend *fe,
230 struct dvb_frontend_parameters *p)
231{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700232 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
234 //table for QAM4-QAM256 ready QAM4 QAM16 QAM32 QAM64 QAM128 QAM256
235 //CONF
236 static const u8 reg0x00 [] = { 0x14, 0x00, 0x04, 0x08, 0x0c, 0x10 };
237 //AGCREF value
238 static const u8 reg0x01 [] = { 0x78, 0x8c, 0x8c, 0x6a, 0x78, 0x5c };
239 //LTHR value
240 static const u8 reg0x05 [] = { 0x78, 0x87, 0x64, 0x46, 0x36, 0x26 };
241 //MSETH
242 static const u8 reg0x08 [] = { 0x8c, 0xa2, 0x74, 0x43, 0x34, 0x23 };
243 //AREF
244 static const u8 reg0x09 [] = { 0x96, 0x91, 0x96, 0x6a, 0x7e, 0x6b };
245
246 int qam = p->u.qam.modulation;
247
248 if (qam < 0 || qam > 5)
249 return -EINVAL;
250
251 //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
252
Patrick Boettcherdea74862006-05-14 05:01:31 -0300253 if (fe->ops.tuner_ops.set_params) {
254 fe->ops.tuner_ops.set_params(fe, p);
255 if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
Andrew de Quinceyf1e80912006-04-18 17:47:10 -0300256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
258 tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300259 _tda10021_writereg (state, 0x34, state->pwm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300261 _tda10021_writereg (state, 0x01, reg0x01[qam]);
262 _tda10021_writereg (state, 0x05, reg0x05[qam]);
263 _tda10021_writereg (state, 0x08, reg0x08[qam]);
264 _tda10021_writereg (state, 0x09, reg0x09[qam]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266 tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
267
268 return 0;
269}
270
271static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
272{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700273 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 int sync;
275
276 *status = 0;
277 //0x11[0] == EQALGO -> Equalizer algorithms state
278 //0x11[1] == CARLOCK -> Carrier locked
279 //0x11[2] == FSYNC -> Frame synchronisation
280 //0x11[3] == FEL -> Front End locked
281 //0x11[6] == NODVB -> DVB Mode Information
282 sync = tda10021_readreg (state, 0x11);
283
284 if (sync & 2)
285 *status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
286
287 if (sync & 4)
288 *status |= FE_HAS_SYNC|FE_HAS_VITERBI;
289
290 if (sync & 8)
291 *status |= FE_HAS_LOCK;
292
293 return 0;
294}
295
296static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
297{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700298 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 u32 _ber = tda10021_readreg(state, 0x14) |
301 (tda10021_readreg(state, 0x15) << 8) |
302 ((tda10021_readreg(state, 0x16) & 0x0f) << 16);
303 *ber = 10 * _ber;
304
305 return 0;
306}
307
308static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
309{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700310 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
312 u8 gain = tda10021_readreg(state, 0x17);
313 *strength = (gain << 8) | gain;
314
315 return 0;
316}
317
318static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
319{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700320 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
322 u8 quality = ~tda10021_readreg(state, 0x18);
323 *snr = (quality << 8) | quality;
324
325 return 0;
326}
327
328static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
329{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700330 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
332 *ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
333 if (*ucblocks == 0x7f)
334 *ucblocks = 0xffffffff;
335
336 /* reset uncorrected block counter */
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300337 _tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
338 _tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
340 return 0;
341}
342
343static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
344{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700345 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 int sync;
347 s8 afc = 0;
348
349 sync = tda10021_readreg(state, 0x11);
350 afc = tda10021_readreg(state, 0x19);
351 if (verbose) {
352 /* AFC only valid when carrier has been recovered */
353 printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
354 "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
355 state->frontend.dvb->num, afc,
356 -((s32)p->u.qam.symbol_rate * afc) >> 10);
357 }
358
359 p->inversion = HAS_INVERSION(state->reg0) ? INVERSION_ON : INVERSION_OFF;
360 p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
361
362 p->u.qam.fec_inner = FEC_NONE;
363 p->frequency = ((p->frequency + 31250) / 62500) * 62500;
364
365 if (sync & 2)
366 p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
367
368 return 0;
369}
370
Andrew de Quinceyf1e80912006-04-18 17:47:10 -0300371static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
372{
373 struct tda10021_state* state = fe->demodulator_priv;
374
375 if (enable) {
376 lock_tuner(state);
377 } else {
378 unlock_tuner(state);
379 }
380 return 0;
381}
382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383static int tda10021_sleep(struct dvb_frontend* fe)
384{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700385 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -0300387 _tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
388 _tda10021_writereg (state, 0x00, 0x80); /* standby */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
390 return 0;
391}
392
393static void tda10021_release(struct dvb_frontend* fe)
394{
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700395 struct tda10021_state* state = fe->demodulator_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 kfree(state);
397}
398
399static struct dvb_frontend_ops tda10021_ops;
400
Hartmut Birraa323ac2007-04-21 19:37:17 -0300401struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 struct i2c_adapter* i2c,
403 u8 pwm)
404{
405 struct tda10021_state* state = NULL;
406
407 /* allocate memory for the internal state */
Johannes Stezenbachb8742702005-05-16 21:54:31 -0700408 state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 if (state == NULL) goto error;
410
411 /* setup the state */
412 state->config = config;
413 state->i2c = i2c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 state->pwm = pwm;
415 state->reg0 = tda10021_inittab[0];
416
417 /* check if the demod is there */
418 if ((tda10021_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
419
420 /* create dvb_frontend */
Patrick Boettcherdea74862006-05-14 05:01:31 -0300421 memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 state->frontend.demodulator_priv = state;
423 return &state->frontend;
424
425error:
426 kfree(state);
427 return NULL;
428}
429
430static struct dvb_frontend_ops tda10021_ops = {
431
432 .info = {
433 .name = "Philips TDA10021 DVB-C",
434 .type = FE_QAM,
435 .frequency_stepsize = 62500,
436 .frequency_min = 51000000,
437 .frequency_max = 858000000,
438 .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
439 .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
Mauro Carvalho Chehabacf28212007-04-27 12:31:06 -0300440 #if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 .frequency_tolerance = ???,
442 .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
443 #endif
444 .caps = 0x400 | //FE_CAN_QAM_4
445 FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
446 FE_CAN_QAM_128 | FE_CAN_QAM_256 |
447 FE_CAN_FEC_AUTO
448 },
449
450 .release = tda10021_release,
451
452 .init = tda10021_init,
453 .sleep = tda10021_sleep,
Andrew de Quinceyf1e80912006-04-18 17:47:10 -0300454 .i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456 .set_frontend = tda10021_set_parameters,
457 .get_frontend = tda10021_get_frontend,
458
459 .read_status = tda10021_read_status,
460 .read_ber = tda10021_read_ber,
461 .read_signal_strength = tda10021_read_signal_strength,
462 .read_snr = tda10021_read_snr,
463 .read_ucblocks = tda10021_read_ucblocks,
464};
465
466module_param(verbose, int, 0644);
467MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
468
469MODULE_DESCRIPTION("Philips TDA10021 DVB-C demodulator driver");
470MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Markus Schulz");
471MODULE_LICENSE("GPL");
472
473EXPORT_SYMBOL(tda10021_attach);