brintos

brintos / linux-shallow public Read only

0
0
Text · 55.5 KiB · b9a7590 Raw
2407 lines · c
1// SPDX-License-Identifier: GPL-2.02// Rafael Micro R820T driver3//4// Copyright (C) 2013 Mauro Carvalho Chehab5//6// This driver was written from scratch, based on an existing driver7// that it is part of rtl-sdr git tree, released under GPLv2:8//	https://groups.google.com/forum/#!topic/ultra-cheap-sdr/Y3rBEOFtHug9//	https://github.com/n1gp/gr-baz10//11// From what I understood from the threads, the original driver was converted12// to userspace from a Realtek tree. I couldn't find the original tree.13// However, the original driver look awkward on my eyes. So, I decided to14// write a new version from it from the scratch, while trying to reproduce15// everything found there.16//17// TODO:18//	After locking, the original driver seems to have some routines to19//		improve reception. This was not implemented here yet.20//21//	RF Gain set/get is not implemented.22 23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt24 25#include <linux/videodev2.h>26#include <linux/mutex.h>27#include <linux/slab.h>28#include <linux/bitrev.h>29 30#include "tuner-i2c.h"31#include "r820t.h"32 33/*34 * FIXME: I think that there are only 32 registers, but better safe than35 *	  sorry. After finishing the driver, we may review it.36 */37#define REG_SHADOW_START	538#define NUM_REGS		2739#define NUM_IMR			540#define IMR_TRIAL		941 42#define VER_NUM  4943 44static int debug;45module_param(debug, int, 0644);46MODULE_PARM_DESC(debug, "enable verbose debug messages");47 48static int no_imr_cal;49module_param(no_imr_cal, int, 0444);50MODULE_PARM_DESC(no_imr_cal, "Disable IMR calibration at module init");51 52 53/*54 * enums and structures55 */56 57enum xtal_cap_value {58	XTAL_LOW_CAP_30P = 0,59	XTAL_LOW_CAP_20P,60	XTAL_LOW_CAP_10P,61	XTAL_LOW_CAP_0P,62	XTAL_HIGH_CAP_0P63};64 65struct r820t_sect_type {66	u8	phase_y;67	u8	gain_x;68	u16	value;69};70 71struct r820t_priv {72	struct list_head		hybrid_tuner_instance_list;73	const struct r820t_config	*cfg;74	struct tuner_i2c_props		i2c_props;75	struct mutex			lock;76 77	u8				regs[NUM_REGS];78	u8				buf[NUM_REGS + 1];79	enum xtal_cap_value		xtal_cap_sel;80	u16				pll;	/* kHz */81	u32				int_freq;82	u8				fil_cal_code;83	bool				imr_done;84	bool				has_lock;85	bool				init_done;86	struct r820t_sect_type		imr_data[NUM_IMR];87 88	/* Store current mode */89	u32				delsys;90	enum v4l2_tuner_type		type;91	v4l2_std_id			std;92	u32				bw;	/* in MHz */93};94 95struct r820t_freq_range {96	u32	freq;97	u8	open_d;98	u8	rf_mux_ploy;99	u8	tf_c;100	u8	xtal_cap20p;101	u8	xtal_cap10p;102	u8	xtal_cap0p;103	u8	imr_mem;		/* Not used, currently */104};105 106#define VCO_POWER_REF   0x02107#define DIP_FREQ	32000000108 109/*110 * Static constants111 */112 113static LIST_HEAD(hybrid_tuner_instance_list);114static DEFINE_MUTEX(r820t_list_mutex);115 116/* Those initial values start from REG_SHADOW_START */117static const u8 r820t_init_array[NUM_REGS] = {118	0x83, 0x32, 0x75,			/* 05 to 07 */119	0xc0, 0x40, 0xd6, 0x6c,			/* 08 to 0b */120	0xf5, 0x63, 0x75, 0x68,			/* 0c to 0f */121	0x6c, 0x83, 0x80, 0x00,			/* 10 to 13 */122	0x0f, 0x00, 0xc0, 0x30,			/* 14 to 17 */123	0x48, 0xcc, 0x60, 0x00,			/* 18 to 1b */124	0x54, 0xae, 0x4a, 0xc0			/* 1c to 1f */125};126 127/* Tuner frequency ranges */128static const struct r820t_freq_range freq_ranges[] = {129	{130		.freq = 0,131		.open_d = 0x08,		/* low */132		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */133		.tf_c = 0xdf,		/* R27[7:0]  band2,band0 */134		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */135		.xtal_cap10p = 0x01,136		.xtal_cap0p = 0x00,137		.imr_mem = 0,138	}, {139		.freq = 50,		/* Start freq, in MHz */140		.open_d = 0x08,		/* low */141		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */142		.tf_c = 0xbe,		/* R27[7:0]  band4,band1  */143		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */144		.xtal_cap10p = 0x01,145		.xtal_cap0p = 0x00,146		.imr_mem = 0,147	}, {148		.freq = 55,		/* Start freq, in MHz */149		.open_d = 0x08,		/* low */150		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */151		.tf_c = 0x8b,		/* R27[7:0]  band7,band4 */152		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */153		.xtal_cap10p = 0x01,154		.xtal_cap0p = 0x00,155		.imr_mem = 0,156	}, {157		.freq = 60,		/* Start freq, in MHz */158		.open_d = 0x08,		/* low */159		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */160		.tf_c = 0x7b,		/* R27[7:0]  band8,band4 */161		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */162		.xtal_cap10p = 0x01,163		.xtal_cap0p = 0x00,164		.imr_mem = 0,165	}, {166		.freq = 65,		/* Start freq, in MHz */167		.open_d = 0x08,		/* low */168		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */169		.tf_c = 0x69,		/* R27[7:0]  band9,band6 */170		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */171		.xtal_cap10p = 0x01,172		.xtal_cap0p = 0x00,173		.imr_mem = 0,174	}, {175		.freq = 70,		/* Start freq, in MHz */176		.open_d = 0x08,		/* low */177		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */178		.tf_c = 0x58,		/* R27[7:0]  band10,band7 */179		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */180		.xtal_cap10p = 0x01,181		.xtal_cap0p = 0x00,182		.imr_mem = 0,183	}, {184		.freq = 75,		/* Start freq, in MHz */185		.open_d = 0x00,		/* high */186		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */187		.tf_c = 0x44,		/* R27[7:0]  band11,band11 */188		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */189		.xtal_cap10p = 0x01,190		.xtal_cap0p = 0x00,191		.imr_mem = 0,192	}, {193		.freq = 80,		/* Start freq, in MHz */194		.open_d = 0x00,		/* high */195		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */196		.tf_c = 0x44,		/* R27[7:0]  band11,band11 */197		.xtal_cap20p = 0x02,	/* R16[1:0]  20pF (10)   */198		.xtal_cap10p = 0x01,199		.xtal_cap0p = 0x00,200		.imr_mem = 0,201	}, {202		.freq = 90,		/* Start freq, in MHz */203		.open_d = 0x00,		/* high */204		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */205		.tf_c = 0x34,		/* R27[7:0]  band12,band11 */206		.xtal_cap20p = 0x01,	/* R16[1:0]  10pF (01)   */207		.xtal_cap10p = 0x01,208		.xtal_cap0p = 0x00,209		.imr_mem = 0,210	}, {211		.freq = 100,		/* Start freq, in MHz */212		.open_d = 0x00,		/* high */213		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */214		.tf_c = 0x34,		/* R27[7:0]  band12,band11 */215		.xtal_cap20p = 0x01,	/* R16[1:0]  10pF (01)    */216		.xtal_cap10p = 0x01,217		.xtal_cap0p = 0x00,218		.imr_mem = 0,219	}, {220		.freq = 110,		/* Start freq, in MHz */221		.open_d = 0x00,		/* high */222		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */223		.tf_c = 0x24,		/* R27[7:0]  band13,band11 */224		.xtal_cap20p = 0x01,	/* R16[1:0]  10pF (01)   */225		.xtal_cap10p = 0x01,226		.xtal_cap0p = 0x00,227		.imr_mem = 1,228	}, {229		.freq = 120,		/* Start freq, in MHz */230		.open_d = 0x00,		/* high */231		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */232		.tf_c = 0x24,		/* R27[7:0]  band13,band11 */233		.xtal_cap20p = 0x01,	/* R16[1:0]  10pF (01)   */234		.xtal_cap10p = 0x01,235		.xtal_cap0p = 0x00,236		.imr_mem = 1,237	}, {238		.freq = 140,		/* Start freq, in MHz */239		.open_d = 0x00,		/* high */240		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */241		.tf_c = 0x14,		/* R27[7:0]  band14,band11 */242		.xtal_cap20p = 0x01,	/* R16[1:0]  10pF (01)   */243		.xtal_cap10p = 0x01,244		.xtal_cap0p = 0x00,245		.imr_mem = 1,246	}, {247		.freq = 180,		/* Start freq, in MHz */248		.open_d = 0x00,		/* high */249		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */250		.tf_c = 0x13,		/* R27[7:0]  band14,band12 */251		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */252		.xtal_cap10p = 0x00,253		.xtal_cap0p = 0x00,254		.imr_mem = 1,255	}, {256		.freq = 220,		/* Start freq, in MHz */257		.open_d = 0x00,		/* high */258		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */259		.tf_c = 0x13,		/* R27[7:0]  band14,band12 */260		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */261		.xtal_cap10p = 0x00,262		.xtal_cap0p = 0x00,263		.imr_mem = 2,264	}, {265		.freq = 250,		/* Start freq, in MHz */266		.open_d = 0x00,		/* high */267		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */268		.tf_c = 0x11,		/* R27[7:0]  highest,highest */269		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */270		.xtal_cap10p = 0x00,271		.xtal_cap0p = 0x00,272		.imr_mem = 2,273	}, {274		.freq = 280,		/* Start freq, in MHz */275		.open_d = 0x00,		/* high */276		.rf_mux_ploy = 0x02,	/* R26[7:6]=0 (LPF)  R26[1:0]=2 (low) */277		.tf_c = 0x00,		/* R27[7:0]  highest,highest */278		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */279		.xtal_cap10p = 0x00,280		.xtal_cap0p = 0x00,281		.imr_mem = 2,282	}, {283		.freq = 310,		/* Start freq, in MHz */284		.open_d = 0x00,		/* high */285		.rf_mux_ploy = 0x41,	/* R26[7:6]=1 (bypass)  R26[1:0]=1 (middle) */286		.tf_c = 0x00,		/* R27[7:0]  highest,highest */287		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */288		.xtal_cap10p = 0x00,289		.xtal_cap0p = 0x00,290		.imr_mem = 2,291	}, {292		.freq = 450,		/* Start freq, in MHz */293		.open_d = 0x00,		/* high */294		.rf_mux_ploy = 0x41,	/* R26[7:6]=1 (bypass)  R26[1:0]=1 (middle) */295		.tf_c = 0x00,		/* R27[7:0]  highest,highest */296		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */297		.xtal_cap10p = 0x00,298		.xtal_cap0p = 0x00,299		.imr_mem = 3,300	}, {301		.freq = 588,		/* Start freq, in MHz */302		.open_d = 0x00,		/* high */303		.rf_mux_ploy = 0x40,	/* R26[7:6]=1 (bypass)  R26[1:0]=0 (highest) */304		.tf_c = 0x00,		/* R27[7:0]  highest,highest */305		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */306		.xtal_cap10p = 0x00,307		.xtal_cap0p = 0x00,308		.imr_mem = 3,309	}, {310		.freq = 650,		/* Start freq, in MHz */311		.open_d = 0x00,		/* high */312		.rf_mux_ploy = 0x40,	/* R26[7:6]=1 (bypass)  R26[1:0]=0 (highest) */313		.tf_c = 0x00,		/* R27[7:0]  highest,highest */314		.xtal_cap20p = 0x00,	/* R16[1:0]  0pF (00)   */315		.xtal_cap10p = 0x00,316		.xtal_cap0p = 0x00,317		.imr_mem = 4,318	}319};320 321static int r820t_xtal_capacitor[][2] = {322	{ 0x0b, XTAL_LOW_CAP_30P },323	{ 0x02, XTAL_LOW_CAP_20P },324	{ 0x01, XTAL_LOW_CAP_10P },325	{ 0x00, XTAL_LOW_CAP_0P  },326	{ 0x10, XTAL_HIGH_CAP_0P },327};328 329static const char *r820t_chip_enum_to_str(enum r820t_chip chip)330{331	switch (chip) {332	case CHIP_R820T:333		return "R820T";334	case CHIP_R620D:335		return "R620D";336	case CHIP_R828D:337		return "R828D";338	case CHIP_R828:339		return "R828";340	case CHIP_R828S:341		return "R828S";342	case CHIP_R820C:343		return "R820C";344	default:345		return "<unknown>";346	}347}348 349/*350 * I2C read/write code and shadow registers logic351 */352static void shadow_store(struct r820t_priv *priv, u8 reg, const u8 *val,353			 int len)354{355	int r = reg - REG_SHADOW_START;356 357	if (r < 0) {358		len += r;359		r = 0;360	}361	if (len <= 0)362		return;363	if (len > NUM_REGS - r)364		len = NUM_REGS - r;365 366	tuner_dbg("%s: prev  reg=%02x len=%d: %*ph\n",367		  __func__, r + REG_SHADOW_START, len, len, val);368 369	memcpy(&priv->regs[r], val, len);370}371 372static int r820t_write(struct r820t_priv *priv, u8 reg, const u8 *val,373		       int len)374{375	int rc, size, pos = 0;376 377	/* Store the shadow registers */378	shadow_store(priv, reg, val, len);379 380	do {381		if (len > priv->cfg->max_i2c_msg_len - 1)382			size = priv->cfg->max_i2c_msg_len - 1;383		else384			size = len;385 386		/* Fill I2C buffer */387		priv->buf[0] = reg;388		memcpy(&priv->buf[1], &val[pos], size);389 390		rc = tuner_i2c_xfer_send(&priv->i2c_props, priv->buf, size + 1);391		if (rc != size + 1) {392			tuner_info("%s: i2c wr failed=%d reg=%02x len=%d: %*ph\n",393				   __func__, rc, reg, size, size, &priv->buf[1]);394			if (rc < 0)395				return rc;396			return -EREMOTEIO;397		}398		tuner_dbg("%s: i2c wr reg=%02x len=%d: %*ph\n",399			  __func__, reg, size, size, &priv->buf[1]);400 401		reg += size;402		len -= size;403		pos += size;404	} while (len > 0);405 406	return 0;407}408 409static inline int r820t_write_reg(struct r820t_priv *priv, u8 reg, u8 val)410{411	u8 tmp = val; /* work around GCC PR81715 with asan-stack=1 */412 413	return r820t_write(priv, reg, &tmp, 1);414}415 416static int r820t_read_cache_reg(struct r820t_priv *priv, int reg)417{418	reg -= REG_SHADOW_START;419 420	if (reg >= 0 && reg < NUM_REGS)421		return priv->regs[reg];422	else423		return -EINVAL;424}425 426static inline int r820t_write_reg_mask(struct r820t_priv *priv, u8 reg, u8 val,427				u8 bit_mask)428{429	u8 tmp = val;430	int rc = r820t_read_cache_reg(priv, reg);431 432	if (rc < 0)433		return rc;434 435	tmp = (rc & ~bit_mask) | (tmp & bit_mask);436 437	return r820t_write(priv, reg, &tmp, 1);438}439 440static int r820t_read(struct r820t_priv *priv, u8 reg, u8 *val, int len)441{442	int rc, i;443	u8 *p = &priv->buf[1];444 445	priv->buf[0] = reg;446 447	rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, priv->buf, 1, p, len);448	if (rc != len) {449		tuner_info("%s: i2c rd failed=%d reg=%02x len=%d: %*ph\n",450			   __func__, rc, reg, len, len, p);451		if (rc < 0)452			return rc;453		return -EREMOTEIO;454	}455 456	/* Copy data to the output buffer */457	for (i = 0; i < len; i++)458		val[i] = bitrev8(p[i]);459 460	tuner_dbg("%s: i2c rd reg=%02x len=%d: %*ph\n",461		  __func__, reg, len, len, val);462 463	return 0;464}465 466/*467 * r820t tuning logic468 */469 470static int r820t_set_mux(struct r820t_priv *priv, u32 freq)471{472	const struct r820t_freq_range *range;473	int i, rc;474	u8 val, reg08, reg09;475 476	/* Get the proper frequency range */477	freq = freq / 1000000;478	for (i = 0; i < ARRAY_SIZE(freq_ranges) - 1; i++) {479		if (freq < freq_ranges[i + 1].freq)480			break;481	}482	range = &freq_ranges[i];483 484	tuner_dbg("set r820t range#%d for frequency %d MHz\n", i, freq);485 486	/* Open Drain */487	rc = r820t_write_reg_mask(priv, 0x17, range->open_d, 0x08);488	if (rc < 0)489		return rc;490 491	/* RF_MUX,Polymux */492	rc = r820t_write_reg_mask(priv, 0x1a, range->rf_mux_ploy, 0xc3);493	if (rc < 0)494		return rc;495 496	/* TF BAND */497	rc = r820t_write_reg(priv, 0x1b, range->tf_c);498	if (rc < 0)499		return rc;500 501	/* XTAL CAP & Drive */502	switch (priv->xtal_cap_sel) {503	case XTAL_LOW_CAP_30P:504	case XTAL_LOW_CAP_20P:505		val = range->xtal_cap20p | 0x08;506		break;507	case XTAL_LOW_CAP_10P:508		val = range->xtal_cap10p | 0x08;509		break;510	case XTAL_HIGH_CAP_0P:511		val = range->xtal_cap0p | 0x00;512		break;513	default:514	case XTAL_LOW_CAP_0P:515		val = range->xtal_cap0p | 0x08;516		break;517	}518	rc = r820t_write_reg_mask(priv, 0x10, val, 0x0b);519	if (rc < 0)520		return rc;521 522	if (priv->imr_done) {523		reg08 = priv->imr_data[range->imr_mem].gain_x;524		reg09 = priv->imr_data[range->imr_mem].phase_y;525	} else {526		reg08 = 0;527		reg09 = 0;528	}529	rc = r820t_write_reg_mask(priv, 0x08, reg08, 0x3f);530	if (rc < 0)531		return rc;532 533	rc = r820t_write_reg_mask(priv, 0x09, reg09, 0x3f);534 535	return rc;536}537 538static int r820t_set_pll(struct r820t_priv *priv, enum v4l2_tuner_type type,539			 u32 freq)540{541	u32 vco_freq;542	int rc, i;543	unsigned sleep_time = 10000;544	u32 vco_fra;		/* VCO contribution by SDM (kHz) */545	u32 vco_min  = 1770000;546	u32 vco_max  = vco_min * 2;547	u32 pll_ref;548	u16 n_sdm = 2;549	u16 sdm = 0;550	u8 mix_div = 2;551	u8 div_buf = 0;552	u8 div_num = 0;553	u8 refdiv2 = 0;554	u8 ni, si, nint, vco_fine_tune, val;555	u8 data[5];556 557	/* Frequency in kHz */558	freq = freq / 1000;559	pll_ref = priv->cfg->xtal / 1000;560 561#if 0562	/* Doesn't exist on rtl-sdk, and on field tests, caused troubles */563	if ((priv->cfg->rafael_chip == CHIP_R620D) ||564	   (priv->cfg->rafael_chip == CHIP_R828D) ||565	   (priv->cfg->rafael_chip == CHIP_R828)) {566		/* ref set refdiv2, reffreq = Xtal/2 on ATV application */567		if (type != V4L2_TUNER_DIGITAL_TV) {568			pll_ref /= 2;569			refdiv2 = 0x10;570			sleep_time = 20000;571		}572	} else {573		if (priv->cfg->xtal > 24000000) {574			pll_ref /= 2;575			refdiv2 = 0x10;576		}577	}578#endif579 580	rc = r820t_write_reg_mask(priv, 0x10, refdiv2, 0x10);581	if (rc < 0)582		return rc;583 584	/* set pll autotune = 128kHz */585	rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x0c);586	if (rc < 0)587		return rc;588 589	/* set VCO current = 100 */590	rc = r820t_write_reg_mask(priv, 0x12, 0x80, 0xe0);591	if (rc < 0)592		return rc;593 594	/* Calculate divider */595	while (mix_div <= 64) {596		if (((freq * mix_div) >= vco_min) &&597		   ((freq * mix_div) < vco_max)) {598			div_buf = mix_div;599			while (div_buf > 2) {600				div_buf = div_buf >> 1;601				div_num++;602			}603			break;604		}605		mix_div = mix_div << 1;606	}607 608	rc = r820t_read(priv, 0x00, data, sizeof(data));609	if (rc < 0)610		return rc;611 612	vco_fine_tune = (data[4] & 0x30) >> 4;613 614	tuner_dbg("mix_div=%d div_num=%d vco_fine_tune=%d\n",615			mix_div, div_num, vco_fine_tune);616 617	/*618	 * XXX: R828D/16MHz seems to have always vco_fine_tune=1.619	 * Due to that, this calculation goes wrong.620	 */621	if (priv->cfg->rafael_chip != CHIP_R828D) {622		if (vco_fine_tune > VCO_POWER_REF)623			div_num = div_num - 1;624		else if (vco_fine_tune < VCO_POWER_REF)625			div_num = div_num + 1;626	}627 628	rc = r820t_write_reg_mask(priv, 0x10, div_num << 5, 0xe0);629	if (rc < 0)630		return rc;631 632	vco_freq = freq * mix_div;633	nint = vco_freq / (2 * pll_ref);634	vco_fra = vco_freq - 2 * pll_ref * nint;635 636	/* boundary spur prevention */637	if (vco_fra < pll_ref / 64) {638		vco_fra = 0;639	} else if (vco_fra > pll_ref * 127 / 64) {640		vco_fra = 0;641		nint++;642	} else if ((vco_fra > pll_ref * 127 / 128) && (vco_fra < pll_ref)) {643		vco_fra = pll_ref * 127 / 128;644	} else if ((vco_fra > pll_ref) && (vco_fra < pll_ref * 129 / 128)) {645		vco_fra = pll_ref * 129 / 128;646	}647 648	ni = (nint - 13) / 4;649	si = nint - 4 * ni - 13;650 651	rc = r820t_write_reg(priv, 0x14, ni + (si << 6));652	if (rc < 0)653		return rc;654 655	/* pw_sdm */656	if (!vco_fra)657		val = 0x08;658	else659		val = 0x00;660 661	rc = r820t_write_reg_mask(priv, 0x12, val, 0x08);662	if (rc < 0)663		return rc;664 665	/* sdm calculator */666	while (vco_fra > 1) {667		if (vco_fra > (2 * pll_ref / n_sdm)) {668			sdm = sdm + 32768 / (n_sdm / 2);669			vco_fra = vco_fra - 2 * pll_ref / n_sdm;670			if (n_sdm >= 0x8000)671				break;672		}673		n_sdm = n_sdm << 1;674	}675 676	tuner_dbg("freq %d kHz, pll ref %d%s, sdm=0x%04x\n",677		  freq, pll_ref, refdiv2 ? " / 2" : "", sdm);678 679	rc = r820t_write_reg(priv, 0x16, sdm >> 8);680	if (rc < 0)681		return rc;682	rc = r820t_write_reg(priv, 0x15, sdm & 0xff);683	if (rc < 0)684		return rc;685 686	for (i = 0; i < 2; i++) {687		usleep_range(sleep_time, sleep_time + 1000);688 689		/* Check if PLL has locked */690		rc = r820t_read(priv, 0x00, data, 3);691		if (rc < 0)692			return rc;693		if (data[2] & 0x40)694			break;695 696		if (!i) {697			/* Didn't lock. Increase VCO current */698			rc = r820t_write_reg_mask(priv, 0x12, 0x60, 0xe0);699			if (rc < 0)700				return rc;701		}702	}703 704	if (!(data[2] & 0x40)) {705		priv->has_lock = false;706		return 0;707	}708 709	priv->has_lock = true;710	tuner_dbg("tuner has lock at frequency %d kHz\n", freq);711 712	/* set pll autotune = 8kHz */713	rc = r820t_write_reg_mask(priv, 0x1a, 0x08, 0x08);714 715	return rc;716}717 718static int r820t_sysfreq_sel(struct r820t_priv *priv, u32 freq,719			     enum v4l2_tuner_type type,720			     v4l2_std_id std,721			     u32 delsys)722{723	int rc;724	u8 mixer_top, lna_top, cp_cur, div_buf_cur, lna_vth_l, mixer_vth_l;725	u8 air_cable1_in, cable2_in, pre_dect, lna_discharge, filter_cur;726 727	tuner_dbg("adjusting tuner parameters for the standard\n");728 729	switch (delsys) {730	case SYS_DVBT:731		if ((freq == 506000000) || (freq == 666000000) ||732		   (freq == 818000000)) {733			mixer_top = 0x14;	/* mixer top:14 , top-1, low-discharge */734			lna_top = 0xe5;		/* detect bw 3, lna top:4, predet top:2 */735			cp_cur = 0x28;		/* 101, 0.2 */736			div_buf_cur = 0x20;	/* 10, 200u */737		} else {738			mixer_top = 0x24;	/* mixer top:13 , top-1, low-discharge */739			lna_top = 0xe5;		/* detect bw 3, lna top:4, predet top:2 */740			cp_cur = 0x38;		/* 111, auto */741			div_buf_cur = 0x30;	/* 11, 150u */742		}743		lna_vth_l = 0x53;		/* lna vth 0.84	,  vtl 0.64 */744		mixer_vth_l = 0x75;		/* mixer vth 1.04, vtl 0.84 */745		air_cable1_in = 0x00;746		cable2_in = 0x00;747		pre_dect = 0x40;748		lna_discharge = 14;749		filter_cur = 0x40;		/* 10, low */750		break;751	case SYS_DVBT2:752		mixer_top = 0x24;	/* mixer top:13 , top-1, low-discharge */753		lna_top = 0xe5;		/* detect bw 3, lna top:4, predet top:2 */754		lna_vth_l = 0x53;	/* lna vth 0.84	,  vtl 0.64 */755		mixer_vth_l = 0x75;	/* mixer vth 1.04, vtl 0.84 */756		air_cable1_in = 0x00;757		cable2_in = 0x00;758		pre_dect = 0x40;759		lna_discharge = 14;760		cp_cur = 0x38;		/* 111, auto */761		div_buf_cur = 0x30;	/* 11, 150u */762		filter_cur = 0x40;	/* 10, low */763		break;764	case SYS_ISDBT:765		mixer_top = 0x24;	/* mixer top:13 , top-1, low-discharge */766		lna_top = 0xe5;		/* detect bw 3, lna top:4, predet top:2 */767		lna_vth_l = 0x75;	/* lna vth 1.04	,  vtl 0.84 */768		mixer_vth_l = 0x75;	/* mixer vth 1.04, vtl 0.84 */769		air_cable1_in = 0x00;770		cable2_in = 0x00;771		pre_dect = 0x40;772		lna_discharge = 14;773		cp_cur = 0x38;		/* 111, auto */774		div_buf_cur = 0x30;	/* 11, 150u */775		filter_cur = 0x40;	/* 10, low */776		break;777	case SYS_DVBC_ANNEX_A:778		mixer_top = 0x24;       /* mixer top:13 , top-1, low-discharge */779		lna_top = 0xe5;780		lna_vth_l = 0x62;781		mixer_vth_l = 0x75;782		air_cable1_in = 0x60;783		cable2_in = 0x00;784		pre_dect = 0x40;785		lna_discharge = 14;786		cp_cur = 0x38;          /* 111, auto */787		div_buf_cur = 0x30;     /* 11, 150u */788		filter_cur = 0x40;      /* 10, low */789		break;790	default: /* DVB-T 8M */791		mixer_top = 0x24;	/* mixer top:13 , top-1, low-discharge */792		lna_top = 0xe5;		/* detect bw 3, lna top:4, predet top:2 */793		lna_vth_l = 0x53;	/* lna vth 0.84	,  vtl 0.64 */794		mixer_vth_l = 0x75;	/* mixer vth 1.04, vtl 0.84 */795		air_cable1_in = 0x00;796		cable2_in = 0x00;797		pre_dect = 0x40;798		lna_discharge = 14;799		cp_cur = 0x38;		/* 111, auto */800		div_buf_cur = 0x30;	/* 11, 150u */801		filter_cur = 0x40;	/* 10, low */802		break;803	}804 805	if (priv->cfg->use_diplexer &&806	   ((priv->cfg->rafael_chip == CHIP_R820T) ||807	   (priv->cfg->rafael_chip == CHIP_R828S) ||808	   (priv->cfg->rafael_chip == CHIP_R820C))) {809		if (freq > DIP_FREQ)810			air_cable1_in = 0x00;811		else812			air_cable1_in = 0x60;813		cable2_in = 0x00;814	}815 816 817	if (priv->cfg->use_predetect) {818		rc = r820t_write_reg_mask(priv, 0x06, pre_dect, 0x40);819		if (rc < 0)820			return rc;821	}822 823	rc = r820t_write_reg_mask(priv, 0x1d, lna_top, 0xc7);824	if (rc < 0)825		return rc;826	rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0xf8);827	if (rc < 0)828		return rc;829	rc = r820t_write_reg(priv, 0x0d, lna_vth_l);830	if (rc < 0)831		return rc;832	rc = r820t_write_reg(priv, 0x0e, mixer_vth_l);833	if (rc < 0)834		return rc;835 836	/* Air-IN only for Astrometa */837	rc = r820t_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);838	if (rc < 0)839		return rc;840	rc = r820t_write_reg_mask(priv, 0x06, cable2_in, 0x08);841	if (rc < 0)842		return rc;843 844	rc = r820t_write_reg_mask(priv, 0x11, cp_cur, 0x38);845	if (rc < 0)846		return rc;847	rc = r820t_write_reg_mask(priv, 0x17, div_buf_cur, 0x30);848	if (rc < 0)849		return rc;850	rc = r820t_write_reg_mask(priv, 0x0a, filter_cur, 0x60);851	if (rc < 0)852		return rc;853	/*854	 * Original driver initializes regs 0x05 and 0x06 with the855	 * same value again on this point. Probably, it is just an856	 * error there857	 */858 859	/*860	 * Set LNA861	 */862 863	tuner_dbg("adjusting LNA parameters\n");864	if (type != V4L2_TUNER_ANALOG_TV) {865		/* LNA TOP: lowest */866		rc = r820t_write_reg_mask(priv, 0x1d, 0, 0x38);867		if (rc < 0)868			return rc;869 870		/* 0: normal mode */871		rc = r820t_write_reg_mask(priv, 0x1c, 0, 0x04);872		if (rc < 0)873			return rc;874 875		/* 0: PRE_DECT off */876		rc = r820t_write_reg_mask(priv, 0x06, 0, 0x40);877		if (rc < 0)878			return rc;879 880		/* agc clk 250hz */881		rc = r820t_write_reg_mask(priv, 0x1a, 0x30, 0x30);882		if (rc < 0)883			return rc;884 885		msleep(250);886 887		/* write LNA TOP = 3 */888		rc = r820t_write_reg_mask(priv, 0x1d, 0x18, 0x38);889		if (rc < 0)890			return rc;891 892		/*893		 * write discharge mode894		 * FIXME: IMHO, the mask here is wrong, but it matches895		 * what's there at the original driver896		 */897		rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0x04);898		if (rc < 0)899			return rc;900 901		/* LNA discharge current */902		rc = r820t_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);903		if (rc < 0)904			return rc;905 906		/* agc clk 60hz */907		rc = r820t_write_reg_mask(priv, 0x1a, 0x20, 0x30);908		if (rc < 0)909			return rc;910	} else {911		/* PRE_DECT off */912		rc = r820t_write_reg_mask(priv, 0x06, 0, 0x40);913		if (rc < 0)914			return rc;915 916		/* write LNA TOP */917		rc = r820t_write_reg_mask(priv, 0x1d, lna_top, 0x38);918		if (rc < 0)919			return rc;920 921		/*922		 * write discharge mode923		 * FIXME: IMHO, the mask here is wrong, but it matches924		 * what's there at the original driver925		 */926		rc = r820t_write_reg_mask(priv, 0x1c, mixer_top, 0x04);927		if (rc < 0)928			return rc;929 930		/* LNA discharge current */931		rc = r820t_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f);932		if (rc < 0)933			return rc;934 935		/* agc clk 1Khz, external det1 cap 1u */936		rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x30);937		if (rc < 0)938			return rc;939 940		rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x04);941		if (rc < 0)942			return rc;943	}944	return 0;945}946 947static int r820t_set_tv_standard(struct r820t_priv *priv,948				 unsigned bw,949				 enum v4l2_tuner_type type,950				 v4l2_std_id std, u32 delsys)951 952{953	int rc, i;954	u32 if_khz, filt_cal_lo;955	u8 data[5], val;956	u8 filt_gain, img_r, filt_q, hp_cor, ext_enable, loop_through;957	u8 lt_att, flt_ext_widest, polyfil_cur;958	bool need_calibration;959 960	tuner_dbg("selecting the delivery system\n");961 962	if (delsys == SYS_ISDBT) {963		if_khz = 4063;964		filt_cal_lo = 59000;965		filt_gain = 0x10;	/* +3db, 6mhz on */966		img_r = 0x00;		/* image negative */967		filt_q = 0x10;		/* r10[4]:low q(1'b1) */968		hp_cor = 0x6a;		/* 1.7m disable, +2cap, 1.25mhz */969		ext_enable = 0x40;	/* r30[6], ext enable; r30[5]:0 ext at lna max */970		loop_through = 0x00;	/* r5[7], lt on */971		lt_att = 0x00;		/* r31[7], lt att enable */972		flt_ext_widest = 0x80;	/* r15[7]: flt_ext_wide on */973		polyfil_cur = 0x60;	/* r25[6:5]:min */974	} else if (delsys == SYS_DVBC_ANNEX_A) {975		if_khz = 5070;976		filt_cal_lo = 73500;977		filt_gain = 0x10;	/* +3db, 6mhz on */978		img_r = 0x00;		/* image negative */979		filt_q = 0x10;		/* r10[4]:low q(1'b1) */980		hp_cor = 0x0b;		/* 1.7m disable, +0cap, 1.0mhz */981		ext_enable = 0x40;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */982		loop_through = 0x00;	/* r5[7], lt on */983		lt_att = 0x00;		/* r31[7], lt att enable */984		flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */985		polyfil_cur = 0x60;	/* r25[6:5]:min */986	} else if (delsys == SYS_DVBC_ANNEX_C) {987		if_khz = 4063;988		filt_cal_lo = 55000;989		filt_gain = 0x10;	/* +3db, 6mhz on */990		img_r = 0x00;		/* image negative */991		filt_q = 0x10;		/* r10[4]:low q(1'b1) */992		hp_cor = 0x6a;		/* 1.7m disable, +0cap, 1.0mhz */993		ext_enable = 0x40;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */994		loop_through = 0x00;	/* r5[7], lt on */995		lt_att = 0x00;		/* r31[7], lt att enable */996		flt_ext_widest = 0x80;	/* r15[7]: flt_ext_wide on */997		polyfil_cur = 0x60;	/* r25[6:5]:min */998	} else {999		if (bw <= 6) {1000			if_khz = 3570;1001			filt_cal_lo = 56000;	/* 52000->56000 */1002			filt_gain = 0x10;	/* +3db, 6mhz on */1003			img_r = 0x00;		/* image negative */1004			filt_q = 0x10;		/* r10[4]:low q(1'b1) */1005			hp_cor = 0x6b;		/* 1.7m disable, +2cap, 1.0mhz */1006			ext_enable = 0x60;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */1007			loop_through = 0x00;	/* r5[7], lt on */1008			lt_att = 0x00;		/* r31[7], lt att enable */1009			flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */1010			polyfil_cur = 0x60;	/* r25[6:5]:min */1011		} else if (bw == 7) {1012#if 01013			/*1014			 * There are two 7 MHz tables defined on the original1015			 * driver, but just the second one seems to be visible1016			 * by rtl2832. Keep this one here commented, as it1017			 * might be needed in the future1018			 */1019 1020			if_khz = 4070;1021			filt_cal_lo = 60000;1022			filt_gain = 0x10;	/* +3db, 6mhz on */1023			img_r = 0x00;		/* image negative */1024			filt_q = 0x10;		/* r10[4]:low q(1'b1) */1025			hp_cor = 0x2b;		/* 1.7m disable, +1cap, 1.0mhz */1026			ext_enable = 0x60;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */1027			loop_through = 0x00;	/* r5[7], lt on */1028			lt_att = 0x00;		/* r31[7], lt att enable */1029			flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */1030			polyfil_cur = 0x60;	/* r25[6:5]:min */1031#endif1032			/* 7 MHz, second table */1033			if_khz = 4570;1034			filt_cal_lo = 63000;1035			filt_gain = 0x10;	/* +3db, 6mhz on */1036			img_r = 0x00;		/* image negative */1037			filt_q = 0x10;		/* r10[4]:low q(1'b1) */1038			hp_cor = 0x2a;		/* 1.7m disable, +1cap, 1.25mhz */1039			ext_enable = 0x60;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */1040			loop_through = 0x00;	/* r5[7], lt on */1041			lt_att = 0x00;		/* r31[7], lt att enable */1042			flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */1043			polyfil_cur = 0x60;	/* r25[6:5]:min */1044		} else {1045			if_khz = 4570;1046			filt_cal_lo = 68500;1047			filt_gain = 0x10;	/* +3db, 6mhz on */1048			img_r = 0x00;		/* image negative */1049			filt_q = 0x10;		/* r10[4]:low q(1'b1) */1050			hp_cor = 0x0b;		/* 1.7m disable, +0cap, 1.0mhz */1051			ext_enable = 0x60;	/* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */1052			loop_through = 0x00;	/* r5[7], lt on */1053			lt_att = 0x00;		/* r31[7], lt att enable */1054			flt_ext_widest = 0x00;	/* r15[7]: flt_ext_wide off */1055			polyfil_cur = 0x60;	/* r25[6:5]:min */1056		}1057	}1058 1059	/* Initialize the shadow registers */1060	memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));1061 1062	/* Init Flag & Xtal_check Result */1063	if (priv->imr_done)1064		val = 1 | priv->xtal_cap_sel << 1;1065	else1066		val = 0;1067	rc = r820t_write_reg_mask(priv, 0x0c, val, 0x0f);1068	if (rc < 0)1069		return rc;1070 1071	/* version */1072	rc = r820t_write_reg_mask(priv, 0x13, VER_NUM, 0x3f);1073	if (rc < 0)1074		return rc;1075 1076	/* for LT Gain test */1077	if (type != V4L2_TUNER_ANALOG_TV) {1078		rc = r820t_write_reg_mask(priv, 0x1d, 0x00, 0x38);1079		if (rc < 0)1080			return rc;1081		usleep_range(1000, 2000);1082	}1083	priv->int_freq = if_khz * 1000;1084 1085	/* Check if standard changed. If so, filter calibration is needed */1086	if (type != priv->type)1087		need_calibration = true;1088	else if ((type == V4L2_TUNER_ANALOG_TV) && (std != priv->std))1089		need_calibration = true;1090	else if ((type == V4L2_TUNER_DIGITAL_TV) &&1091		 ((delsys != priv->delsys) || bw != priv->bw))1092		need_calibration = true;1093	else1094		need_calibration = false;1095 1096	if (need_calibration) {1097		tuner_dbg("calibrating the tuner\n");1098		for (i = 0; i < 2; i++) {1099			/* Set filt_cap */1100			rc = r820t_write_reg_mask(priv, 0x0b, hp_cor, 0x60);1101			if (rc < 0)1102				return rc;1103 1104			/* set cali clk =on */1105			rc = r820t_write_reg_mask(priv, 0x0f, 0x04, 0x04);1106			if (rc < 0)1107				return rc;1108 1109			/* X'tal cap 0pF for PLL */1110			rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x03);1111			if (rc < 0)1112				return rc;1113 1114			rc = r820t_set_pll(priv, type, filt_cal_lo * 1000);1115			if (rc < 0 || !priv->has_lock)1116				return rc;1117 1118			/* Start Trigger */1119			rc = r820t_write_reg_mask(priv, 0x0b, 0x10, 0x10);1120			if (rc < 0)1121				return rc;1122 1123			usleep_range(1000, 2000);1124 1125			/* Stop Trigger */1126			rc = r820t_write_reg_mask(priv, 0x0b, 0x00, 0x10);1127			if (rc < 0)1128				return rc;1129 1130			/* set cali clk =off */1131			rc = r820t_write_reg_mask(priv, 0x0f, 0x00, 0x04);1132			if (rc < 0)1133				return rc;1134 1135			/* Check if calibration worked */1136			rc = r820t_read(priv, 0x00, data, sizeof(data));1137			if (rc < 0)1138				return rc;1139 1140			priv->fil_cal_code = data[4] & 0x0f;1141			if (priv->fil_cal_code && priv->fil_cal_code != 0x0f)1142				break;1143		}1144		/* narrowest */1145		if (priv->fil_cal_code == 0x0f)1146			priv->fil_cal_code = 0;1147	}1148 1149	rc = r820t_write_reg_mask(priv, 0x0a,1150				  filt_q | priv->fil_cal_code, 0x1f);1151	if (rc < 0)1152		return rc;1153 1154	/* Set BW, Filter_gain, & HP corner */1155	rc = r820t_write_reg_mask(priv, 0x0b, hp_cor, 0xef);1156	if (rc < 0)1157		return rc;1158 1159 1160	/* Set Img_R */1161	rc = r820t_write_reg_mask(priv, 0x07, img_r, 0x80);1162	if (rc < 0)1163		return rc;1164 1165	/* Set filt_3dB, V6MHz */1166	rc = r820t_write_reg_mask(priv, 0x06, filt_gain, 0x30);1167	if (rc < 0)1168		return rc;1169 1170	/* channel filter extension */1171	rc = r820t_write_reg_mask(priv, 0x1e, ext_enable, 0x60);1172	if (rc < 0)1173		return rc;1174 1175	/* Loop through */1176	rc = r820t_write_reg_mask(priv, 0x05, loop_through, 0x80);1177	if (rc < 0)1178		return rc;1179 1180	/* Loop through attenuation */1181	rc = r820t_write_reg_mask(priv, 0x1f, lt_att, 0x80);1182	if (rc < 0)1183		return rc;1184 1185	/* filter extension widest */1186	rc = r820t_write_reg_mask(priv, 0x0f, flt_ext_widest, 0x80);1187	if (rc < 0)1188		return rc;1189 1190	/* RF poly filter current */1191	rc = r820t_write_reg_mask(priv, 0x19, polyfil_cur, 0x60);1192	if (rc < 0)1193		return rc;1194 1195	/* Store current standard. If it changes, re-calibrate the tuner */1196	priv->delsys = delsys;1197	priv->type = type;1198	priv->std = std;1199	priv->bw = bw;1200 1201	return 0;1202}1203 1204static int r820t_read_gain(struct r820t_priv *priv)1205{1206	u8 data[4];1207	int rc;1208 1209	rc = r820t_read(priv, 0x00, data, sizeof(data));1210	if (rc < 0)1211		return rc;1212 1213	return ((data[3] & 0x08) << 1) + ((data[3] & 0xf0) >> 4);1214}1215 1216#if 01217/* FIXME: This routine requires more testing */1218 1219/*1220 * measured with a Racal 6103E GSM test set at 928 MHz with -60 dBm1221 * input power, for raw results see:1222 *	http://steve-m.de/projects/rtl-sdr/gain_measurement/r820t/1223 */1224 1225static const int r820t_lna_gain_steps[]  = {1226	0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 131227};1228 1229static const int r820t_mixer_gain_steps[]  = {1230	0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -81231};1232 1233static int r820t_set_gain_mode(struct r820t_priv *priv,1234			       bool set_manual_gain,1235			       int gain)1236{1237	int rc;1238 1239	if (set_manual_gain) {1240		int i, total_gain = 0;1241		uint8_t mix_index = 0, lna_index = 0;1242		u8 data[4];1243 1244		/* LNA auto off */1245		rc = r820t_write_reg_mask(priv, 0x05, 0x10, 0x10);1246		if (rc < 0)1247			return rc;1248 1249		 /* Mixer auto off */1250		rc = r820t_write_reg_mask(priv, 0x07, 0, 0x10);1251		if (rc < 0)1252			return rc;1253 1254		rc = r820t_read(priv, 0x00, data, sizeof(data));1255		if (rc < 0)1256			return rc;1257 1258		/* set fixed VGA gain for now (16.3 dB) */1259		rc = r820t_write_reg_mask(priv, 0x0c, 0x08, 0x9f);1260		if (rc < 0)1261			return rc;1262 1263		for (i = 0; i < 15; i++) {1264			if (total_gain >= gain)1265				break;1266 1267			total_gain += r820t_lna_gain_steps[++lna_index];1268 1269			if (total_gain >= gain)1270				break;1271 1272			total_gain += r820t_mixer_gain_steps[++mix_index];1273		}1274 1275		/* set LNA gain */1276		rc = r820t_write_reg_mask(priv, 0x05, lna_index, 0x0f);1277		if (rc < 0)1278			return rc;1279 1280		/* set Mixer gain */1281		rc = r820t_write_reg_mask(priv, 0x07, mix_index, 0x0f);1282		if (rc < 0)1283			return rc;1284	} else {1285		/* LNA */1286		rc = r820t_write_reg_mask(priv, 0x05, 0, 0x10);1287		if (rc < 0)1288			return rc;1289 1290		/* Mixer */1291		rc = r820t_write_reg_mask(priv, 0x07, 0x10, 0x10);1292		if (rc < 0)1293			return rc;1294 1295		/* set fixed VGA gain for now (26.5 dB) */1296		rc = r820t_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);1297		if (rc < 0)1298			return rc;1299	}1300 1301	return 0;1302}1303#endif1304 1305static int generic_set_freq(struct dvb_frontend *fe,1306			    u32 freq /* in HZ */,1307			    unsigned bw,1308			    enum v4l2_tuner_type type,1309			    v4l2_std_id std, u32 delsys)1310{1311	struct r820t_priv		*priv = fe->tuner_priv;1312	int				rc;1313	u32				lo_freq;1314 1315	tuner_dbg("should set frequency to %d kHz, bw %d MHz\n",1316		  freq / 1000, bw);1317 1318	rc = r820t_set_tv_standard(priv, bw, type, std, delsys);1319	if (rc < 0)1320		goto err;1321 1322	if ((type == V4L2_TUNER_ANALOG_TV) && (std == V4L2_STD_SECAM_LC))1323		lo_freq = freq - priv->int_freq;1324	 else1325		lo_freq = freq + priv->int_freq;1326 1327	rc = r820t_set_mux(priv, lo_freq);1328	if (rc < 0)1329		goto err;1330 1331	rc = r820t_set_pll(priv, type, lo_freq);1332	if (rc < 0 || !priv->has_lock)1333		goto err;1334 1335	rc = r820t_sysfreq_sel(priv, freq, type, std, delsys);1336	if (rc < 0)1337		goto err;1338 1339	tuner_dbg("%s: PLL locked on frequency %d Hz, gain=%d\n",1340		  __func__, freq, r820t_read_gain(priv));1341 1342err:1343 1344	if (rc < 0)1345		tuner_dbg("%s: failed=%d\n", __func__, rc);1346	return rc;1347}1348 1349/*1350 * r820t standby logic1351 */1352 1353static int r820t_standby(struct r820t_priv *priv)1354{1355	int rc;1356 1357	/* If device was not initialized yet, don't need to standby */1358	if (!priv->init_done)1359		return 0;1360 1361	rc = r820t_write_reg(priv, 0x06, 0xb1);1362	if (rc < 0)1363		return rc;1364	rc = r820t_write_reg(priv, 0x05, 0x03);1365	if (rc < 0)1366		return rc;1367	rc = r820t_write_reg(priv, 0x07, 0x3a);1368	if (rc < 0)1369		return rc;1370	rc = r820t_write_reg(priv, 0x08, 0x40);1371	if (rc < 0)1372		return rc;1373	rc = r820t_write_reg(priv, 0x09, 0xc0);1374	if (rc < 0)1375		return rc;1376	rc = r820t_write_reg(priv, 0x0a, 0x36);1377	if (rc < 0)1378		return rc;1379	rc = r820t_write_reg(priv, 0x0c, 0x35);1380	if (rc < 0)1381		return rc;1382	rc = r820t_write_reg(priv, 0x0f, 0x68);1383	if (rc < 0)1384		return rc;1385	rc = r820t_write_reg(priv, 0x11, 0x03);1386	if (rc < 0)1387		return rc;1388	rc = r820t_write_reg(priv, 0x17, 0xf4);1389	if (rc < 0)1390		return rc;1391	rc = r820t_write_reg(priv, 0x19, 0x0c);1392 1393	/* Force initial calibration */1394	priv->type = -1;1395 1396	return rc;1397}1398 1399/*1400 * r820t device init logic1401 */1402 1403static int r820t_xtal_check(struct r820t_priv *priv)1404{1405	int rc, i;1406	u8 data[3], val;1407 1408	/* Initialize the shadow registers */1409	memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));1410 1411	/* cap 30pF & Drive Low */1412	rc = r820t_write_reg_mask(priv, 0x10, 0x0b, 0x0b);1413	if (rc < 0)1414		return rc;1415 1416	/* set pll autotune = 128kHz */1417	rc = r820t_write_reg_mask(priv, 0x1a, 0x00, 0x0c);1418	if (rc < 0)1419		return rc;1420 1421	/* set manual initial reg = 111111;  */1422	rc = r820t_write_reg_mask(priv, 0x13, 0x7f, 0x7f);1423	if (rc < 0)1424		return rc;1425 1426	/* set auto */1427	rc = r820t_write_reg_mask(priv, 0x13, 0x00, 0x40);1428	if (rc < 0)1429		return rc;1430 1431	/* Try several xtal capacitor alternatives */1432	for (i = 0; i < ARRAY_SIZE(r820t_xtal_capacitor); i++) {1433		rc = r820t_write_reg_mask(priv, 0x10,1434					  r820t_xtal_capacitor[i][0], 0x1b);1435		if (rc < 0)1436			return rc;1437 1438		usleep_range(5000, 6000);1439 1440		rc = r820t_read(priv, 0x00, data, sizeof(data));1441		if (rc < 0)1442			return rc;1443		if (!(data[2] & 0x40))1444			continue;1445 1446		val = data[2] & 0x3f;1447 1448		if (priv->cfg->xtal == 16000000 && (val > 29 || val < 23))1449			break;1450 1451		if (val != 0x3f)1452			break;1453	}1454 1455	if (i == ARRAY_SIZE(r820t_xtal_capacitor))1456		return -EINVAL;1457 1458	return r820t_xtal_capacitor[i][1];1459}1460 1461static int r820t_imr_prepare(struct r820t_priv *priv)1462{1463	int rc;1464 1465	/* Initialize the shadow registers */1466	memcpy(priv->regs, r820t_init_array, sizeof(r820t_init_array));1467 1468	/* lna off (air-in off) */1469	rc = r820t_write_reg_mask(priv, 0x05, 0x20, 0x20);1470	if (rc < 0)1471		return rc;1472 1473	/* mixer gain mode = manual */1474	rc = r820t_write_reg_mask(priv, 0x07, 0, 0x10);1475	if (rc < 0)1476		return rc;1477 1478	/* filter corner = lowest */1479	rc = r820t_write_reg_mask(priv, 0x0a, 0x0f, 0x0f);1480	if (rc < 0)1481		return rc;1482 1483	/* filter bw=+2cap, hp=5M */1484	rc = r820t_write_reg_mask(priv, 0x0b, 0x60, 0x6f);1485	if (rc < 0)1486		return rc;1487 1488	/* adc=on, vga code mode, gain = 26.5dB   */1489	rc = r820t_write_reg_mask(priv, 0x0c, 0x0b, 0x9f);1490	if (rc < 0)1491		return rc;1492 1493	/* ring clk = on */1494	rc = r820t_write_reg_mask(priv, 0x0f, 0, 0x08);1495	if (rc < 0)1496		return rc;1497 1498	/* ring power = on */1499	rc = r820t_write_reg_mask(priv, 0x18, 0x10, 0x10);1500	if (rc < 0)1501		return rc;1502 1503	/* from ring = ring pll in */1504	rc = r820t_write_reg_mask(priv, 0x1c, 0x02, 0x02);1505	if (rc < 0)1506		return rc;1507 1508	/* sw_pdect = det3 */1509	rc = r820t_write_reg_mask(priv, 0x1e, 0x80, 0x80);1510	if (rc < 0)1511		return rc;1512 1513	/* Set filt_3dB */1514	rc = r820t_write_reg_mask(priv, 0x06, 0x20, 0x20);1515 1516	return rc;1517}1518 1519static int r820t_multi_read(struct r820t_priv *priv)1520{1521	int rc, i;1522	u16 sum = 0;1523	u8 data[2], min = 255, max = 0;1524 1525	usleep_range(5000, 6000);1526 1527	for (i = 0; i < 6; i++) {1528		rc = r820t_read(priv, 0x00, data, sizeof(data));1529		if (rc < 0)1530			return rc;1531 1532		sum += data[1];1533 1534		if (data[1] < min)1535			min = data[1];1536 1537		if (data[1] > max)1538			max = data[1];1539	}1540	rc = sum - max - min;1541 1542	return rc;1543}1544 1545static int r820t_imr_cross(struct r820t_priv *priv,1546			   struct r820t_sect_type iq_point[3],1547			   u8 *x_direct)1548{1549	struct r820t_sect_type cross[5]; /* (0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0) */1550	struct r820t_sect_type tmp;1551	int i, rc;1552	u8 reg08, reg09;1553 1554	reg08 = r820t_read_cache_reg(priv, 8) & 0xc0;1555	reg09 = r820t_read_cache_reg(priv, 9) & 0xc0;1556 1557	tmp.gain_x = 0;1558	tmp.phase_y = 0;1559	tmp.value = 255;1560 1561	for (i = 0; i < 5; i++) {1562		switch (i) {1563		case 0:1564			cross[i].gain_x  = reg08;1565			cross[i].phase_y = reg09;1566			break;1567		case 1:1568			cross[i].gain_x  = reg08;		/* 0 */1569			cross[i].phase_y = reg09 + 1;		/* Q-1 */1570			break;1571		case 2:1572			cross[i].gain_x  = reg08;		/* 0 */1573			cross[i].phase_y = (reg09 | 0x20) + 1;	/* I-1 */1574			break;1575		case 3:1576			cross[i].gain_x  = reg08 + 1;		/* Q-1 */1577			cross[i].phase_y = reg09;1578			break;1579		default:1580			cross[i].gain_x  = (reg08 | 0x20) + 1;	/* I-1 */1581			cross[i].phase_y = reg09;1582		}1583 1584		rc = r820t_write_reg(priv, 0x08, cross[i].gain_x);1585		if (rc < 0)1586			return rc;1587 1588		rc = r820t_write_reg(priv, 0x09, cross[i].phase_y);1589		if (rc < 0)1590			return rc;1591 1592		rc = r820t_multi_read(priv);1593		if (rc < 0)1594			return rc;1595 1596		cross[i].value = rc;1597 1598		if (cross[i].value < tmp.value)1599			tmp = cross[i];1600	}1601 1602	if ((tmp.phase_y & 0x1f) == 1) {	/* y-direction */1603		*x_direct = 0;1604 1605		iq_point[0] = cross[0];1606		iq_point[1] = cross[1];1607		iq_point[2] = cross[2];1608	} else {				/* (0,0) or x-direction */1609		*x_direct = 1;1610 1611		iq_point[0] = cross[0];1612		iq_point[1] = cross[3];1613		iq_point[2] = cross[4];1614	}1615	return 0;1616}1617 1618static void r820t_compre_cor(struct r820t_sect_type iq[3])1619{1620	int i;1621 1622	for (i = 3; i > 0; i--) {1623		if (iq[0].value > iq[i - 1].value)1624			swap(iq[0], iq[i - 1]);1625	}1626}1627 1628static int r820t_compre_step(struct r820t_priv *priv,1629			     struct r820t_sect_type iq[3], u8 reg)1630{1631	int rc;1632	struct r820t_sect_type tmp;1633 1634	/*1635	 * Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare1636	 * with min value:1637	 *  new < min => update to min and continue1638	 *  new > min => Exit1639	 */1640 1641	/* min value already saved in iq[0] */1642	tmp.phase_y = iq[0].phase_y;1643	tmp.gain_x  = iq[0].gain_x;1644 1645	while (((tmp.gain_x & 0x1f) < IMR_TRIAL) &&1646	      ((tmp.phase_y & 0x1f) < IMR_TRIAL)) {1647		if (reg == 0x08)1648			tmp.gain_x++;1649		else1650			tmp.phase_y++;1651 1652		rc = r820t_write_reg(priv, 0x08, tmp.gain_x);1653		if (rc < 0)1654			return rc;1655 1656		rc = r820t_write_reg(priv, 0x09, tmp.phase_y);1657		if (rc < 0)1658			return rc;1659 1660		rc = r820t_multi_read(priv);1661		if (rc < 0)1662			return rc;1663		tmp.value = rc;1664 1665		if (tmp.value <= iq[0].value) {1666			iq[0].gain_x  = tmp.gain_x;1667			iq[0].phase_y = tmp.phase_y;1668			iq[0].value   = tmp.value;1669		} else {1670			return 0;1671		}1672 1673	}1674 1675	return 0;1676}1677 1678static int r820t_iq_tree(struct r820t_priv *priv,1679			 struct r820t_sect_type iq[3],1680			 u8 fix_val, u8 var_val, u8 fix_reg)1681{1682	int rc, i;1683	u8 tmp, var_reg;1684 1685	/*1686	 * record IMC results by input gain/phase location then adjust1687	 * gain or phase positive 1 step and negative 1 step,1688	 * both record results1689	 */1690 1691	if (fix_reg == 0x08)1692		var_reg = 0x09;1693	else1694		var_reg = 0x08;1695 1696	for (i = 0; i < 3; i++) {1697		rc = r820t_write_reg(priv, fix_reg, fix_val);1698		if (rc < 0)1699			return rc;1700 1701		rc = r820t_write_reg(priv, var_reg, var_val);1702		if (rc < 0)1703			return rc;1704 1705		rc = r820t_multi_read(priv);1706		if (rc < 0)1707			return rc;1708		iq[i].value = rc;1709 1710		if (fix_reg == 0x08) {1711			iq[i].gain_x  = fix_val;1712			iq[i].phase_y = var_val;1713		} else {1714			iq[i].phase_y = fix_val;1715			iq[i].gain_x  = var_val;1716		}1717 1718		if (i == 0) {  /* try right-side point */1719			var_val++;1720		} else if (i == 1) { /* try left-side point */1721			 /* if absolute location is 1, change I/Q direction */1722			if ((var_val & 0x1f) < 0x02) {1723				tmp = 2 - (var_val & 0x1f);1724 1725				/* b[5]:I/Q selection. 0:Q-path, 1:I-path */1726				if (var_val & 0x20) {1727					var_val &= 0xc0;1728					var_val |= tmp;1729				} else {1730					var_val |= 0x20 | tmp;1731				}1732			} else {1733				var_val -= 2;1734			}1735		}1736	}1737 1738	return 0;1739}1740 1741static int r820t_section(struct r820t_priv *priv,1742			 struct r820t_sect_type *iq_point)1743{1744	int rc;1745	struct r820t_sect_type compare_iq[3], compare_bet[3];1746 1747	/* Try X-1 column and save min result to compare_bet[0] */1748	if (!(iq_point->gain_x & 0x1f))1749		compare_iq[0].gain_x = ((iq_point->gain_x) & 0xdf) + 1;  /* Q-path, Gain=1 */1750	else1751		compare_iq[0].gain_x  = iq_point->gain_x - 1;  /* left point */1752	compare_iq[0].phase_y = iq_point->phase_y;1753 1754	/* y-direction */1755	rc = r820t_iq_tree(priv, compare_iq,  compare_iq[0].gain_x,1756			compare_iq[0].phase_y, 0x08);1757	if (rc < 0)1758		return rc;1759 1760	r820t_compre_cor(compare_iq);1761 1762	compare_bet[0] = compare_iq[0];1763 1764	/* Try X column and save min result to compare_bet[1] */1765	compare_iq[0].gain_x  = iq_point->gain_x;1766	compare_iq[0].phase_y = iq_point->phase_y;1767 1768	rc = r820t_iq_tree(priv, compare_iq,  compare_iq[0].gain_x,1769			   compare_iq[0].phase_y, 0x08);1770	if (rc < 0)1771		return rc;1772 1773	r820t_compre_cor(compare_iq);1774 1775	compare_bet[1] = compare_iq[0];1776 1777	/* Try X+1 column and save min result to compare_bet[2] */1778	if ((iq_point->gain_x & 0x1f) == 0x00)1779		compare_iq[0].gain_x = ((iq_point->gain_x) | 0x20) + 1;  /* I-path, Gain=1 */1780	else1781		compare_iq[0].gain_x = iq_point->gain_x + 1;1782	compare_iq[0].phase_y = iq_point->phase_y;1783 1784	rc = r820t_iq_tree(priv, compare_iq,  compare_iq[0].gain_x,1785			   compare_iq[0].phase_y, 0x08);1786	if (rc < 0)1787		return rc;1788 1789	r820t_compre_cor(compare_iq);1790 1791	compare_bet[2] = compare_iq[0];1792 1793	r820t_compre_cor(compare_bet);1794 1795	*iq_point = compare_bet[0];1796 1797	return 0;1798}1799 1800static int r820t_vga_adjust(struct r820t_priv *priv)1801{1802	int rc;1803	u8 vga_count;1804 1805	/* increase vga power to let image significant */1806	for (vga_count = 12; vga_count < 16; vga_count++) {1807		rc = r820t_write_reg_mask(priv, 0x0c, vga_count, 0x0f);1808		if (rc < 0)1809			return rc;1810 1811		usleep_range(10000, 11000);1812 1813		rc = r820t_multi_read(priv);1814		if (rc < 0)1815			return rc;1816 1817		if (rc > 40 * 4)1818			break;1819	}1820 1821	return 0;1822}1823 1824static int r820t_iq(struct r820t_priv *priv, struct r820t_sect_type *iq_pont)1825{1826	struct r820t_sect_type compare_iq[3];1827	int rc;1828	u8 x_direction = 0;  /* 1:x, 0:y */1829	u8 dir_reg, other_reg;1830 1831	r820t_vga_adjust(priv);1832 1833	rc = r820t_imr_cross(priv, compare_iq, &x_direction);1834	if (rc < 0)1835		return rc;1836 1837	if (x_direction == 1) {1838		dir_reg   = 0x08;1839		other_reg = 0x09;1840	} else {1841		dir_reg   = 0x09;1842		other_reg = 0x08;1843	}1844 1845	/* compare and find min of 3 points. determine i/q direction */1846	r820t_compre_cor(compare_iq);1847 1848	/* increase step to find min value of this direction */1849	rc = r820t_compre_step(priv, compare_iq, dir_reg);1850	if (rc < 0)1851		return rc;1852 1853	/* the other direction */1854	rc = r820t_iq_tree(priv, compare_iq,  compare_iq[0].gain_x,1855				compare_iq[0].phase_y, dir_reg);1856	if (rc < 0)1857		return rc;1858 1859	/* compare and find min of 3 points. determine i/q direction */1860	r820t_compre_cor(compare_iq);1861 1862	/* increase step to find min value on this direction */1863	rc = r820t_compre_step(priv, compare_iq, other_reg);1864	if (rc < 0)1865		return rc;1866 1867	/* check 3 points again */1868	rc = r820t_iq_tree(priv, compare_iq,  compare_iq[0].gain_x,1869				compare_iq[0].phase_y, other_reg);1870	if (rc < 0)1871		return rc;1872 1873	r820t_compre_cor(compare_iq);1874 1875	/* section-9 check */1876	rc = r820t_section(priv, compare_iq);1877 1878	*iq_pont = compare_iq[0];1879 1880	/* reset gain/phase control setting */1881	rc = r820t_write_reg_mask(priv, 0x08, 0, 0x3f);1882	if (rc < 0)1883		return rc;1884 1885	rc = r820t_write_reg_mask(priv, 0x09, 0, 0x3f);1886 1887	return rc;1888}1889 1890static int r820t_f_imr(struct r820t_priv *priv, struct r820t_sect_type *iq_pont)1891{1892	int rc;1893 1894	r820t_vga_adjust(priv);1895 1896	/*1897	 * search surrounding points from previous point1898	 * try (x-1), (x), (x+1) columns, and find min IMR result point1899	 */1900	rc = r820t_section(priv, iq_pont);1901	if (rc < 0)1902		return rc;1903 1904	return 0;1905}1906 1907static int r820t_imr(struct r820t_priv *priv, unsigned imr_mem, bool im_flag)1908{1909	struct r820t_sect_type imr_point;1910	int rc;1911	u32 ring_vco, ring_freq, ring_ref;1912	u8 n_ring, n;1913	int reg18, reg19, reg1f;1914 1915	if (priv->cfg->xtal > 24000000)1916		ring_ref = priv->cfg->xtal / 2000;1917	else1918		ring_ref = priv->cfg->xtal / 1000;1919 1920	n_ring = 15;1921	for (n = 0; n < 16; n++) {1922		if ((16 + n) * 8 * ring_ref >= 3100000) {1923			n_ring = n;1924			break;1925		}1926	}1927 1928	reg18 = r820t_read_cache_reg(priv, 0x18);1929	reg19 = r820t_read_cache_reg(priv, 0x19);1930	reg1f = r820t_read_cache_reg(priv, 0x1f);1931 1932	reg18 &= 0xf0;      /* set ring[3:0] */1933	reg18 |= n_ring;1934 1935	ring_vco = (16 + n_ring) * 8 * ring_ref;1936 1937	reg18 &= 0xdf;   /* clear ring_se23 */1938	reg19 &= 0xfc;   /* clear ring_seldiv */1939	reg1f &= 0xfc;   /* clear ring_att */1940 1941	switch (imr_mem) {1942	case 0:1943		ring_freq = ring_vco / 48;1944		reg18 |= 0x20;  /* ring_se23 = 1 */1945		reg19 |= 0x03;  /* ring_seldiv = 3 */1946		reg1f |= 0x02;  /* ring_att 10 */1947		break;1948	case 1:1949		ring_freq = ring_vco / 16;1950		reg18 |= 0x00;  /* ring_se23 = 0 */1951		reg19 |= 0x02;  /* ring_seldiv = 2 */1952		reg1f |= 0x00;  /* pw_ring 00 */1953		break;1954	case 2:1955		ring_freq = ring_vco / 8;1956		reg18 |= 0x00;  /* ring_se23 = 0 */1957		reg19 |= 0x01;  /* ring_seldiv = 1 */1958		reg1f |= 0x03;  /* pw_ring 11 */1959		break;1960	case 3:1961		ring_freq = ring_vco / 6;1962		reg18 |= 0x20;  /* ring_se23 = 1 */1963		reg19 |= 0x00;  /* ring_seldiv = 0 */1964		reg1f |= 0x03;  /* pw_ring 11 */1965		break;1966	case 4:1967		ring_freq = ring_vco / 4;1968		reg18 |= 0x00;  /* ring_se23 = 0 */1969		reg19 |= 0x00;  /* ring_seldiv = 0 */1970		reg1f |= 0x01;  /* pw_ring 01 */1971		break;1972	default:1973		ring_freq = ring_vco / 4;1974		reg18 |= 0x00;  /* ring_se23 = 0 */1975		reg19 |= 0x00;  /* ring_seldiv = 0 */1976		reg1f |= 0x01;  /* pw_ring 01 */1977		break;1978	}1979 1980 1981	/* write pw_ring, n_ring, ringdiv2 registers */1982 1983	/* n_ring, ring_se23 */1984	rc = r820t_write_reg(priv, 0x18, reg18);1985	if (rc < 0)1986		return rc;1987 1988	/* ring_sediv */1989	rc = r820t_write_reg(priv, 0x19, reg19);1990	if (rc < 0)1991		return rc;1992 1993	/* pw_ring */1994	rc = r820t_write_reg(priv, 0x1f, reg1f);1995	if (rc < 0)1996		return rc;1997 1998	/* mux input freq ~ rf_in freq */1999	rc = r820t_set_mux(priv, (ring_freq - 5300) * 1000);2000	if (rc < 0)2001		return rc;2002 2003	rc = r820t_set_pll(priv, V4L2_TUNER_DIGITAL_TV,2004			   (ring_freq - 5300) * 1000);2005	if (!priv->has_lock)2006		rc = -EINVAL;2007	if (rc < 0)2008		return rc;2009 2010	if (im_flag) {2011		rc = r820t_iq(priv, &imr_point);2012	} else {2013		imr_point.gain_x  = priv->imr_data[3].gain_x;2014		imr_point.phase_y = priv->imr_data[3].phase_y;2015		imr_point.value   = priv->imr_data[3].value;2016 2017		rc = r820t_f_imr(priv, &imr_point);2018	}2019	if (rc < 0)2020		return rc;2021 2022	/* save IMR value */2023	switch (imr_mem) {2024	case 0:2025		priv->imr_data[0].gain_x  = imr_point.gain_x;2026		priv->imr_data[0].phase_y = imr_point.phase_y;2027		priv->imr_data[0].value   = imr_point.value;2028		break;2029	case 1:2030		priv->imr_data[1].gain_x  = imr_point.gain_x;2031		priv->imr_data[1].phase_y = imr_point.phase_y;2032		priv->imr_data[1].value   = imr_point.value;2033		break;2034	case 2:2035		priv->imr_data[2].gain_x  = imr_point.gain_x;2036		priv->imr_data[2].phase_y = imr_point.phase_y;2037		priv->imr_data[2].value   = imr_point.value;2038		break;2039	case 3:2040		priv->imr_data[3].gain_x  = imr_point.gain_x;2041		priv->imr_data[3].phase_y = imr_point.phase_y;2042		priv->imr_data[3].value   = imr_point.value;2043		break;2044	case 4:2045		priv->imr_data[4].gain_x  = imr_point.gain_x;2046		priv->imr_data[4].phase_y = imr_point.phase_y;2047		priv->imr_data[4].value   = imr_point.value;2048		break;2049	default:2050		priv->imr_data[4].gain_x  = imr_point.gain_x;2051		priv->imr_data[4].phase_y = imr_point.phase_y;2052		priv->imr_data[4].value   = imr_point.value;2053		break;2054	}2055 2056	return 0;2057}2058 2059static int r820t_imr_callibrate(struct r820t_priv *priv)2060{2061	int rc, i;2062	int xtal_cap = 0;2063 2064	if (priv->init_done)2065		return 0;2066 2067	/* Detect Xtal capacitance */2068	if ((priv->cfg->rafael_chip == CHIP_R820T) ||2069	    (priv->cfg->rafael_chip == CHIP_R828S) ||2070	    (priv->cfg->rafael_chip == CHIP_R820C)) {2071		priv->xtal_cap_sel = XTAL_HIGH_CAP_0P;2072	} else {2073		/* Initialize registers */2074		rc = r820t_write(priv, 0x05,2075				r820t_init_array, sizeof(r820t_init_array));2076		if (rc < 0)2077			return rc;2078		for (i = 0; i < 3; i++) {2079			rc = r820t_xtal_check(priv);2080			if (rc < 0)2081				return rc;2082			if (!i || rc > xtal_cap)2083				xtal_cap = rc;2084		}2085		priv->xtal_cap_sel = xtal_cap;2086	}2087 2088	/*2089	 * Disables IMR calibration. That emulates the same behaviour2090	 * as what is done by rtl-sdr userspace library. Useful for testing2091	 */2092	if (no_imr_cal) {2093		priv->init_done = true;2094 2095		return 0;2096	}2097 2098	/* Initialize registers */2099	rc = r820t_write(priv, 0x05,2100			 r820t_init_array, sizeof(r820t_init_array));2101	if (rc < 0)2102		return rc;2103 2104	rc = r820t_imr_prepare(priv);2105	if (rc < 0)2106		return rc;2107 2108	rc = r820t_imr(priv, 3, true);2109	if (rc < 0)2110		return rc;2111	rc = r820t_imr(priv, 1, false);2112	if (rc < 0)2113		return rc;2114	rc = r820t_imr(priv, 0, false);2115	if (rc < 0)2116		return rc;2117	rc = r820t_imr(priv, 2, false);2118	if (rc < 0)2119		return rc;2120	rc = r820t_imr(priv, 4, false);2121	if (rc < 0)2122		return rc;2123 2124	priv->init_done = true;2125	priv->imr_done = true;2126 2127	return 0;2128}2129 2130#if 02131/* Not used, for now */2132static int r820t_gpio(struct r820t_priv *priv, bool enable)2133{2134	return r820t_write_reg_mask(priv, 0x0f, enable ? 1 : 0, 0x01);2135}2136#endif2137 2138/*2139 *  r820t frontend operations and tuner attach code2140 *2141 * All driver locks and i2c control are only in this part of the code2142 */2143 2144static int r820t_init(struct dvb_frontend *fe)2145{2146	struct r820t_priv *priv = fe->tuner_priv;2147	int rc;2148 2149	tuner_dbg("%s:\n", __func__);2150 2151	mutex_lock(&priv->lock);2152	if (fe->ops.i2c_gate_ctrl)2153		fe->ops.i2c_gate_ctrl(fe, 1);2154 2155	rc = r820t_imr_callibrate(priv);2156	if (rc < 0)2157		goto err;2158 2159	/* Initialize registers */2160	rc = r820t_write(priv, 0x05,2161			 r820t_init_array, sizeof(r820t_init_array));2162 2163err:2164	if (fe->ops.i2c_gate_ctrl)2165		fe->ops.i2c_gate_ctrl(fe, 0);2166	mutex_unlock(&priv->lock);2167 2168	if (rc < 0)2169		tuner_dbg("%s: failed=%d\n", __func__, rc);2170	return rc;2171}2172 2173static int r820t_sleep(struct dvb_frontend *fe)2174{2175	struct r820t_priv *priv = fe->tuner_priv;2176	int rc;2177 2178	tuner_dbg("%s:\n", __func__);2179 2180	mutex_lock(&priv->lock);2181	if (fe->ops.i2c_gate_ctrl)2182		fe->ops.i2c_gate_ctrl(fe, 1);2183 2184	rc = r820t_standby(priv);2185 2186	if (fe->ops.i2c_gate_ctrl)2187		fe->ops.i2c_gate_ctrl(fe, 0);2188	mutex_unlock(&priv->lock);2189 2190	tuner_dbg("%s: failed=%d\n", __func__, rc);2191	return rc;2192}2193 2194static int r820t_set_analog_freq(struct dvb_frontend *fe,2195				 struct analog_parameters *p)2196{2197	struct r820t_priv *priv = fe->tuner_priv;2198	unsigned bw;2199	int rc;2200 2201	tuner_dbg("%s called\n", __func__);2202 2203	/* if std is not defined, choose one */2204	if (!p->std)2205		p->std = V4L2_STD_MN;2206 2207	if ((p->std == V4L2_STD_PAL_M) || (p->std == V4L2_STD_NTSC))2208		bw = 6;2209	else2210		bw = 8;2211 2212	mutex_lock(&priv->lock);2213	if (fe->ops.i2c_gate_ctrl)2214		fe->ops.i2c_gate_ctrl(fe, 1);2215 2216	rc = generic_set_freq(fe, 62500l * p->frequency, bw,2217			      V4L2_TUNER_ANALOG_TV, p->std, SYS_UNDEFINED);2218 2219	if (fe->ops.i2c_gate_ctrl)2220		fe->ops.i2c_gate_ctrl(fe, 0);2221	mutex_unlock(&priv->lock);2222 2223	return rc;2224}2225 2226static int r820t_set_params(struct dvb_frontend *fe)2227{2228	struct r820t_priv *priv = fe->tuner_priv;2229	struct dtv_frontend_properties *c = &fe->dtv_property_cache;2230	int rc;2231	unsigned bw;2232 2233	tuner_dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",2234		__func__, c->delivery_system, c->frequency, c->bandwidth_hz);2235 2236	mutex_lock(&priv->lock);2237	if (fe->ops.i2c_gate_ctrl)2238		fe->ops.i2c_gate_ctrl(fe, 1);2239 2240	bw = (c->bandwidth_hz + 500000) / 1000000;2241	if (!bw)2242		bw = 8;2243 2244	rc = generic_set_freq(fe, c->frequency, bw,2245			      V4L2_TUNER_DIGITAL_TV, 0, c->delivery_system);2246 2247	if (fe->ops.i2c_gate_ctrl)2248		fe->ops.i2c_gate_ctrl(fe, 0);2249	mutex_unlock(&priv->lock);2250 2251	if (rc)2252		tuner_dbg("%s: failed=%d\n", __func__, rc);2253	return rc;2254}2255 2256static int r820t_signal(struct dvb_frontend *fe, u16 *strength)2257{2258	struct r820t_priv *priv = fe->tuner_priv;2259	int rc = 0;2260 2261	mutex_lock(&priv->lock);2262	if (fe->ops.i2c_gate_ctrl)2263		fe->ops.i2c_gate_ctrl(fe, 1);2264 2265	if (priv->has_lock) {2266		rc = r820t_read_gain(priv);2267		if (rc < 0)2268			goto err;2269 2270		/* A higher gain at LNA means a lower signal strength */2271		*strength = (45 - rc) << 4 | 0xff;2272		if (*strength == 0xff)2273			*strength = 0;2274	} else {2275		*strength = 0;2276	}2277 2278err:2279	if (fe->ops.i2c_gate_ctrl)2280		fe->ops.i2c_gate_ctrl(fe, 0);2281	mutex_unlock(&priv->lock);2282 2283	tuner_dbg("%s: %s, gain=%d strength=%d\n",2284		  __func__,2285		  priv->has_lock ? "PLL locked" : "no signal",2286		  rc, *strength);2287 2288	return 0;2289}2290 2291static int r820t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)2292{2293	struct r820t_priv *priv = fe->tuner_priv;2294 2295	tuner_dbg("%s:\n", __func__);2296 2297	*frequency = priv->int_freq;2298 2299	return 0;2300}2301 2302static void r820t_release(struct dvb_frontend *fe)2303{2304	struct r820t_priv *priv = fe->tuner_priv;2305 2306	tuner_dbg("%s:\n", __func__);2307 2308	mutex_lock(&r820t_list_mutex);2309 2310	if (priv)2311		hybrid_tuner_release_state(priv);2312 2313	mutex_unlock(&r820t_list_mutex);2314 2315	fe->tuner_priv = NULL;2316}2317 2318static const struct dvb_tuner_ops r820t_tuner_ops = {2319	.info = {2320		.name             = "Rafael Micro R820T",2321		.frequency_min_hz =   42 * MHz,2322		.frequency_max_hz = 1002 * MHz,2323	},2324	.init = r820t_init,2325	.release = r820t_release,2326	.sleep = r820t_sleep,2327	.set_params = r820t_set_params,2328	.set_analog_params = r820t_set_analog_freq,2329	.get_if_frequency = r820t_get_if_frequency,2330	.get_rf_strength = r820t_signal,2331};2332 2333struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,2334				  struct i2c_adapter *i2c,2335				  const struct r820t_config *cfg)2336{2337	struct r820t_priv *priv;2338	int rc = -ENODEV;2339	u8 data[5];2340	int instance;2341 2342	mutex_lock(&r820t_list_mutex);2343 2344	instance = hybrid_tuner_request_state(struct r820t_priv, priv,2345					      hybrid_tuner_instance_list,2346					      i2c, cfg->i2c_addr,2347					      "r820t");2348	switch (instance) {2349	case 0:2350		/* memory allocation failure */2351		goto err_no_gate;2352	case 1:2353		/* new tuner instance */2354		priv->cfg = cfg;2355 2356		mutex_init(&priv->lock);2357 2358		fe->tuner_priv = priv;2359		break;2360	case 2:2361		/* existing tuner instance */2362		fe->tuner_priv = priv;2363		break;2364	}2365 2366	if (fe->ops.i2c_gate_ctrl)2367		fe->ops.i2c_gate_ctrl(fe, 1);2368 2369	/* check if the tuner is there */2370	rc = r820t_read(priv, 0x00, data, sizeof(data));2371	if (rc < 0)2372		goto err;2373 2374	rc = r820t_sleep(fe);2375	if (rc < 0)2376		goto err;2377 2378	tuner_info(2379		"Rafael Micro r820t successfully identified, chip type: %s\n",2380		r820t_chip_enum_to_str(cfg->rafael_chip));2381 2382	if (fe->ops.i2c_gate_ctrl)2383		fe->ops.i2c_gate_ctrl(fe, 0);2384 2385	mutex_unlock(&r820t_list_mutex);2386 2387	memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops,2388			sizeof(struct dvb_tuner_ops));2389 2390	return fe;2391err:2392	if (fe->ops.i2c_gate_ctrl)2393		fe->ops.i2c_gate_ctrl(fe, 0);2394 2395err_no_gate:2396	mutex_unlock(&r820t_list_mutex);2397 2398	pr_info("%s: failed=%d\n", __func__, rc);2399	r820t_release(fe);2400	return NULL;2401}2402EXPORT_SYMBOL_GPL(r820t_attach);2403 2404MODULE_DESCRIPTION("Rafael Micro r820t silicon tuner driver");2405MODULE_AUTHOR("Mauro Carvalho Chehab");2406MODULE_LICENSE("GPL v2");2407