tuner-xc2028.c 20.3 KB
Newer Older
1 2 3
/* tuner-xc2028
 *
 * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
4
 *
5 6
 * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
 *       - frontend interface
7
 *
8 9 10 11 12 13
 * This code is placed under the terms of the GNU General Public License v2
 */

#include <linux/i2c.h>
#include <asm/div64.h>
#include <linux/firmware.h>
14
#include <linux/videodev2.h>
15
#include <linux/delay.h>
16
#include <media/tuner.h>
17
#include <linux/mutex.h>
18
#include "tuner-i2c.h"
19
#include "tuner-xc2028.h"
20
#include "tuner-xc2028-types.h"
21

22 23 24
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"

25

26
#define PREFIX "xc2028"
27

28 29 30 31
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable verbose debug messages");

32 33 34 35 36 37 38 39 40 41 42 43 44 45
static char audio_std[8];
module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
MODULE_PARM_DESC(audio_std,
	"Audio standard. XC3028 audio decoder explicitly "
	"needs to know what audio\n"
	"standard is needed for some video standards with audio A2 or NICAM.\n"
	"The valid values are:\n"
	"A2\n"
	"A2/A\n"
	"A2/B\n"
	"NICAM\n"
	"NICAM/A\n"
	"NICAM/B\n");

46
static LIST_HEAD(xc2028_list);
47 48 49 50 51 52 53
/* struct for storing firmware table */
struct firmware_description {
	unsigned int  type;
	v4l2_std_id   id;
	unsigned char *ptr;
	unsigned int  size;
};
54 55

struct xc2028_data {
56 57 58 59 60 61
	struct list_head        xc2028_list;
	struct tuner_i2c_props  i2c_props;
	int                     (*tuner_callback) (void *dev,
						   int command, int arg);
	void			*video_dev;
	int			count;
62 63 64 65 66 67 68 69
	__u32			frequency;

	struct firmware_description *firm;
	int			firm_size;

	__u16			version;

	struct xc2028_ctrl	ctrl;
70

71 72 73 74 75 76
	v4l2_std_id		firm_type;	   /* video stds supported
							by current firmware */
	fe_bandwidth_t		bandwidth;	   /* Firmware bandwidth:
							      6M, 7M or 8M */
	int			need_load_generic; /* The generic firmware
							      were loaded? */
77 78 79

	int			max_len;	/* Max firmware chunk */

80 81
	enum tuner_mode	mode;
	struct i2c_client	*i2c_client;
82 83

	struct mutex lock;
84 85
};

86 87 88
#define i2c_send(rc, priv, buf, size) do {				\
	rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size);		\
	if (size != rc)							\
89
		tuner_err("i2c output error: rc = %d (should be %d)\n",	\
90 91 92 93 94 95
			   rc, (int)size);				\
} while (0)

#define i2c_rcv(rc, priv, buf, size) do {				\
	rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size);		\
	if (size != rc)							\
96
		tuner_err("i2c input error: rc = %d (should be %d)\n",	\
97 98 99 100 101
			   rc, (int)size); 				\
} while (0)

#define send_seq(priv, data...)	do {					\
	int rc;								\
102
	static u8 _val[] = data;					\
103
	if (sizeof(_val) !=						\
104
			(rc = tuner_i2c_xfer_send(&priv->i2c_props,	\
105
						_val, sizeof(_val)))) {	\
106
		tuner_err("Error on line %d: %d\n", __LINE__, rc);	\
107
		return -EINVAL;						\
108
	}								\
109 110
	msleep(10);							\
} while (0)
111

112
static unsigned int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
113 114
{
	int rc;
115
	unsigned char buf[2];
116

117
	tuner_dbg("%s called\n", __FUNCTION__);
118

119 120
	buf[0] = reg>>8;
	buf[1] = (unsigned char) reg;
121

122
	i2c_send(rc, priv, buf, 2);
123
	if (rc < 0)
124 125
		return rc;

126
	i2c_rcv(rc, priv, buf, 2);
127
	if (rc < 0)
128 129
		return rc;

130
	return (buf[1]) | (buf[0] << 8);
131 132
}

133 134 135 136
void dump_firm_type(unsigned int type)
{
	 if (type & BASE)
		printk("BASE ");
137 138
	 if (type & INIT1)
		printk("INIT1 ");
139 140 141 142 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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	 if (type & F8MHZ)
		printk("F8MHZ ");
	 if (type & MTS)
		printk("MTS ");
	 if (type & D2620)
		printk("D2620 ");
	 if (type & D2633)
		printk("D2633 ");
	 if (type & DTV6)
		printk("DTV6 ");
	 if (type & QAM)
		printk("QAM ");
	 if (type & DTV7)
		printk("DTV7 ");
	 if (type & DTV78)
		printk("DTV78 ");
	 if (type & DTV8)
		printk("DTV8 ");
	 if (type & FM)
		printk("FM ");
	 if (type & INPUT1)
		printk("INPUT1 ");
	 if (type & LCD)
		printk("LCD ");
	 if (type & NOGD)
		printk("NOGD ");
	 if (type & MONO)
		printk("MONO ");
	 if (type & ATSC)
		printk("ATSC ");
	 if (type & IF)
		printk("IF ");
	 if (type & LG60)
		printk("LG60 ");
	 if (type & ATI638)
		printk("ATI638 ");
	 if (type & OREN538)
		printk("OREN538 ");
	 if (type & OREN36)
		printk("OREN36 ");
	 if (type & TOYOTA388)
		printk("TOYOTA388 ");
	 if (type & TOYOTA794)
		printk("TOYOTA794 ");
	 if (type & DIBCOM52)
		printk("DIBCOM52 ");
	 if (type & ZARLINK456)
		printk("ZARLINK456 ");
	 if (type & CHINA)
		printk("CHINA ");
	 if (type & F6MHZ)
		printk("F6MHZ ");
	 if (type & INPUT2)
		printk("INPUT2 ");
	 if (type & SCODE)
		printk("SCODE ");
}

197
static  v4l2_std_id parse_audio_std_option(void)
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
{
	if (strcasecmp(audio_std, "A2"))
		return V4L2_STD_A2;
	if (strcasecmp(audio_std, "A2/A"))
		return V4L2_STD_A2_A;
	if (strcasecmp(audio_std, "A2/B"))
		return V4L2_STD_A2_B;
	if (strcasecmp(audio_std, "NICAM"))
		return V4L2_STD_NICAM;
	if (strcasecmp(audio_std, "NICAM/A"))
		return V4L2_STD_NICAM_A;
	if (strcasecmp(audio_std, "NICAM/B"))
		return V4L2_STD_NICAM_B;

	return 0;
}

215
static void free_firmware(struct xc2028_data *priv)
216
{
217 218 219 220 221
	int i;

	if (!priv->firm)
		return;

222 223 224
	for (i = 0; i < priv->firm_size; i++)
		kfree(priv->firm[i].ptr);

225 226
	kfree(priv->firm);

227
	priv->firm = NULL;
228 229 230
	priv->need_load_generic = 1;
}

231
static int load_all_firmwares(struct dvb_frontend *fe)
232 233
{
	struct xc2028_data    *priv = fe->tuner_priv;
234
	const struct firmware *fw   = NULL;
235
	unsigned char         *p, *endp;
236 237
	int                   rc = 0;
	int		      n, n_array;
238
	char		      name[33];
239

240
	tuner_dbg("%s called\n", __FUNCTION__);
241

242
	tuner_info("Reading firmware %s\n", priv->ctrl.fname);
243 244
	rc = request_firmware(&fw, priv->ctrl.fname,
			      &priv->i2c_props.adap->dev);
245
	if (rc < 0) {
246
		if (rc == -ENOENT)
247
			tuner_err("Error: firmware %s not found.\n",
248
				   priv->ctrl.fname);
249
		else
250
			tuner_err("Error %d while requesting firmware %s \n",
251
				   rc, priv->ctrl.fname);
252

253 254
		return rc;
	}
255 256
	p = fw->data;
	endp = p + fw->size;
257

258
	if (fw->size < sizeof(name) - 1 + 2) {
259
		tuner_err("Error: firmware size is zero!\n");
260
		rc = -EINVAL;
261
		goto done;
262
	}
263

264 265 266
	memcpy(name, p, sizeof(name) - 1);
	name[sizeof(name) - 1] = 0;
	p += sizeof(name) - 1;
267

268
	priv->version = le16_to_cpu(*(__u16 *) p);
269 270
	p += 2;

271
	tuner_info("Firmware: %s, ver %d.%d\n", name,
272
		   priv->version >> 8, priv->version & 0xff);
273

274
	if (p + 2 > endp)
275 276
		goto corrupt;

277
	n_array = le16_to_cpu(*(__u16 *) p);
278 279
	p += 2;

280 281
	tuner_info("There are %d firmwares at %s\n",
		   n_array, priv->ctrl.fname);
282

283
	priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
284 285

	if (!fw) {
286
		tuner_err("Not enough memory for reading firmware.\n");
287
		rc = -ENOMEM;
288
		goto done;
289 290
	}

291
	priv->firm_size = n_array;
292 293
	n = -1;
	while (p < endp) {
294 295 296 297 298
		__u32 type, size;
		v4l2_std_id id;

		n++;
		if (n >= n_array) {
299
			tuner_err("Too much firmwares at the file\n");
300 301 302 303
			goto corrupt;
		}

		/* Checks if there's enough bytes to read */
304
		if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
305
			tuner_err("Firmware header is incomplete!\n");
306 307 308
			goto corrupt;
		}

309
		type = le32_to_cpu(*(__u32 *) p);
310 311
		p += sizeof(type);

312
		id = le64_to_cpu(*(v4l2_std_id *) p);
313 314
		p += sizeof(id);

315
		size = le32_to_cpu(*(__u32 *) p);
316 317
		p += sizeof(size);

318
		if ((!size) || (size + p > endp)) {
319
			tuner_err("Firmware type ");
320
			dump_firm_type(type);
321 322 323 324
			printk("(%x), id %llx is corrupted "
			       "(size=%d, expected %d)\n",
			       type, id,
			       (unsigned)(endp - p), size);
325 326 327
			goto corrupt;
		}

328
		priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
329
		if (!priv->firm[n].ptr) {
330
			tuner_err("Not enough memory.\n");
331
			rc = -ENOMEM;
332 333
			goto err;
		}
334
		tuner_info("Reading firmware type ");
335 336
		dump_firm_type(type);
		printk("(%x), id %lx, size=%d.\n",
337
			   type, (unsigned long)id, size);
338 339 340 341 342 343 344 345 346

		memcpy(priv->firm[n].ptr, p, size);
		priv->firm[n].type = type;
		priv->firm[n].id   = id;
		priv->firm[n].size = size;

		p += size;
	}

347
	if (n + 1 != priv->firm_size) {
348
		tuner_err("Firmware file is incomplete!\n");
349 350 351 352 353 354
		goto corrupt;
	}

	goto done;

corrupt:
355
	rc = -EINVAL;
356
	tuner_err("Error: firmware file is corrupted!\n");
357 358 359 360 361 362 363 364

err:
	tuner_info("Releasing loaded firmware file.\n");

	free_firmware(priv);

done:
	release_firmware(fw);
365
	tuner_dbg("Firmware files loaded.\n");
366 367 368 369

	return rc;
}

370 371
static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
			 v4l2_std_id *id)
372 373
{
	struct xc2028_data *priv = fe->tuner_priv;
374
	int                i;
375

376
	tuner_dbg("%s called\n", __FUNCTION__);
377 378

	if (!priv->firm) {
379
		tuner_err("Error! firmware not loaded\n");
380 381 382
		return -EINVAL;
	}

383
	if (((type & ~SCODE) == 0) && (*id == 0))
384
		*id = V4L2_STD_PAL;
385 386

	/* Seek for exact match */
387 388
	for (i = 0; i < priv->firm_size; i++) {
		if ((type == priv->firm[i].type) && (*id == priv->firm[i].id))
389 390 391 392
			goto found;
	}

	/* Seek for generic video standard match */
393 394
	for (i = 0; i < priv->firm_size; i++) {
		if ((type == priv->firm[i].type) && (*id & priv->firm[i].id))
395 396 397 398 399
			goto found;
	}

	/*FIXME: Would make sense to seek for type "hint" match ? */

400 401
	i = -EINVAL;
	goto ret;
402 403 404 405

found:
	*id = priv->firm[i].id;

406
ret:
407 408 409 410 411
	tuner_dbg("%s firmware for type=", (i < 0)? "Can't find": "Found");
	if (debug) {
		dump_firm_type(type);
		printk("(%x), id %08lx.\n", type, (unsigned long)*id);
	}
412 413 414 415 416 417 418 419 420 421
	return i;
}

static int load_firmware(struct dvb_frontend *fe, unsigned int type,
			 v4l2_std_id *id)
{
	struct xc2028_data *priv = fe->tuner_priv;
	int                pos, rc;
	unsigned char      *p, *endp, buf[priv->max_len];

422
	tuner_dbg("%s called\n", __FUNCTION__);
423 424 425 426 427

	pos = seek_firmware(fe, type, id);
	if (pos < 0)
		return pos;

428 429 430 431
	tuner_info("Loading firmware for type=");
	dump_firm_type(type);
	printk("(%x), id %08lx.\n", type, (unsigned long)*id);

432
	p = priv->firm[pos].ptr;
433 434

	if (!p) {
435
		tuner_err("Firmware pointer were freed!");
436
		return -EINVAL;
437
	}
438
	endp = p + priv->firm[pos].size;
439

440
	while (p < endp) {
441 442 443
		__u16 size;

		/* Checks if there's enough bytes to read */
444
		if (p + sizeof(size) > endp) {
445
			tuner_err("Firmware chunk size is wrong\n");
446 447 448
			return -EINVAL;
		}

449
		size = le16_to_cpu(*(__u16 *) p);
450 451 452 453 454 455
		p += sizeof(size);

		if (size == 0xffff)
			return 0;

		if (!size) {
456
			/* Special callback command received */
457
			rc = priv->tuner_callback(priv->video_dev,
458 459
						  XC2028_TUNER_RESET, 0);
			if (rc < 0) {
460
				tuner_err("Error at RESET code %d\n",
461
					   (*p) & 0x7f);
462
				return -EINVAL;
463 464 465
			}
			continue;
		}
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
		if (size >= 0xff00) {
			switch (size) {
			case 0xff00:
				rc = priv->tuner_callback(priv->video_dev,
							XC2028_RESET_CLK, 0);
				if (rc < 0) {
					tuner_err("Error at RESET code %d\n",
						  (*p) & 0x7f);
					return -EINVAL;
				}
			default:
				tuner_info("Invalid RESET code %d\n",
					   size & 0x7f);
				return -EINVAL;

			}
482
			continue;
483
		}
484 485 486

		/* Checks for a sleep command */
		if (size & 0x8000) {
487
			msleep(size & 0x7fff);
488
			continue;
489 490
		}

491
		if ((size + p > endp)) {
492
			tuner_err("missing bytes: need %d, have %d\n",
493
				   size, (int)(endp - p));
494 495
			return -EINVAL;
		}
496

497
		buf[0] = *p;
498
		p++;
499
		size--;
500

501
		/* Sends message chunks */
502 503 504
		while (size > 0) {
			int len = (size < priv->max_len - 1) ?
				   size : priv->max_len - 1;
505

506
			memcpy(buf + 1, p, len);
507

508 509
			i2c_send(rc, priv, buf, len + 1);
			if (rc < 0) {
510
				tuner_err("%d returned from send\n", rc);
511 512 513 514 515 516 517
				return -EINVAL;
			}

			p += len;
			size -= len;
		}
	}
518
	return 0;
519 520
}

521 522 523 524 525 526 527
static int load_scode(struct dvb_frontend *fe, unsigned int type,
			 v4l2_std_id *id, int scode)
{
	struct xc2028_data *priv = fe->tuner_priv;
	int                pos, rc;
	unsigned char	   *p;

528
	tuner_dbg("%s called\n", __FUNCTION__);
529 530 531 532 533 534 535 536

	pos = seek_firmware(fe, type, id);
	if (pos < 0)
		return pos;

	p = priv->firm[pos].ptr;

	if (!p) {
537
		tuner_err("Firmware pointer were freed!");
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
		return -EINVAL;
	}

	if ((priv->firm[pos].size != 12 * 16) || (scode >= 16))
		return -EINVAL;

	if (priv->version < 0x0202) {
		send_seq(priv, {0x20, 0x00, 0x00, 0x00});
	} else {
		send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
	}

	i2c_send(rc, priv, p + 12 * scode, 12);

	send_seq(priv, {0x00, 0x8c});

	return 0;
}

557
static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
558
			  v4l2_std_id std, fe_bandwidth_t bandwidth)
559
{
560
	struct xc2028_data      *priv = fe->tuner_priv;
561
	int			rc, version, hwmodel;
562 563
	v4l2_std_id		std0 = 0;
	unsigned int		type0 = 0, type = 0;
564
	int			change_digital_bandwidth;
565

566
	tuner_dbg("%s called\n", __FUNCTION__);
567

568
	if (!priv->firm) {
569 570
		if (!priv->ctrl.fname) {
			tuner_info("xc2028/3028 firmware name not set!\n");
571
			return -EINVAL;
572
		}
573

574 575
		rc = load_all_firmwares(fe);
		if (rc < 0)
576 577 578
			return rc;
	}

579
	tuner_dbg("I am in mode %u and I should switch to mode %i\n",
580
		   priv->mode, new_mode);
581 582

	/* first of all, determine whether we have switched the mode */
583
	if (new_mode != priv->mode) {
584 585
		priv->mode = new_mode;
		priv->need_load_generic = 1;
586 587
	}

588
	change_digital_bandwidth = (priv->mode == T_DIGITAL_TV
589
				    && bandwidth != priv->bandwidth) ? 1 : 0;
590
	tuner_dbg("old bandwidth %u, new bandwidth %u\n", priv->bandwidth,
591
		   bandwidth);
592

593
	if (priv->need_load_generic) {
594
		/* Reset is needed before loading firmware */
595 596
		rc = priv->tuner_callback(priv->video_dev,
					  XC2028_TUNER_RESET, 0);
597
		if (rc < 0)
598 599
			return rc;

600
		type0 = BASE;
601 602 603 604

		if (priv->ctrl.type == XC2028_FIRM_MTS)
			type0 |= MTS;

605
		if (priv->bandwidth == 8)
606 607 608 609 610
			type0 |= F8MHZ;

		/* FIXME: How to load FM and FM|INPUT1 firmwares? */

		rc = load_firmware(fe, type0, &std0);
611
		if (rc < 0) {
612 613
			tuner_err("Error %d while loading generic firmware\n",
				  rc);
614
			return rc;
615
		}
616

617 618 619 620
		priv->need_load_generic = 0;
		priv->firm_type = 0;
		if (priv->mode == T_DIGITAL_TV)
			change_digital_bandwidth = 1;
621 622
	}

623
	tuner_dbg("I should change bandwidth %u\n", change_digital_bandwidth);
624 625

	if (change_digital_bandwidth) {
626 627 628 629 630 631

		/*FIXME: Should allow selecting between D2620 and D2633 */
		type |= D2620;

		/* FIXME: When should select a DTV78 firmware?
		 */
632
		switch (bandwidth) {
633 634
		case BANDWIDTH_8_MHZ:
			type |= DTV8;
635
			break;
636 637
		case BANDWIDTH_7_MHZ:
			type |= DTV7;
638
			break;
639 640
		case BANDWIDTH_6_MHZ:
			/* FIXME: Should allow select also ATSC */
641
			type |= DTV6 | QAM;
642 643
			break;

644
		default:
645
			tuner_err("error: bandwidth not supported.\n");
646
		};
647
		priv->bandwidth = bandwidth;
648 649
	}

650 651 652
	if (!change_digital_bandwidth && priv->mode == T_DIGITAL_TV)
		return 0;

653
	/* Load INIT1, if needed */
654
	tuner_dbg("Load init1 firmware, if exists\n");
655
	type0 = BASE | INIT1;
656 657 658 659 660 661 662 663 664 665 666 667
	if (priv->ctrl.type == XC2028_FIRM_MTS)
		type0 |= MTS;

	/* FIXME: Should handle errors - if INIT1 found */
	rc = load_firmware(fe, type0, &std0);

	/* FIXME: Should add support for FM radio
	 */

	if (priv->ctrl.type == XC2028_FIRM_MTS)
		type |= MTS;

668
	if (priv->firm_type & std) {
669
		tuner_dbg("Std-specific firmware already loaded.\n");
670
		return 0;
671
	}
672

673 674 675
	/* Add audio hack to std mask */
	std |= parse_audio_std_option();

676
	rc = load_firmware(fe, type, &std);
677
	if (rc < 0)
678 679
		return rc;

680
	/* Load SCODE firmware, if exists */
681
	tuner_dbg("Trying to load scode 0\n");
682 683 684
	type |= SCODE;

	rc = load_scode(fe, type, &std, 0);
685

686 687 688 689 690 691 692
	version = xc2028_get_reg(priv, 0x0004);
	hwmodel = xc2028_get_reg(priv, 0x0008);

	tuner_info("Device is Xceive %d version %d.%d, "
		   "firmware version %d.%d\n",
		   hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
		   (version & 0xf0) >> 4, version & 0xf);
693

694
	priv->firm_type = std;
695 696 697 698

	return 0;
}

699
static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
700
{
701
	struct xc2028_data *priv = fe->tuner_priv;
702
	int                frq_lock, signal = 0;
703

704
	tuner_dbg("%s called\n", __FUNCTION__);
705

706
	mutex_lock(&priv->lock);
707

708 709
	*strength = 0;

710 711
	/* Sync Lock Indicator */
	frq_lock = xc2028_get_reg(priv, 0x0002);
712
	if (frq_lock <= 0)
713
		goto ret;
714 715 716

	/* Frequency is locked. Return signal quality */

717 718
	/* Get SNR of the video signal */
	signal = xc2028_get_reg(priv, 0x0040);
719

720 721
	if (signal <= 0)
		signal = frq_lock;
722 723

ret:
724 725 726
	mutex_unlock(&priv->lock);

	*strength = signal;
727

728
	return 0;
729 730 731 732
}

#define DIV 15625

733 734 735
static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */ ,
			       enum tuner_mode new_mode,
			       v4l2_std_id std, fe_bandwidth_t bandwidth)
736
{
737
	struct xc2028_data *priv = fe->tuner_priv;
738 739 740
	int		   rc = -EINVAL;
	unsigned char	   buf[5];
	u32		   div, offset = 0;
741

742
	tuner_dbg("%s called\n", __FUNCTION__);
743

744 745
	mutex_lock(&priv->lock);

746 747
	/* HACK: It seems that specific firmware need to be reloaded
	   when freq is changed */
748

749
	priv->firm_type = 0;
750

751
	/* Reset GPIO 1 */
752
	rc = priv->tuner_callback(priv->video_dev, XC2028_TUNER_RESET, 0);
753
	if (rc < 0)
754 755
		goto ret;

756
	msleep(10);
757
	tuner_dbg("should set frequency %d kHz)\n", freq / 1000);
758

759
	if (check_firmware(fe, new_mode, std, bandwidth) < 0)
760
		goto ret;
761

762
	if (new_mode == T_DIGITAL_TV)
763
		offset = 2750000;
764

765
	div = (freq - offset + DIV / 2) / DIV;
766

767
	/* CMD= Set frequency */
768

769
	if (priv->version < 0x0202) {
770 771 772 773 774
		send_seq(priv, {0x00, 0x02, 0x00, 0x00});
	} else {
		send_seq(priv, {0x80, 0x02, 0x00, 0x00});
	}

775
	rc = priv->tuner_callback(priv->video_dev, XC2028_RESET_CLK, 1);
776
	if (rc < 0)
777
		goto ret;
778 779

	msleep(10);
780

781 782 783 784 785
	buf[0] = 0xff & (div >> 24);
	buf[1] = 0xff & (div >> 16);
	buf[2] = 0xff & (div >> 8);
	buf[3] = 0xff & (div);
	buf[4] = 0;
786

787
	i2c_send(rc, priv, buf, sizeof(buf));
788
	if (rc < 0)
789
		goto ret;
790 791
	msleep(100);

792
	priv->frequency = freq;
793

794
	tuner_dbg("divider= %02x %02x %02x %02x (freq=%d.%02d)\n",
795 796
	       buf[1], buf[2], buf[3], buf[4],
	       freq / 1000000, (freq % 1000000) / 10000);
797

798
	rc = 0;
799

800 801
ret:
	mutex_unlock(&priv->lock);
802

803
	return rc;
804 805
}

806
static int xc2028_set_tv_freq(struct dvb_frontend *fe,
807
			      struct analog_parameters *p)
808
{
809
	struct xc2028_data *priv = fe->tuner_priv;
810

811
	tuner_dbg("%s called\n", __FUNCTION__);
812

813 814
	return generic_set_tv_freq(fe, 62500l * p->frequency, T_ANALOG_TV,
				   p->std, BANDWIDTH_8_MHZ /* NOT USED */);
815
}
816

817 818
static int xc2028_set_params(struct dvb_frontend *fe,
			     struct dvb_frontend_parameters *p)
819
{
820
	struct xc2028_data *priv = fe->tuner_priv;
821

822
	tuner_dbg("%s called\n", __FUNCTION__);
823

824 825
	/* FIXME: Only OFDM implemented */
	if (fe->ops.info.type != FE_OFDM) {
826
		tuner_err("DTV type not implemented.\n");
827
		return -EINVAL;
828 829
	}

830
	return generic_set_tv_freq(fe, p->frequency, T_DIGITAL_TV,
831 832
				   0 /* NOT USED */,
				   p->u.ofdm.bandwidth);
833 834

}
835

836
static int xc2028_dvb_release(struct dvb_frontend *fe)
837
{
838 839
	struct xc2028_data *priv = fe->tuner_priv;

840
	tuner_dbg("%s called\n", __FUNCTION__);
841

842
	priv->count--;
843

844
	if (!priv->count) {
845 846
		list_del(&priv->xc2028_list);

847
		kfree(priv->ctrl.fname);
848 849

		free_firmware(priv);
850
		kfree(priv);
851
	}
852 853 854 855

	return 0;
}

856
static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
857
{
858
	struct xc2028_data *priv = fe->tuner_priv;
859

860
	tuner_dbg("%s called\n", __FUNCTION__);
861

862
	*frequency = priv->frequency;
863 864 865 866

	return 0;
}

867
static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
868 869 870 871
{
	struct xc2028_data *priv = fe->tuner_priv;
	struct xc2028_ctrl *p    = priv_cfg;

872
	tuner_dbg("%s called\n", __FUNCTION__);
873 874 875 876

	priv->ctrl.type = p->type;

	if (p->fname) {
877
		kfree(priv->ctrl.fname);
878

879
		priv->ctrl.fname = kmalloc(strlen(p->fname) + 1, GFP_KERNEL);
880 881 882 883 884 885 886
		if (!priv->ctrl.fname)
			return -ENOMEM;

		free_firmware(priv);
		strcpy(priv->ctrl.fname, p->fname);
	}

887
	if (p->max_len > 0)
888 889
		priv->max_len = p->max_len;

890 891 892
	return 0;
}

893
static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
894
	.info = {
895 896 897 898 899
		 .name = "Xceive XC3028",
		 .frequency_min = 42000000,
		 .frequency_max = 864000000,
		 .frequency_step = 50000,
		 },
900

901
	.set_config	   = xc2028_set_config,
902 903 904 905 906
	.set_analog_params = xc2028_set_tv_freq,
	.release           = xc2028_dvb_release,
	.get_frequency     = xc2028_get_frequency,
	.get_rf_strength   = xc2028_signal,
	.set_params        = xc2028_set_params,
907 908 909

};

910
void *xc2028_attach(struct dvb_frontend *fe, struct xc2028_config *cfg)
911
{
912
	struct xc2028_data *priv;
913
	void               *video_dev;
914

915 916
	if (debug)
		printk(KERN_DEBUG PREFIX "Xcv2028/3028 init called!\n");
917

918 919
	if (NULL == cfg->video_dev)
		return NULL;
920

921 922 923
	if (!fe) {
		printk(KERN_ERR PREFIX "No frontend!\n");
		return NULL;
924 925
	}

926 927
	video_dev = cfg->video_dev;

928
	list_for_each_entry(priv, &xc2028_list, xc2028_list) {
929 930 931 932
		if (priv->video_dev == cfg->video_dev) {
			video_dev = NULL;
			break;
		}
933 934
	}

935
	if (video_dev) {
936 937
		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
		if (priv == NULL)
938
			return NULL;
939

940 941
		priv->bandwidth = BANDWIDTH_6_MHZ;
		priv->need_load_generic = 1;
942
		priv->mode = T_UNINITIALIZED;
943 944
		priv->i2c_props.addr = cfg->i2c_addr;
		priv->i2c_props.adap = cfg->i2c_adap;
945
		priv->video_dev = video_dev;
946
		priv->tuner_callback = cfg->callback;
947 948
		priv->max_len = 13;

949 950
		mutex_init(&priv->lock);

951
		list_add_tail(&priv->xc2028_list, &xc2028_list);
952
	}
953 954

	fe->tuner_priv = priv;
955
	priv->count++;
956 957

	memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
958
	       sizeof(xc2028_dvb_tuner_ops));
959 960 961

	tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");

962
	return fe;
963
}
964

965 966
EXPORT_SYMBOL(xc2028_attach);

967
MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
968
MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
969 970
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_LICENSE("GPL");