tea5767.c 11.8 KB
Newer Older
1 2 3 4 5
/*
 * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
 * I2C address is allways 0xC0.
 *
 *
6
 * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org)
7 8 9 10 11 12 13
 * This code is placed under the terms of the GNU General Public License
 *
 * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
 * from their contributions on DScaler.
 */

#include <linux/i2c.h>
M
Mauro Carvalho Chehab 已提交
14
#include <linux/delay.h>
15
#include <linux/videodev.h>
16 17
#include "tuner-i2c.h"
#include "tea5767.h"
18

19
static int debug;
20 21
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable verbose debug messages");
22

23
/*****************************************************************************/
24

25 26 27 28
struct tea5767_priv {
	struct tuner_i2c_props	i2c_props;
	u32			frequency;
	struct tea5767_ctrl	ctrl;
29 30
};

31 32 33 34 35 36 37
/*****************************************************************************/

/******************************
 * Write mode register values *
 ******************************/

/* First register */
M
Mauro Carvalho Chehab 已提交
38 39
#define TEA5767_MUTE		0x80	/* Mutes output */
#define TEA5767_SEARCH		0x40	/* Activates station search */
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
/* Bits 0-5 for divider MSB */

/* Second register */
/* Bits 0-7 for divider LSB */

/* Third register */

/* Station search from botton to up */
#define TEA5767_SEARCH_UP	0x80

/* Searches with ADC output = 10 */
#define TEA5767_SRCH_HIGH_LVL	0x60

/* Searches with ADC output = 10 */
#define TEA5767_SRCH_MID_LVL	0x40

/* Searches with ADC output = 5 */
#define TEA5767_SRCH_LOW_LVL	0x20

/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
#define TEA5767_HIGH_LO_INJECT	0x10

/* Disable stereo */
#define TEA5767_MONO		0x08

/* Disable right channel and turns to mono */
#define TEA5767_MUTE_RIGHT	0x04

/* Disable left channel and turns to mono */
#define TEA5767_MUTE_LEFT	0x02

#define TEA5767_PORT1_HIGH	0x01

73
/* Fourth register */
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
#define TEA5767_PORT2_HIGH	0x80
/* Chips stops working. Only I2C bus remains on */
#define TEA5767_STDBY		0x40

/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
#define TEA5767_JAPAN_BAND	0x20

/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
#define TEA5767_XTAL_32768	0x10

/* Cuts weak signals */
#define TEA5767_SOFT_MUTE	0x08

/* Activates high cut control */
#define TEA5767_HIGH_CUT_CTRL	0x04

/* Activates stereo noise control */
#define TEA5767_ST_NOISE_CTL	0x02

/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
#define TEA5767_SRCH_IND	0x01

96
/* Fifth register */
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

/* By activating, it will use Xtal at 13 MHz as reference for divider */
#define TEA5767_PLLREF_ENABLE	0x80

/* By activating, deemphasis=50, or else, deemphasis of 50us */
#define TEA5767_DEEMPH_75	0X40

/*****************************
 * Read mode register values *
 *****************************/

/* First register */
#define TEA5767_READY_FLAG_MASK	0x80
#define TEA5767_BAND_LIMIT_MASK	0X40
/* Bits 0-5 for divider MSB after search or preset */

/* Second register */
/* Bits 0-7 for divider LSB after search or preset */

/* Third register */
#define TEA5767_STEREO_MASK	0x80
#define TEA5767_IF_CNTR_MASK	0x7f

120
/* Fourth register */
121 122 123 124 125
#define TEA5767_ADC_LEVEL_MASK	0xf0

/* should be 0 */
#define TEA5767_CHIP_ID_MASK	0x0f

126
/* Fifth register */
127 128 129 130 131
/* Reserved for future extensions */
#define TEA5767_RESERVED_MASK	0xff

/*****************************************************************************/

132 133
static void tea5767_status_dump(struct tea5767_priv *priv,
				unsigned char *buffer)
134 135 136 137
{
	unsigned int div, frq;

	if (TEA5767_READY_FLAG_MASK & buffer[0])
138
		tuner_info("Ready Flag ON\n");
139
	else
140
		tuner_info("Ready Flag OFF\n");
141 142

	if (TEA5767_BAND_LIMIT_MASK & buffer[0])
143
		tuner_info("Tuner at band limit\n");
144
	else
145
		tuner_info("Tuner not at band limit\n");
146

M
Mauro Carvalho Chehab 已提交
147
	div = ((buffer[0] & 0x3f) << 8) | buffer[1];
148

149
	switch (priv->ctrl.xtal_freq) {
150
	case TEA5767_HIGH_LO_13MHz:
151
		frq = (div * 50000 - 700000 - 225000) / 4;	/* Freq in KHz */
152 153
		break;
	case TEA5767_LOW_LO_13MHz:
154
		frq = (div * 50000 + 700000 + 225000) / 4;	/* Freq in KHz */
155 156
		break;
	case TEA5767_LOW_LO_32768:
157
		frq = (div * 32768 + 700000 + 225000) / 4;	/* Freq in KHz */
158 159 160
		break;
	case TEA5767_HIGH_LO_32768:
	default:
161
		frq = (div * 32768 - 700000 - 225000) / 4;	/* Freq in KHz */
162 163
		break;
	}
M
Mauro Carvalho Chehab 已提交
164 165
	buffer[0] = (div >> 8) & 0x3f;
	buffer[1] = div & 0xff;
166

167 168
	tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
		   frq / 1000, frq % 1000, div);
169 170

	if (TEA5767_STEREO_MASK & buffer[2])
171
		tuner_info("Stereo\n");
172
	else
173
		tuner_info("Mono\n");
174

175
	tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
176

177 178
	tuner_info("ADC Level = %d\n",
		   (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
179

180
	tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
181

182 183
	tuner_info("Reserved = 0x%02x\n",
		   (buffer[4] & TEA5767_RESERVED_MASK));
184 185 186
}

/* Freq should be specifyed at 62.5 Hz */
187 188
static int set_radio_freq(struct dvb_frontend *fe,
			  struct analog_parameters *params)
189
{
190 191
	struct tea5767_priv *priv = fe->tuner_priv;
	unsigned int frq = params->frequency;
M
Mauro Carvalho Chehab 已提交
192
	unsigned char buffer[5];
193 194 195
	unsigned div;
	int rc;

196
	tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
197

198
	buffer[2] = 0;
199

200 201
	if (priv->ctrl.port1)
		buffer[2] |= TEA5767_PORT1_HIGH;
M
Mauro Carvalho Chehab 已提交
202

203
	if (params->audmode == V4L2_TUNER_MODE_MONO) {
204 205
		tuner_dbg("TEA5767 set to mono\n");
		buffer[2] |= TEA5767_MONO;
M
Mauro Carvalho Chehab 已提交
206 207 208
	} else {
		tuner_dbg("TEA5767 set to stereo\n");
	}
209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240

	buffer[3] = 0;

	if (priv->ctrl.port2)
		buffer[3] |= TEA5767_PORT2_HIGH;

	if (priv->ctrl.high_cut)
		buffer[3] |= TEA5767_HIGH_CUT_CTRL;

	if (priv->ctrl.st_noise)
		buffer[3] |= TEA5767_ST_NOISE_CTL;

	if (priv->ctrl.soft_mute)
		buffer[3] |= TEA5767_SOFT_MUTE;

	if (priv->ctrl.japan_band)
		buffer[3] |= TEA5767_JAPAN_BAND;

	buffer[4] = 0;

	if (priv->ctrl.deemph_75)
		buffer[4] |= TEA5767_DEEMPH_75;

	if (priv->ctrl.pllref)
		buffer[4] |= TEA5767_PLLREF_ENABLE;


	/* Rounds freq to next decimal value - for 62.5 KHz step */
	/* frq = 20*(frq/16)+radio_frq[frq%16]; */

	switch (priv->ctrl.xtal_freq) {
241
	case TEA5767_HIGH_LO_13MHz:
242
		tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
243
		buffer[2] |= TEA5767_HIGH_LO_INJECT;
244
		div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
245 246
		break;
	case TEA5767_LOW_LO_13MHz:
247
		tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
248

249
		div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
250 251
		break;
	case TEA5767_LOW_LO_32768:
252
		tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
253 254
		buffer[3] |= TEA5767_XTAL_32768;
		/* const 700=4000*175 Khz - to adjust freq to right value */
255
		div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
256 257 258
		break;
	case TEA5767_HIGH_LO_32768:
	default:
259
		tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
260 261 262

		buffer[2] |= TEA5767_HIGH_LO_INJECT;
		buffer[3] |= TEA5767_XTAL_32768;
263
		div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
264 265
		break;
	}
M
Mauro Carvalho Chehab 已提交
266 267
	buffer[0] = (div >> 8) & 0x3f;
	buffer[1] = div & 0xff;
268

269
	if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
M
Mauro Carvalho Chehab 已提交
270
		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
271

272
	if (debug) {
273
		if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5)))
274 275
			tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
		else
276
			tea5767_status_dump(priv, buffer);
277
	}
278 279 280 281

	priv->frequency = frq * 125 / 2;

	return 0;
282 283
}

284
static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
285
{
286
	struct tea5767_priv *priv = fe->tuner_priv;
287
	int rc;
288

289 290
	memset(buffer, 0, 5);
	if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
M
Mauro Carvalho Chehab 已提交
291
		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
292 293
		return -EREMOTEIO;
	}
294

295
	return 0;
296 297
}

298
static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
299
{
300
	struct tea5767_priv *priv = fe->tuner_priv;
301

302 303 304 305 306 307
	int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);

	tuner_dbg("Signal strength: %d\n", signal);

	return signal;
}
308

309 310 311
static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
{
	struct tea5767_priv *priv = fe->tuner_priv;
312

313
	int stereo = buffer[2] & TEA5767_STEREO_MASK;
314

315 316 317
	tuner_dbg("Radio ST GET = %02x\n", stereo);

	return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
318 319
}

320 321
static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
{
322 323
	unsigned char buffer[5];

324 325
	*status = 0;

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	if (0 == tea5767_read_status(fe, buffer)) {
		if (tea5767_signal(fe, buffer))
			*status = TUNER_STATUS_LOCKED;
		if (tea5767_stereo(fe, buffer))
			*status |= TUNER_STATUS_STEREO;
	}

	return 0;
}

static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
{
	unsigned char buffer[5];

	*strength = 0;
341

342 343
	if (0 == tea5767_read_status(fe, buffer))
		*strength = tea5767_signal(fe, buffer);
344 345 346 347 348

	return 0;
}

static int tea5767_standby(struct dvb_frontend *fe)
349 350
{
	unsigned char buffer[5];
351
	struct tea5767_priv *priv = fe->tuner_priv;
352 353 354 355 356 357 358 359 360 361
	unsigned div, rc;

	div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
	buffer[0] = (div >> 8) & 0x3f;
	buffer[1] = div & 0xff;
	buffer[2] = TEA5767_PORT1_HIGH;
	buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
		    TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
	buffer[4] = 0;

362
	if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
363
		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
364 365

	return 0;
366 367
}

368
int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
369
{
370
	struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
371
	unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
372 373
	int rc;

374 375
	if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
		printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
376 377 378
		return EINVAL;
	}

379
	/* If all bytes are the same then it's a TV tuner and not a tea5767 */
M
Mauro Carvalho Chehab 已提交
380 381
	if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
	    buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
382
		printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
383 384 385 386 387
		return EINVAL;
	}

	/*  Status bytes:
	 *  Byte 4: bit 3:1 : CI (Chip Identification) == 0
M
Mauro Carvalho Chehab 已提交
388
	 *          bit 0   : internally set to 0
389 390
	 *  Byte 5: bit 7:0 : == 0
	 */
391
	if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
392
		printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
393 394
		return EINVAL;
	}
395

396

397 398 399
	return 0;
}

400
static int tea5767_release(struct dvb_frontend *fe)
401
{
402 403 404 405
	kfree(fe->tuner_priv);
	fe->tuner_priv = NULL;

	return 0;
406 407
}

408 409 410 411
static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
	struct tea5767_priv *priv = fe->tuner_priv;
	*frequency = priv->frequency;
412 413 414 415 416 417 418 419 420 421

	return 0;
}

static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg)
{
	struct tea5767_priv *priv = fe->tuner_priv;

	memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl));

422 423 424 425 426 427 428 429 430
	return 0;
}

static struct dvb_tuner_ops tea5767_tuner_ops = {
	.info = {
		.name           = "tea5767", // Philips TEA5767HN FM Radio
	},

	.set_analog_params = set_radio_freq,
431
	.set_config	   = tea5767_set_config,
432 433 434 435
	.sleep             = tea5767_standby,
	.release           = tea5767_release,
	.get_frequency     = tea5767_get_frequency,
	.get_status        = tea5767_get_status,
436
	.get_rf_strength   = tea5767_get_rf_strength,
437 438
};

439 440 441
struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
				    struct i2c_adapter* i2c_adap,
				    u8 i2c_addr)
442
{
443 444 445 446
	struct tea5767_priv *priv = NULL;

	priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
	if (priv == NULL)
447 448
		return NULL;
	fe->tuner_priv = priv;
449

450 451
	priv->i2c_props.addr  = i2c_addr;
	priv->i2c_props.adap  = i2c_adap;
452 453
	priv->i2c_props.name  = "tea5767";

454 455 456 457 458 459
	priv->ctrl.xtal_freq  = TEA5767_HIGH_LO_32768;
	priv->ctrl.port1      = 1;
	priv->ctrl.port2      = 1;
	priv->ctrl.high_cut   = 1;
	priv->ctrl.st_noise   = 1;
	priv->ctrl.japan_band = 1;
460

461 462
	memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
	       sizeof(struct dvb_tuner_ops));
463

464
	tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
465

466
	return fe;
467
}
468 469 470 471 472 473 474

EXPORT_SYMBOL_GPL(tea5767_attach);
EXPORT_SYMBOL_GPL(tea5767_autodetection);

MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_LICENSE("GPL");