tea5767.c 12.0 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 20 21
static int debug = 0;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable verbose debug messages");
22

23
#define PREFIX "tea5767"
24

25
/*****************************************************************************/
26

27 28 29 30
struct tea5767_priv {
	struct tuner_i2c_props	i2c_props;
	u32			frequency;
	struct tea5767_ctrl	ctrl;
31 32
};

33 34 35 36 37 38 39
/*****************************************************************************/

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

/* First register */
M
Mauro Carvalho Chehab 已提交
40 41
#define TEA5767_MUTE		0x80	/* Mutes output */
#define TEA5767_SEARCH		0x40	/* Activates station search */
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 73 74
/* 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

75
/* Fourth register */
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#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

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

/* 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

122
/* Fourth register */
123 124 125 126 127
#define TEA5767_ADC_LEVEL_MASK	0xf0

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

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

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

134 135
static void tea5767_status_dump(struct tea5767_priv *priv,
				unsigned char *buffer)
136 137 138 139 140 141 142 143 144 145 146 147 148
{
	unsigned int div, frq;

	if (TEA5767_READY_FLAG_MASK & buffer[0])
		printk(PREFIX "Ready Flag ON\n");
	else
		printk(PREFIX "Ready Flag OFF\n");

	if (TEA5767_BAND_LIMIT_MASK & buffer[0])
		printk(PREFIX "Tuner at band limit\n");
	else
		printk(PREFIX "Tuner not at band limit\n");

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

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

	printk(PREFIX "Frequency %d.%03d KHz (divider = 0x%04x)\n",
M
Mauro Carvalho Chehab 已提交
170
	       frq / 1000, frq % 1000, div);
171 172 173 174 175 176

	if (TEA5767_STEREO_MASK & buffer[2])
		printk(PREFIX "Stereo\n");
	else
		printk(PREFIX "Mono\n");

M
Mauro Carvalho Chehab 已提交
177
	printk(PREFIX "IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
178

M
Mauro Carvalho Chehab 已提交
179 180
	printk(PREFIX "ADC Level = %d\n",
	       (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
181

M
Mauro Carvalho Chehab 已提交
182
	printk(PREFIX "Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
183

M
Mauro Carvalho Chehab 已提交
184 185
	printk(PREFIX "Reserved = 0x%02x\n",
	       (buffer[4] & TEA5767_RESERVED_MASK));
186 187 188
}

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

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

200
	buffer[2] = 0;
201

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

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

	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) {
243
	case TEA5767_HIGH_LO_13MHz:
244
		tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
245
		buffer[2] |= TEA5767_HIGH_LO_INJECT;
246
		div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
247 248
		break;
	case TEA5767_LOW_LO_13MHz:
249
		tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
250

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

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

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

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

	priv->frequency = frq * 125 / 2;

	return 0;
284 285
}

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

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

297
	return 0;
298 299
}

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

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

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

	return signal;
}
310

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

315
	int stereo = buffer[2] & TEA5767_STEREO_MASK;
316

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

	return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
320 321
}

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

326 327
	*status = 0;

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
	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;
343

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

	return 0;
}

static int tea5767_standby(struct dvb_frontend *fe)
351 352
{
	unsigned char buffer[5];
353
	struct tea5767_priv *priv = fe->tuner_priv;
354 355 356 357 358 359 360 361 362 363
	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;

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

	return 0;
368 369
}

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

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

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

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

398 399
	/* It seems that tea5767 returns 0xff after the 5th byte */
	if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
400
		printk(KERN_WARNING "Returned more than 5 bytes. It is not a TEA5767\n");
401 402 403
		return EINVAL;
	}

404 405 406
	return 0;
}

407
static int tea5767_release(struct dvb_frontend *fe)
408
{
409 410 411 412
	kfree(fe->tuner_priv);
	fe->tuner_priv = NULL;

	return 0;
413 414
}

415 416 417 418
static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
	struct tea5767_priv *priv = fe->tuner_priv;
	*frequency = priv->frequency;
419 420 421 422 423 424 425 426 427 428

	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));

429 430 431 432 433 434 435 436 437
	return 0;
}

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

	.set_analog_params = set_radio_freq,
438
	.set_config	   = tea5767_set_config,
439 440 441 442
	.sleep             = tea5767_standby,
	.release           = tea5767_release,
	.get_frequency     = tea5767_get_frequency,
	.get_status        = tea5767_get_status,
443
	.get_rf_strength   = tea5767_get_rf_strength,
444 445
};

446 447 448
struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
				    struct i2c_adapter* i2c_adap,
				    u8 i2c_addr)
449
{
450 451 452 453
	struct tea5767_priv *priv = NULL;

	priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
	if (priv == NULL)
454 455
		return NULL;
	fe->tuner_priv = priv;
456

457 458 459 460 461 462 463 464
	priv->i2c_props.addr  = i2c_addr;
	priv->i2c_props.adap  = i2c_adap;
	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;
465

466 467
	memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
	       sizeof(struct dvb_tuner_ops));
468

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

471
	return fe;
472
}
473 474 475 476 477 478 479

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");