tda10021.c 13.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
    TDA10021  - Single Chip Cable Channel Receiver driver module
3
	       used on the Siemens DVB-C cards
L
Linus Torvalds 已提交
4 5 6

    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
7
		   Support for TDA10021
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>

#include "dvb_frontend.h"
33
#include "tda1002x.h"
L
Linus Torvalds 已提交
34 35 36 37 38


struct tda10021_state {
	struct i2c_adapter* i2c;
	/* configuration settings */
39
	const struct tda1002x_config* config;
L
Linus Torvalds 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
	struct dvb_frontend frontend;

	u8 pwm;
	u8 reg0;
};


#if 0
#define dprintk(x...) printk(x)
#else
#define dprintk(x...)
#endif

static int verbose;

#define XIN 57840000UL

#define FIN (XIN >> 4)

static int tda10021_inittab_size = 0x40;
static u8 tda10021_inittab[0x40]=
{
	0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,
	0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,
64
	0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff,
L
Linus Torvalds 已提交
65 66 67 68 69 70 71
	0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,
	0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
	0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,
	0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0x00,
	0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
};

72
static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
L
Linus Torvalds 已提交
73
{
74
	u8 buf[] = { reg, data };
L
Linus Torvalds 已提交
75
	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
76
	int ret;
L
Linus Torvalds 已提交
77 78 79

	ret = i2c_transfer (state->i2c, &msg, 1);
	if (ret != 1)
80
		printk("DVB: TDA10021(%d): %s, writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
81
			state->frontend.dvb->num, __func__, reg, data, ret);
L
Linus Torvalds 已提交
82 83 84 85 86 87 88 89 90 91

	msleep(10);
	return (ret != 1) ? -EREMOTEIO : 0;
}

static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
{
	u8 b0 [] = { reg };
	u8 b1 [] = { 0 };
	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
92
				  { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
L
Linus Torvalds 已提交
93 94 95
	int ret;

	ret = i2c_transfer (state->i2c, msg, 2);
96 97
	// Don't print an error message if the id is read.
	if (ret != 2 && reg != 0x1a)
98
		printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
99
				__func__, ret);
L
Linus Torvalds 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
	return b1[0];
}

//get access to tuner
static int lock_tuner(struct tda10021_state* state)
{
	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] | 0x80 };
	struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};

	if(i2c_transfer(state->i2c, &msg, 1) != 1)
	{
		printk("tda10021: lock tuner fails\n");
		return -EREMOTEIO;
	}
	return 0;
}

//release access from tuner
static int unlock_tuner(struct tda10021_state* state)
{
	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] & 0x7f };
	struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};

	if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
	{
		printk("tda10021: unlock tuner fails\n");
		return -EREMOTEIO;
	}
	return 0;
}

131 132
static int tda10021_setup_reg0(struct tda10021_state *state, u8 reg0,
			       enum fe_spectral_inversion inversion)
L
Linus Torvalds 已提交
133 134 135
{
	reg0 |= state->reg0 & 0x63;

136 137 138 139
	if ((INVERSION_ON == inversion) ^ (state->config->invert == 0))
		reg0 &= ~0x20;
	else
		reg0 |= 0x20;
L
Linus Torvalds 已提交
140

141 142
	_tda10021_writereg (state, 0x00, reg0 & 0xfe);
	_tda10021_writereg (state, 0x00, reg0 | 0x01);
L
Linus Torvalds 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

	state->reg0 = reg0;
	return 0;
}

static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate)
{
	s32 BDR;
	s32 BDRI;
	s16 SFIL=0;
	u16 NDEC = 0;
	u32 tmp, ratio;

	if (symbolrate > XIN/2)
		symbolrate = XIN/2;
	if (symbolrate < 500000)
		symbolrate = 500000;

	if (symbolrate < XIN/16) NDEC = 1;
	if (symbolrate < XIN/32) NDEC = 2;
	if (symbolrate < XIN/64) NDEC = 3;

	if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;
	if (symbolrate < (u32)(XIN/16))	 SFIL = 0;
	if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;
	if (symbolrate < (u32)(XIN/32))	 SFIL = 0;
	if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;
	if (symbolrate < (u32)(XIN/64))	 SFIL = 0;
	if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;

	symbolrate <<= NDEC;
	ratio = (symbolrate << 4) / FIN;
	tmp =  ((symbolrate << 4) % FIN) << 8;
	ratio = (ratio << 8) + tmp / FIN;
	tmp = (tmp % FIN) << 8;
178
	ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN);
L
Linus Torvalds 已提交
179 180 181 182 183 184 185 186 187 188 189

	BDR = ratio;
	BDRI = (((XIN << 5) / symbolrate) + 1) / 2;

	if (BDRI > 0xFF)
		BDRI = 0xFF;

	SFIL = (SFIL << 4) | tda10021_inittab[0x0E];

	NDEC = (NDEC << 6) | tda10021_inittab[0x03];

190 191 192 193
	_tda10021_writereg (state, 0x03, NDEC);
	_tda10021_writereg (state, 0x0a, BDR&0xff);
	_tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
	_tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
L
Linus Torvalds 已提交
194

195 196
	_tda10021_writereg (state, 0x0d, BDRI);
	_tda10021_writereg (state, 0x0e, SFIL);
L
Linus Torvalds 已提交
197 198 199 200 201 202

	return 0;
}

static int tda10021_init (struct dvb_frontend *fe)
{
203
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
204 205 206 207
	int i;

	dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);

208
	//_tda10021_writereg (fe, 0, 0);
L
Linus Torvalds 已提交
209 210

	for (i=0; i<tda10021_inittab_size; i++)
211
		_tda10021_writereg (state, i, tda10021_inittab[i]);
L
Linus Torvalds 已提交
212

213
	_tda10021_writereg (state, 0x34, state->pwm);
L
Linus Torvalds 已提交
214 215 216 217 218 219 220 221

	//Comment by markus
	//0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
	//0x2A[4] == BYPPLL -> Power down mode (default 1)
	//0x2A[5] == LCK -> PLL Lock Flag
	//0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)

	//Activate PLL
222
	_tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
L
Linus Torvalds 已提交
223 224 225
	return 0;
}

226 227 228 229
struct qam_params {
	u8 conf, agcref, lthr, mseth, aref;
};

230
static int tda10021_set_parameters(struct dvb_frontend *fe)
L
Linus Torvalds 已提交
231
{
232 233 234 235 236
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	u32 delsys  = c->delivery_system;
	unsigned qam = c->modulation;
	bool is_annex_c;
	u32 reg0x3d;
237
	struct tda10021_state* state = fe->demodulator_priv;
238 239 240 241 242 243 244 245 246
	static const struct qam_params qam_params[] = {
		/* Modulation  Conf  AGCref  LTHR  MSETH  AREF */
		[QPSK]	   = { 0x14, 0x78,   0x78, 0x8c,  0x96 },
		[QAM_16]   = { 0x00, 0x8c,   0x87, 0xa2,  0x91 },
		[QAM_32]   = { 0x04, 0x8c,   0x64, 0x74,  0x96 },
		[QAM_64]   = { 0x08, 0x6a,   0x46, 0x43,  0x6a },
		[QAM_128]  = { 0x0c, 0x78,   0x36, 0x34,  0x7e },
		[QAM_256]  = { 0x10, 0x5c,   0x26, 0x23,  0x6b },
	};
247 248 249 250 251 252 253 254 255 256 257

	switch (delsys) {
	case SYS_DVBC_ANNEX_A:
		is_annex_c = false;
		break;
	case SYS_DVBC_ANNEX_C:
		is_annex_c = true;
		break;
	default:
		return -EINVAL;
	}
L
Linus Torvalds 已提交
258

259
	/*
260
	 * gcc optimizes the code below the same way as it would code:
261 262 263 264 265 266 267 268 269 270 271 272 273 274
	 *           "if (qam > 5) return -EINVAL;"
	 * Yet, the code is clearer, as it shows what QAM standards are
	 * supported by the driver, and avoids the usage of magic numbers on
	 * it.
	 */
	switch (qam) {
	case QPSK:
	case QAM_16:
	case QAM_32:
	case QAM_64:
	case QAM_128:
	case QAM_256:
		break;
	default:
L
Linus Torvalds 已提交
275
		return -EINVAL;
276
	}
L
Linus Torvalds 已提交
277

278
	if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF)
279 280
		return -EINVAL;

281
	/*printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->symbol_rate);*/
L
Linus Torvalds 已提交
282

283
	if (fe->ops.tuner_ops.set_params) {
284
		fe->ops.tuner_ops.set_params(fe);
285
		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
286
	}
L
Linus Torvalds 已提交
287

288
	tda10021_set_symbolrate(state, c->symbol_rate);
289
	_tda10021_writereg(state, 0x34, state->pwm);
L
Linus Torvalds 已提交
290

291 292 293 294
	_tda10021_writereg(state, 0x01, qam_params[qam].agcref);
	_tda10021_writereg(state, 0x05, qam_params[qam].lthr);
	_tda10021_writereg(state, 0x08, qam_params[qam].mseth);
	_tda10021_writereg(state, 0x09, qam_params[qam].aref);
295 296 297 298 299 300 301 302 303 304 305

	/*
	 * Bit 0 == 0 means roll-off = 0.15 (Annex A)
	 *	 == 1 means roll-off = 0.13 (Annex C)
	 */
	reg0x3d = tda10021_readreg (state, 0x3d);
	if (is_annex_c)
		_tda10021_writereg (state, 0x3d, 0x01 | reg0x3d);
	else
		_tda10021_writereg (state, 0x3d, 0xfe & reg0x3d);
	tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion);
L
Linus Torvalds 已提交
306 307 308 309

	return 0;
}

310 311
static int tda10021_read_status(struct dvb_frontend *fe,
				enum fe_status *status)
L
Linus Torvalds 已提交
312
{
313
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
	int sync;

	*status = 0;
	//0x11[0] == EQALGO -> Equalizer algorithms state
	//0x11[1] == CARLOCK -> Carrier locked
	//0x11[2] == FSYNC -> Frame synchronisation
	//0x11[3] == FEL -> Front End locked
	//0x11[6] == NODVB -> DVB Mode Information
	sync = tda10021_readreg (state, 0x11);

	if (sync & 2)
		*status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;

	if (sync & 4)
		*status |= FE_HAS_SYNC|FE_HAS_VITERBI;

	if (sync & 8)
		*status |= FE_HAS_LOCK;

	return 0;
}

static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
{
338
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
339 340 341 342

	u32 _ber = tda10021_readreg(state, 0x14) |
		(tda10021_readreg(state, 0x15) << 8) |
		((tda10021_readreg(state, 0x16) & 0x0f) << 16);
343 344
	_tda10021_writereg(state, 0x10, (tda10021_readreg(state, 0x10) & ~0xc0)
					| (tda10021_inittab[0x10] & 0xc0));
L
Linus Torvalds 已提交
345 346 347 348 349 350 351
	*ber = 10 * _ber;

	return 0;
}

static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
352
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
353

354
	u8 config = tda10021_readreg(state, 0x02);
L
Linus Torvalds 已提交
355
	u8 gain = tda10021_readreg(state, 0x17);
356 357 358
	if (config & 0x02)
		/* the agc value is inverted */
		gain = ~gain;
L
Linus Torvalds 已提交
359 360 361 362 363 364 365
	*strength = (gain << 8) | gain;

	return 0;
}

static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
{
366
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
367 368 369 370 371 372 373 374 375

	u8 quality = ~tda10021_readreg(state, 0x18);
	*snr = (quality << 8) | quality;

	return 0;
}

static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
376
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
377 378 379 380 381 382

	*ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
	if (*ucblocks == 0x7f)
		*ucblocks = 0xffffffff;

	/* reset uncorrected block counter */
383 384
	_tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
	_tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
L
Linus Torvalds 已提交
385 386 387 388

	return 0;
}

389 390
static int tda10021_get_frontend(struct dvb_frontend *fe,
				 struct dtv_frontend_properties *p)
L
Linus Torvalds 已提交
391
{
392
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
393 394 395 396 397 398 399 400 401 402
	int sync;
	s8 afc = 0;

	sync = tda10021_readreg(state, 0x11);
	afc = tda10021_readreg(state, 0x19);
	if (verbose) {
		/* AFC only valid when carrier has been recovered */
		printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
				  "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
			state->frontend.dvb->num, afc,
403
		       -((s32)p->symbol_rate * afc) >> 10);
L
Linus Torvalds 已提交
404 405
	}

406
	p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
407
	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
L
Linus Torvalds 已提交
408

409
	p->fec_inner = FEC_NONE;
L
Linus Torvalds 已提交
410 411 412
	p->frequency = ((p->frequency + 31250) / 62500) * 62500;

	if (sync & 2)
413
		p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
L
Linus Torvalds 已提交
414 415 416 417

	return 0;
}

418 419 420 421 422 423 424 425 426 427 428 429
static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
	struct tda10021_state* state = fe->demodulator_priv;

	if (enable) {
		lock_tuner(state);
	} else {
		unlock_tuner(state);
	}
	return 0;
}

L
Linus Torvalds 已提交
430 431
static int tda10021_sleep(struct dvb_frontend* fe)
{
432
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
433

434 435
	_tda10021_writereg (state, 0x1b, 0x02);  /* pdown ADC */
	_tda10021_writereg (state, 0x00, 0x80);  /* standby */
L
Linus Torvalds 已提交
436 437 438 439 440 441

	return 0;
}

static void tda10021_release(struct dvb_frontend* fe)
{
442
	struct tda10021_state* state = fe->demodulator_priv;
L
Linus Torvalds 已提交
443 444 445 446 447
	kfree(state);
}

static struct dvb_frontend_ops tda10021_ops;

448
struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
L
Linus Torvalds 已提交
449 450 451 452
				     struct i2c_adapter* i2c,
				     u8 pwm)
{
	struct tda10021_state* state = NULL;
453
	u8 id;
L
Linus Torvalds 已提交
454 455

	/* allocate memory for the internal state */
456
	state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL);
L
Linus Torvalds 已提交
457 458 459 460 461 462 463 464 465
	if (state == NULL) goto error;

	/* setup the state */
	state->config = config;
	state->i2c = i2c;
	state->pwm = pwm;
	state->reg0 = tda10021_inittab[0];

	/* check if the demod is there */
466 467 468
	id = tda10021_readreg(state, 0x1a);
	if ((id & 0xf0) != 0x70) goto error;

469 470 471 472
	/* Don't claim TDA10023 */
	if (id == 0x7d)
		goto error;

473 474
	printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n",
	       state->config->demod_address, id);
L
Linus Torvalds 已提交
475 476

	/* create dvb_frontend */
477
	memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
L
Linus Torvalds 已提交
478 479 480 481 482 483 484 485 486
	state->frontend.demodulator_priv = state;
	return &state->frontend;

error:
	kfree(state);
	return NULL;
}

static struct dvb_frontend_ops tda10021_ops = {
487
	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
L
Linus Torvalds 已提交
488 489 490
	.info = {
		.name = "Philips TDA10021 DVB-C",
		.frequency_stepsize = 62500,
491 492
		.frequency_min = 47000000,
		.frequency_max = 862000000,
L
Linus Torvalds 已提交
493 494
		.symbol_rate_min = (XIN/2)/64,     /* SACLK/64 == (XIN/2)/64 */
		.symbol_rate_max = (XIN/2)/4,      /* SACLK/4 */
495
	#if 0
L
Linus Torvalds 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508
		.frequency_tolerance = ???,
		.symbol_rate_tolerance = ???,  /* ppm */  /* == 8% (spec p. 5) */
	#endif
		.caps = 0x400 | //FE_CAN_QAM_4
			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
			FE_CAN_FEC_AUTO
	},

	.release = tda10021_release,

	.init = tda10021_init,
	.sleep = tda10021_sleep,
509
	.i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
L
Linus Torvalds 已提交
510

511 512
	.set_frontend = tda10021_set_parameters,
	.get_frontend = tda10021_get_frontend,
L
Linus Torvalds 已提交
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528

	.read_status = tda10021_read_status,
	.read_ber = tda10021_read_ber,
	.read_signal_strength = tda10021_read_signal_strength,
	.read_snr = tda10021_read_snr,
	.read_ucblocks = tda10021_read_ucblocks,
};

module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");

MODULE_DESCRIPTION("Philips TDA10021 DVB-C demodulator driver");
MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Markus Schulz");
MODULE_LICENSE("GPL");

EXPORT_SYMBOL(tda10021_attach);