162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Driver for mt2063 Micronas tuner
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2011 Mauro Carvalho Chehab
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This driver came from a driver originally written by:
862306a36Sopenharmony_ci *		Henry Wang <Henry.wang@AzureWave.com>
962306a36Sopenharmony_ci * Made publicly available by Terratec, at:
1062306a36Sopenharmony_ci *	http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/string.h>
1762306a36Sopenharmony_ci#include <linux/videodev2.h>
1862306a36Sopenharmony_ci#include <linux/gcd.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "mt2063.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic unsigned int debug;
2362306a36Sopenharmony_cimodule_param(debug, int, 0644);
2462306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Set Verbosity level");
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define dprintk(level, fmt, arg...) do {				\
2762306a36Sopenharmony_ciif (debug >= level)							\
2862306a36Sopenharmony_ci	printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg);	\
2962306a36Sopenharmony_ci} while (0)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* positive error codes used internally */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/*  Info: Unavoidable LO-related spur may be present in the output  */
3562306a36Sopenharmony_ci#define MT2063_SPUR_PRESENT_ERR             (0x00800000)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*  Info: Mask of bits used for # of LO-related spurs that were avoided during tuning  */
3862306a36Sopenharmony_ci#define MT2063_SPUR_CNT_MASK                (0x001f0000)
3962306a36Sopenharmony_ci#define MT2063_SPUR_SHIFT                   (16)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/*  Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
4262306a36Sopenharmony_ci#define MT2063_UPC_RANGE                    (0x04000000)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*  Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
4562306a36Sopenharmony_ci#define MT2063_DNC_RANGE                    (0x08000000)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci *  Constant defining the version of the following structure
4962306a36Sopenharmony_ci *  and therefore the API for this code.
5062306a36Sopenharmony_ci *
5162306a36Sopenharmony_ci *  When compiling the tuner driver, the preprocessor will
5262306a36Sopenharmony_ci *  check against this version number to make sure that
5362306a36Sopenharmony_ci *  it matches the version that the tuner driver knows about.
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* DECT Frequency Avoidance */
5762306a36Sopenharmony_ci#define MT2063_DECT_AVOID_US_FREQS      0x00000001
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define MT2063_DECT_AVOID_EURO_FREQS    0x00000002
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cienum MT2063_DECT_Avoid_Type {
6662306a36Sopenharmony_ci	MT2063_NO_DECT_AVOIDANCE = 0,				/* Do not create DECT exclusion zones.     */
6762306a36Sopenharmony_ci	MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS,	/* Avoid US DECT frequencies.              */
6862306a36Sopenharmony_ci	MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS,	/* Avoid European DECT frequencies.        */
6962306a36Sopenharmony_ci	MT2063_AVOID_BOTH					/* Avoid both regions. Not typically used. */
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define MT2063_MAX_ZONES 48
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistruct MT2063_ExclZone_t {
7562306a36Sopenharmony_ci	u32 min_;
7662306a36Sopenharmony_ci	u32 max_;
7762306a36Sopenharmony_ci	struct MT2063_ExclZone_t *next_;
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/*
8162306a36Sopenharmony_ci *  Structure of data needed for Spur Avoidance
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_cistruct MT2063_AvoidSpursData_t {
8462306a36Sopenharmony_ci	u32 f_ref;
8562306a36Sopenharmony_ci	u32 f_in;
8662306a36Sopenharmony_ci	u32 f_LO1;
8762306a36Sopenharmony_ci	u32 f_if1_Center;
8862306a36Sopenharmony_ci	u32 f_if1_Request;
8962306a36Sopenharmony_ci	u32 f_if1_bw;
9062306a36Sopenharmony_ci	u32 f_LO2;
9162306a36Sopenharmony_ci	u32 f_out;
9262306a36Sopenharmony_ci	u32 f_out_bw;
9362306a36Sopenharmony_ci	u32 f_LO1_Step;
9462306a36Sopenharmony_ci	u32 f_LO2_Step;
9562306a36Sopenharmony_ci	u32 f_LO1_FracN_Avoid;
9662306a36Sopenharmony_ci	u32 f_LO2_FracN_Avoid;
9762306a36Sopenharmony_ci	u32 f_zif_bw;
9862306a36Sopenharmony_ci	u32 f_min_LO_Separation;
9962306a36Sopenharmony_ci	u32 maxH1;
10062306a36Sopenharmony_ci	u32 maxH2;
10162306a36Sopenharmony_ci	enum MT2063_DECT_Avoid_Type avoidDECT;
10262306a36Sopenharmony_ci	u32 bSpurPresent;
10362306a36Sopenharmony_ci	u32 bSpurAvoided;
10462306a36Sopenharmony_ci	u32 nSpursFound;
10562306a36Sopenharmony_ci	u32 nZones;
10662306a36Sopenharmony_ci	struct MT2063_ExclZone_t *freeZones;
10762306a36Sopenharmony_ci	struct MT2063_ExclZone_t *usedZones;
10862306a36Sopenharmony_ci	struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/*
11262306a36Sopenharmony_ci * Parameter for function MT2063_SetPowerMask that specifies the power down
11362306a36Sopenharmony_ci * of various sections of the MT2063.
11462306a36Sopenharmony_ci */
11562306a36Sopenharmony_cienum MT2063_Mask_Bits {
11662306a36Sopenharmony_ci	MT2063_REG_SD = 0x0040,		/* Shutdown regulator                 */
11762306a36Sopenharmony_ci	MT2063_SRO_SD = 0x0020,		/* Shutdown SRO                       */
11862306a36Sopenharmony_ci	MT2063_AFC_SD = 0x0010,		/* Shutdown AFC A/D                   */
11962306a36Sopenharmony_ci	MT2063_PD_SD = 0x0002,		/* Enable power detector shutdown     */
12062306a36Sopenharmony_ci	MT2063_PDADC_SD = 0x0001,	/* Enable power detector A/D shutdown */
12162306a36Sopenharmony_ci	MT2063_VCO_SD = 0x8000,		/* Enable VCO shutdown                */
12262306a36Sopenharmony_ci	MT2063_LTX_SD = 0x4000,		/* Enable LTX shutdown                */
12362306a36Sopenharmony_ci	MT2063_LT1_SD = 0x2000,		/* Enable LT1 shutdown                */
12462306a36Sopenharmony_ci	MT2063_LNA_SD = 0x1000,		/* Enable LNA shutdown                */
12562306a36Sopenharmony_ci	MT2063_UPC_SD = 0x0800,		/* Enable upconverter shutdown        */
12662306a36Sopenharmony_ci	MT2063_DNC_SD = 0x0400,		/* Enable downconverter shutdown      */
12762306a36Sopenharmony_ci	MT2063_VGA_SD = 0x0200,		/* Enable VGA shutdown                */
12862306a36Sopenharmony_ci	MT2063_AMP_SD = 0x0100,		/* Enable AMP shutdown                */
12962306a36Sopenharmony_ci	MT2063_ALL_SD = 0xFF73,		/* All shutdown bits for this tuner   */
13062306a36Sopenharmony_ci	MT2063_NONE_SD = 0x0000		/* No shutdown bits                   */
13162306a36Sopenharmony_ci};
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/*
13462306a36Sopenharmony_ci *  Possible values for MT2063_DNC_OUTPUT
13562306a36Sopenharmony_ci */
13662306a36Sopenharmony_cienum MT2063_DNC_Output_Enable {
13762306a36Sopenharmony_ci	MT2063_DNC_NONE = 0,
13862306a36Sopenharmony_ci	MT2063_DNC_1,
13962306a36Sopenharmony_ci	MT2063_DNC_2,
14062306a36Sopenharmony_ci	MT2063_DNC_BOTH
14162306a36Sopenharmony_ci};
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci/*
14462306a36Sopenharmony_ci *  Two-wire serial bus subaddresses of the tuner registers.
14562306a36Sopenharmony_ci *  Also known as the tuner's register addresses.
14662306a36Sopenharmony_ci */
14762306a36Sopenharmony_cienum MT2063_Register_Offsets {
14862306a36Sopenharmony_ci	MT2063_REG_PART_REV = 0,	/*  0x00: Part/Rev Code         */
14962306a36Sopenharmony_ci	MT2063_REG_LO1CQ_1,		/*  0x01: LO1C Queued Byte 1    */
15062306a36Sopenharmony_ci	MT2063_REG_LO1CQ_2,		/*  0x02: LO1C Queued Byte 2    */
15162306a36Sopenharmony_ci	MT2063_REG_LO2CQ_1,		/*  0x03: LO2C Queued Byte 1    */
15262306a36Sopenharmony_ci	MT2063_REG_LO2CQ_2,		/*  0x04: LO2C Queued Byte 2    */
15362306a36Sopenharmony_ci	MT2063_REG_LO2CQ_3,		/*  0x05: LO2C Queued Byte 3    */
15462306a36Sopenharmony_ci	MT2063_REG_RSVD_06,		/*  0x06: Reserved              */
15562306a36Sopenharmony_ci	MT2063_REG_LO_STATUS,		/*  0x07: LO Status             */
15662306a36Sopenharmony_ci	MT2063_REG_FIFFC,		/*  0x08: FIFF Center           */
15762306a36Sopenharmony_ci	MT2063_REG_CLEARTUNE,		/*  0x09: ClearTune Filter      */
15862306a36Sopenharmony_ci	MT2063_REG_ADC_OUT,		/*  0x0A: ADC_OUT               */
15962306a36Sopenharmony_ci	MT2063_REG_LO1C_1,		/*  0x0B: LO1C Byte 1           */
16062306a36Sopenharmony_ci	MT2063_REG_LO1C_2,		/*  0x0C: LO1C Byte 2           */
16162306a36Sopenharmony_ci	MT2063_REG_LO2C_1,		/*  0x0D: LO2C Byte 1           */
16262306a36Sopenharmony_ci	MT2063_REG_LO2C_2,		/*  0x0E: LO2C Byte 2           */
16362306a36Sopenharmony_ci	MT2063_REG_LO2C_3,		/*  0x0F: LO2C Byte 3           */
16462306a36Sopenharmony_ci	MT2063_REG_RSVD_10,		/*  0x10: Reserved              */
16562306a36Sopenharmony_ci	MT2063_REG_PWR_1,		/*  0x11: PWR Byte 1            */
16662306a36Sopenharmony_ci	MT2063_REG_PWR_2,		/*  0x12: PWR Byte 2            */
16762306a36Sopenharmony_ci	MT2063_REG_TEMP_STATUS,		/*  0x13: Temp Status           */
16862306a36Sopenharmony_ci	MT2063_REG_XO_STATUS,		/*  0x14: Crystal Status        */
16962306a36Sopenharmony_ci	MT2063_REG_RF_STATUS,		/*  0x15: RF Attn Status        */
17062306a36Sopenharmony_ci	MT2063_REG_FIF_STATUS,		/*  0x16: FIF Attn Status       */
17162306a36Sopenharmony_ci	MT2063_REG_LNA_OV,		/*  0x17: LNA Attn Override     */
17262306a36Sopenharmony_ci	MT2063_REG_RF_OV,		/*  0x18: RF Attn Override      */
17362306a36Sopenharmony_ci	MT2063_REG_FIF_OV,		/*  0x19: FIF Attn Override     */
17462306a36Sopenharmony_ci	MT2063_REG_LNA_TGT,		/*  0x1A: Reserved              */
17562306a36Sopenharmony_ci	MT2063_REG_PD1_TGT,		/*  0x1B: Pwr Det 1 Target      */
17662306a36Sopenharmony_ci	MT2063_REG_PD2_TGT,		/*  0x1C: Pwr Det 2 Target      */
17762306a36Sopenharmony_ci	MT2063_REG_RSVD_1D,		/*  0x1D: Reserved              */
17862306a36Sopenharmony_ci	MT2063_REG_RSVD_1E,		/*  0x1E: Reserved              */
17962306a36Sopenharmony_ci	MT2063_REG_RSVD_1F,		/*  0x1F: Reserved              */
18062306a36Sopenharmony_ci	MT2063_REG_RSVD_20,		/*  0x20: Reserved              */
18162306a36Sopenharmony_ci	MT2063_REG_BYP_CTRL,		/*  0x21: Bypass Control        */
18262306a36Sopenharmony_ci	MT2063_REG_RSVD_22,		/*  0x22: Reserved              */
18362306a36Sopenharmony_ci	MT2063_REG_RSVD_23,		/*  0x23: Reserved              */
18462306a36Sopenharmony_ci	MT2063_REG_RSVD_24,		/*  0x24: Reserved              */
18562306a36Sopenharmony_ci	MT2063_REG_RSVD_25,		/*  0x25: Reserved              */
18662306a36Sopenharmony_ci	MT2063_REG_RSVD_26,		/*  0x26: Reserved              */
18762306a36Sopenharmony_ci	MT2063_REG_RSVD_27,		/*  0x27: Reserved              */
18862306a36Sopenharmony_ci	MT2063_REG_FIFF_CTRL,		/*  0x28: FIFF Control          */
18962306a36Sopenharmony_ci	MT2063_REG_FIFF_OFFSET,		/*  0x29: FIFF Offset           */
19062306a36Sopenharmony_ci	MT2063_REG_CTUNE_CTRL,		/*  0x2A: Reserved              */
19162306a36Sopenharmony_ci	MT2063_REG_CTUNE_OV,		/*  0x2B: Reserved              */
19262306a36Sopenharmony_ci	MT2063_REG_CTRL_2C,		/*  0x2C: Reserved              */
19362306a36Sopenharmony_ci	MT2063_REG_FIFF_CTRL2,		/*  0x2D: Fiff Control          */
19462306a36Sopenharmony_ci	MT2063_REG_RSVD_2E,		/*  0x2E: Reserved              */
19562306a36Sopenharmony_ci	MT2063_REG_DNC_GAIN,		/*  0x2F: DNC Control           */
19662306a36Sopenharmony_ci	MT2063_REG_VGA_GAIN,		/*  0x30: VGA Gain Ctrl         */
19762306a36Sopenharmony_ci	MT2063_REG_RSVD_31,		/*  0x31: Reserved              */
19862306a36Sopenharmony_ci	MT2063_REG_TEMP_SEL,		/*  0x32: Temperature Selection */
19962306a36Sopenharmony_ci	MT2063_REG_RSVD_33,		/*  0x33: Reserved              */
20062306a36Sopenharmony_ci	MT2063_REG_RSVD_34,		/*  0x34: Reserved              */
20162306a36Sopenharmony_ci	MT2063_REG_RSVD_35,		/*  0x35: Reserved              */
20262306a36Sopenharmony_ci	MT2063_REG_RSVD_36,		/*  0x36: Reserved              */
20362306a36Sopenharmony_ci	MT2063_REG_RSVD_37,		/*  0x37: Reserved              */
20462306a36Sopenharmony_ci	MT2063_REG_RSVD_38,		/*  0x38: Reserved              */
20562306a36Sopenharmony_ci	MT2063_REG_RSVD_39,		/*  0x39: Reserved              */
20662306a36Sopenharmony_ci	MT2063_REG_RSVD_3A,		/*  0x3A: Reserved              */
20762306a36Sopenharmony_ci	MT2063_REG_RSVD_3B,		/*  0x3B: Reserved              */
20862306a36Sopenharmony_ci	MT2063_REG_RSVD_3C,		/*  0x3C: Reserved              */
20962306a36Sopenharmony_ci	MT2063_REG_END_REGS
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistruct mt2063_state {
21362306a36Sopenharmony_ci	struct i2c_adapter *i2c;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	bool init;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	const struct mt2063_config *config;
21862306a36Sopenharmony_ci	struct dvb_tuner_ops ops;
21962306a36Sopenharmony_ci	struct dvb_frontend *frontend;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	u32 frequency;
22262306a36Sopenharmony_ci	u32 srate;
22362306a36Sopenharmony_ci	u32 bandwidth;
22462306a36Sopenharmony_ci	u32 reference;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	u32 tuner_id;
22762306a36Sopenharmony_ci	struct MT2063_AvoidSpursData_t AS_Data;
22862306a36Sopenharmony_ci	u32 f_IF1_actual;
22962306a36Sopenharmony_ci	u32 rcvr_mode;
23062306a36Sopenharmony_ci	u32 ctfilt_sw;
23162306a36Sopenharmony_ci	u32 CTFiltMax[31];
23262306a36Sopenharmony_ci	u32 num_regs;
23362306a36Sopenharmony_ci	u8 reg[MT2063_REG_END_REGS];
23462306a36Sopenharmony_ci};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/*
23762306a36Sopenharmony_ci * mt2063_write - Write data into the I2C bus
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_cistatic int mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	struct dvb_frontend *fe = state->frontend;
24262306a36Sopenharmony_ci	int ret;
24362306a36Sopenharmony_ci	u8 buf[60];
24462306a36Sopenharmony_ci	struct i2c_msg msg = {
24562306a36Sopenharmony_ci		.addr = state->config->tuner_address,
24662306a36Sopenharmony_ci		.flags = 0,
24762306a36Sopenharmony_ci		.buf = buf,
24862306a36Sopenharmony_ci		.len = len + 1
24962306a36Sopenharmony_ci	};
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	dprintk(2, "\n");
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	msg.buf[0] = reg;
25462306a36Sopenharmony_ci	memcpy(msg.buf + 1, data, len);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
25762306a36Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
25862306a36Sopenharmony_ci	ret = i2c_transfer(state->i2c, &msg, 1);
25962306a36Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
26062306a36Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 0);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (ret < 0)
26362306a36Sopenharmony_ci		printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	return ret;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci/*
26962306a36Sopenharmony_ci * mt2063_write - Write register data into the I2C bus, caching the value
27062306a36Sopenharmony_ci */
27162306a36Sopenharmony_cistatic int mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	int status;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	dprintk(2, "\n");
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	if (reg >= MT2063_REG_END_REGS)
27862306a36Sopenharmony_ci		return -ERANGE;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	status = mt2063_write(state, reg, &val, 1);
28162306a36Sopenharmony_ci	if (status < 0)
28262306a36Sopenharmony_ci		return status;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	state->reg[reg] = val;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	return 0;
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci/*
29062306a36Sopenharmony_ci * mt2063_read - Read data from the I2C bus
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_cistatic int mt2063_read(struct mt2063_state *state,
29362306a36Sopenharmony_ci			   u8 subAddress, u8 *pData, u32 cnt)
29462306a36Sopenharmony_ci{
29562306a36Sopenharmony_ci	int status = 0;	/* Status to be returned        */
29662306a36Sopenharmony_ci	struct dvb_frontend *fe = state->frontend;
29762306a36Sopenharmony_ci	u32 i = 0;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	dprintk(2, "addr 0x%02x, cnt %d\n", subAddress, cnt);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
30262306a36Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	for (i = 0; i < cnt; i++) {
30562306a36Sopenharmony_ci		u8 b0[] = { subAddress + i };
30662306a36Sopenharmony_ci		struct i2c_msg msg[] = {
30762306a36Sopenharmony_ci			{
30862306a36Sopenharmony_ci				.addr = state->config->tuner_address,
30962306a36Sopenharmony_ci				.flags = 0,
31062306a36Sopenharmony_ci				.buf = b0,
31162306a36Sopenharmony_ci				.len = 1
31262306a36Sopenharmony_ci			}, {
31362306a36Sopenharmony_ci				.addr = state->config->tuner_address,
31462306a36Sopenharmony_ci				.flags = I2C_M_RD,
31562306a36Sopenharmony_ci				.buf = pData + i,
31662306a36Sopenharmony_ci				.len = 1
31762306a36Sopenharmony_ci			}
31862306a36Sopenharmony_ci		};
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci		status = i2c_transfer(state->i2c, msg, 2);
32162306a36Sopenharmony_ci		dprintk(2, "addr 0x%02x, ret = %d, val = 0x%02x\n",
32262306a36Sopenharmony_ci			   subAddress + i, status, *(pData + i));
32362306a36Sopenharmony_ci		if (status < 0)
32462306a36Sopenharmony_ci			break;
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
32762306a36Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 0);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	if (status < 0)
33062306a36Sopenharmony_ci		printk(KERN_ERR "Can't read from address 0x%02x,\n",
33162306a36Sopenharmony_ci		       subAddress + i);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	return status;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci/*
33762306a36Sopenharmony_ci * FIXME: Is this really needed?
33862306a36Sopenharmony_ci */
33962306a36Sopenharmony_cistatic int MT2063_Sleep(struct dvb_frontend *fe)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	/*
34262306a36Sopenharmony_ci	 *  ToDo:  Add code here to implement a OS blocking
34362306a36Sopenharmony_ci	 */
34462306a36Sopenharmony_ci	msleep(100);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	return 0;
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci/*
35062306a36Sopenharmony_ci * Microtune spur avoidance
35162306a36Sopenharmony_ci */
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci/*  Implement ceiling, floor functions.  */
35462306a36Sopenharmony_ci#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
35562306a36Sopenharmony_ci#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistruct MT2063_FIFZone_t {
35862306a36Sopenharmony_ci	s32 min_;
35962306a36Sopenharmony_ci	s32 max_;
36062306a36Sopenharmony_ci};
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
36362306a36Sopenharmony_ci					    *pAS_Info,
36462306a36Sopenharmony_ci					    struct MT2063_ExclZone_t *pPrevNode)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	struct MT2063_ExclZone_t *pNode;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	dprintk(2, "\n");
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	/*  Check for a node in the free list  */
37162306a36Sopenharmony_ci	if (pAS_Info->freeZones != NULL) {
37262306a36Sopenharmony_ci		/*  Use one from the free list  */
37362306a36Sopenharmony_ci		pNode = pAS_Info->freeZones;
37462306a36Sopenharmony_ci		pAS_Info->freeZones = pNode->next_;
37562306a36Sopenharmony_ci	} else {
37662306a36Sopenharmony_ci		/*  Grab a node from the array  */
37762306a36Sopenharmony_ci		pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	if (pPrevNode != NULL) {
38162306a36Sopenharmony_ci		pNode->next_ = pPrevNode->next_;
38262306a36Sopenharmony_ci		pPrevNode->next_ = pNode;
38362306a36Sopenharmony_ci	} else {		/*  insert at the beginning of the list  */
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci		pNode->next_ = pAS_Info->usedZones;
38662306a36Sopenharmony_ci		pAS_Info->usedZones = pNode;
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	pAS_Info->nZones++;
39062306a36Sopenharmony_ci	return pNode;
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
39462306a36Sopenharmony_ci					    *pAS_Info,
39562306a36Sopenharmony_ci					    struct MT2063_ExclZone_t *pPrevNode,
39662306a36Sopenharmony_ci					    struct MT2063_ExclZone_t
39762306a36Sopenharmony_ci					    *pNodeToRemove)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	dprintk(2, "\n");
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	/*  Make previous node point to the subsequent node  */
40462306a36Sopenharmony_ci	if (pPrevNode != NULL)
40562306a36Sopenharmony_ci		pPrevNode->next_ = pNext;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	/*  Add pNodeToRemove to the beginning of the freeZones  */
40862306a36Sopenharmony_ci	pNodeToRemove->next_ = pAS_Info->freeZones;
40962306a36Sopenharmony_ci	pAS_Info->freeZones = pNodeToRemove;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	/*  Decrement node count  */
41262306a36Sopenharmony_ci	pAS_Info->nZones--;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	return pNext;
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci/*
41862306a36Sopenharmony_ci * MT_AddExclZone()
41962306a36Sopenharmony_ci *
42062306a36Sopenharmony_ci * Add (and merge) an exclusion zone into the list.
42162306a36Sopenharmony_ci * If the range (f_min, f_max) is totally outside the
42262306a36Sopenharmony_ci * 1st IF BW, ignore the entry.
42362306a36Sopenharmony_ci * If the range (f_min, f_max) is negative, ignore the entry.
42462306a36Sopenharmony_ci */
42562306a36Sopenharmony_cistatic void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
42662306a36Sopenharmony_ci			       u32 f_min, u32 f_max)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
42962306a36Sopenharmony_ci	struct MT2063_ExclZone_t *pPrev = NULL;
43062306a36Sopenharmony_ci	struct MT2063_ExclZone_t *pNext = NULL;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	dprintk(2, "\n");
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	/*  Check to see if this overlaps the 1st IF filter  */
43562306a36Sopenharmony_ci	if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
43662306a36Sopenharmony_ci	    && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
43762306a36Sopenharmony_ci	    && (f_min < f_max)) {
43862306a36Sopenharmony_ci		/*
43962306a36Sopenharmony_ci		 *                1        2         3      4       5        6
44062306a36Sopenharmony_ci		 *
44162306a36Sopenharmony_ci		 *   New entry:  |---|    |--|      |--|    |-|    |---|    |--|
44262306a36Sopenharmony_ci		 *                or       or        or     or      or
44362306a36Sopenharmony_ci		 *   Existing:  |--|      |--|      |--|    |---|  |-|      |--|
44462306a36Sopenharmony_ci		 */
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		/*  Check for our place in the list  */
44762306a36Sopenharmony_ci		while ((pNode != NULL) && (pNode->max_ < f_min)) {
44862306a36Sopenharmony_ci			pPrev = pNode;
44962306a36Sopenharmony_ci			pNode = pNode->next_;
45062306a36Sopenharmony_ci		}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci		if ((pNode != NULL) && (pNode->min_ < f_max)) {
45362306a36Sopenharmony_ci			/*  Combine me with pNode  */
45462306a36Sopenharmony_ci			if (f_min < pNode->min_)
45562306a36Sopenharmony_ci				pNode->min_ = f_min;
45662306a36Sopenharmony_ci			if (f_max > pNode->max_)
45762306a36Sopenharmony_ci				pNode->max_ = f_max;
45862306a36Sopenharmony_ci		} else {
45962306a36Sopenharmony_ci			pNode = InsertNode(pAS_Info, pPrev);
46062306a36Sopenharmony_ci			pNode->min_ = f_min;
46162306a36Sopenharmony_ci			pNode->max_ = f_max;
46262306a36Sopenharmony_ci		}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci		/*  Look for merging possibilities  */
46562306a36Sopenharmony_ci		pNext = pNode->next_;
46662306a36Sopenharmony_ci		while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
46762306a36Sopenharmony_ci			if (pNext->max_ > pNode->max_)
46862306a36Sopenharmony_ci				pNode->max_ = pNext->max_;
46962306a36Sopenharmony_ci			/*  Remove pNext, return ptr to pNext->next  */
47062306a36Sopenharmony_ci			pNext = RemoveNode(pAS_Info, pNode, pNext);
47162306a36Sopenharmony_ci		}
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci/*
47662306a36Sopenharmony_ci *  Reset all exclusion zones.
47762306a36Sopenharmony_ci *  Add zones to protect the PLL FracN regions near zero
47862306a36Sopenharmony_ci */
47962306a36Sopenharmony_cistatic void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
48062306a36Sopenharmony_ci{
48162306a36Sopenharmony_ci	u32 center;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	dprintk(2, "\n");
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	pAS_Info->nZones = 0;	/*  this clears the used list  */
48662306a36Sopenharmony_ci	pAS_Info->usedZones = NULL;	/*  reset ptr                  */
48762306a36Sopenharmony_ci	pAS_Info->freeZones = NULL;	/*  reset ptr                  */
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	center =
49062306a36Sopenharmony_ci	    pAS_Info->f_ref *
49162306a36Sopenharmony_ci	    ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
49262306a36Sopenharmony_ci	      pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
49362306a36Sopenharmony_ci	while (center <
49462306a36Sopenharmony_ci	       pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
49562306a36Sopenharmony_ci	       pAS_Info->f_LO1_FracN_Avoid) {
49662306a36Sopenharmony_ci		/*  Exclude LO1 FracN  */
49762306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info,
49862306a36Sopenharmony_ci				   center - pAS_Info->f_LO1_FracN_Avoid,
49962306a36Sopenharmony_ci				   center - 1);
50062306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, center + 1,
50162306a36Sopenharmony_ci				   center + pAS_Info->f_LO1_FracN_Avoid);
50262306a36Sopenharmony_ci		center += pAS_Info->f_ref;
50362306a36Sopenharmony_ci	}
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	center =
50662306a36Sopenharmony_ci	    pAS_Info->f_ref *
50762306a36Sopenharmony_ci	    ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
50862306a36Sopenharmony_ci	      pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
50962306a36Sopenharmony_ci	while (center <
51062306a36Sopenharmony_ci	       pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
51162306a36Sopenharmony_ci	       pAS_Info->f_LO2_FracN_Avoid) {
51262306a36Sopenharmony_ci		/*  Exclude LO2 FracN  */
51362306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info,
51462306a36Sopenharmony_ci				   center - pAS_Info->f_LO2_FracN_Avoid,
51562306a36Sopenharmony_ci				   center - 1);
51662306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, center + 1,
51762306a36Sopenharmony_ci				   center + pAS_Info->f_LO2_FracN_Avoid);
51862306a36Sopenharmony_ci		center += pAS_Info->f_ref;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
52262306a36Sopenharmony_ci		/*  Exclude LO1 values that conflict with DECT channels */
52362306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in);	/* Ctr = 1921.536 */
52462306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in);	/* Ctr = 1923.264 */
52562306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in);	/* Ctr = 1924.992 */
52662306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in);	/* Ctr = 1926.720 */
52762306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in);	/* Ctr = 1928.448 */
52862306a36Sopenharmony_ci	}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
53162306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in);	/* Ctr = 1897.344 */
53262306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in);	/* Ctr = 1895.616 */
53362306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in);	/* Ctr = 1893.888 */
53462306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in);	/* Ctr = 1892.16  */
53562306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in);	/* Ctr = 1890.432 */
53662306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in);	/* Ctr = 1888.704 */
53762306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in);	/* Ctr = 1886.976 */
53862306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in);	/* Ctr = 1885.248 */
53962306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in);	/* Ctr = 1883.52  */
54062306a36Sopenharmony_ci		MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in);	/* Ctr = 1881.792 */
54162306a36Sopenharmony_ci	}
54262306a36Sopenharmony_ci}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci/*
54562306a36Sopenharmony_ci * MT_ChooseFirstIF - Choose the best available 1st IF
54662306a36Sopenharmony_ci *                    If f_Desired is not excluded, choose that first.
54762306a36Sopenharmony_ci *                    Otherwise, return the value closest to f_Center that is
54862306a36Sopenharmony_ci *                    not excluded
54962306a36Sopenharmony_ci */
55062306a36Sopenharmony_cistatic u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
55162306a36Sopenharmony_ci{
55262306a36Sopenharmony_ci	/*
55362306a36Sopenharmony_ci	 * Update "f_Desired" to be the nearest "combinational-multiple" of
55462306a36Sopenharmony_ci	 * "f_LO1_Step".
55562306a36Sopenharmony_ci	 * The resulting number, F_LO1 must be a multiple of f_LO1_Step.
55662306a36Sopenharmony_ci	 * And F_LO1 is the arithmetic sum of f_in + f_Center.
55762306a36Sopenharmony_ci	 * Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
55862306a36Sopenharmony_ci	 * However, the sum must be.
55962306a36Sopenharmony_ci	 */
56062306a36Sopenharmony_ci	const u32 f_Desired =
56162306a36Sopenharmony_ci	    pAS_Info->f_LO1_Step *
56262306a36Sopenharmony_ci	    ((pAS_Info->f_if1_Request + pAS_Info->f_in +
56362306a36Sopenharmony_ci	      pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
56462306a36Sopenharmony_ci	    pAS_Info->f_in;
56562306a36Sopenharmony_ci	const u32 f_Step =
56662306a36Sopenharmony_ci	    (pAS_Info->f_LO1_Step >
56762306a36Sopenharmony_ci	     pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
56862306a36Sopenharmony_ci	    f_LO2_Step;
56962306a36Sopenharmony_ci	u32 f_Center;
57062306a36Sopenharmony_ci	s32 i;
57162306a36Sopenharmony_ci	s32 j = 0;
57262306a36Sopenharmony_ci	u32 bDesiredExcluded = 0;
57362306a36Sopenharmony_ci	u32 bZeroExcluded = 0;
57462306a36Sopenharmony_ci	s32 tmpMin, tmpMax;
57562306a36Sopenharmony_ci	s32 bestDiff;
57662306a36Sopenharmony_ci	struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
57762306a36Sopenharmony_ci	struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	dprintk(2, "\n");
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	if (pAS_Info->nZones == 0)
58262306a36Sopenharmony_ci		return f_Desired;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	/*
58562306a36Sopenharmony_ci	 *  f_Center needs to be an integer multiple of f_Step away
58662306a36Sopenharmony_ci	 *  from f_Desired
58762306a36Sopenharmony_ci	 */
58862306a36Sopenharmony_ci	if (pAS_Info->f_if1_Center > f_Desired)
58962306a36Sopenharmony_ci		f_Center =
59062306a36Sopenharmony_ci		    f_Desired +
59162306a36Sopenharmony_ci		    f_Step *
59262306a36Sopenharmony_ci		    ((pAS_Info->f_if1_Center - f_Desired +
59362306a36Sopenharmony_ci		      f_Step / 2) / f_Step);
59462306a36Sopenharmony_ci	else
59562306a36Sopenharmony_ci		f_Center =
59662306a36Sopenharmony_ci		    f_Desired -
59762306a36Sopenharmony_ci		    f_Step *
59862306a36Sopenharmony_ci		    ((f_Desired - pAS_Info->f_if1_Center +
59962306a36Sopenharmony_ci		      f_Step / 2) / f_Step);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	/*
60262306a36Sopenharmony_ci	 * Take MT_ExclZones, center around f_Center and change the
60362306a36Sopenharmony_ci	 * resolution to f_Step
60462306a36Sopenharmony_ci	 */
60562306a36Sopenharmony_ci	while (pNode != NULL) {
60662306a36Sopenharmony_ci		/*  floor function  */
60762306a36Sopenharmony_ci		tmpMin =
60862306a36Sopenharmony_ci		    floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci		/*  ceil function  */
61162306a36Sopenharmony_ci		tmpMax =
61262306a36Sopenharmony_ci		    ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
61562306a36Sopenharmony_ci			bDesiredExcluded = 1;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		if ((tmpMin < 0) && (tmpMax > 0))
61862306a36Sopenharmony_ci			bZeroExcluded = 1;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci		/*  See if this zone overlaps the previous  */
62162306a36Sopenharmony_ci		if ((j > 0) && (tmpMin < zones[j - 1].max_))
62262306a36Sopenharmony_ci			zones[j - 1].max_ = tmpMax;
62362306a36Sopenharmony_ci		else {
62462306a36Sopenharmony_ci			/*  Add new zone  */
62562306a36Sopenharmony_ci			zones[j].min_ = tmpMin;
62662306a36Sopenharmony_ci			zones[j].max_ = tmpMax;
62762306a36Sopenharmony_ci			j++;
62862306a36Sopenharmony_ci		}
62962306a36Sopenharmony_ci		pNode = pNode->next_;
63062306a36Sopenharmony_ci	}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	/*
63362306a36Sopenharmony_ci	 *  If the desired is okay, return with it
63462306a36Sopenharmony_ci	 */
63562306a36Sopenharmony_ci	if (bDesiredExcluded == 0)
63662306a36Sopenharmony_ci		return f_Desired;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	/*
63962306a36Sopenharmony_ci	 *  If the desired is excluded and the center is okay, return with it
64062306a36Sopenharmony_ci	 */
64162306a36Sopenharmony_ci	if (bZeroExcluded == 0)
64262306a36Sopenharmony_ci		return f_Center;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	/*  Find the value closest to 0 (f_Center)  */
64562306a36Sopenharmony_ci	bestDiff = zones[0].min_;
64662306a36Sopenharmony_ci	for (i = 0; i < j; i++) {
64762306a36Sopenharmony_ci		if (abs(zones[i].min_) < abs(bestDiff))
64862306a36Sopenharmony_ci			bestDiff = zones[i].min_;
64962306a36Sopenharmony_ci		if (abs(zones[i].max_) < abs(bestDiff))
65062306a36Sopenharmony_ci			bestDiff = zones[i].max_;
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	if (bestDiff < 0)
65462306a36Sopenharmony_ci		return f_Center - ((u32) (-bestDiff) * f_Step);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	return f_Center + (bestDiff * f_Step);
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci/**
66062306a36Sopenharmony_ci * IsSpurInBand() - Checks to see if a spur will be present within the IF's
66162306a36Sopenharmony_ci *                  bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
66262306a36Sopenharmony_ci *
66362306a36Sopenharmony_ci *                    ma   mb                                     mc   md
66462306a36Sopenharmony_ci *                  <--+-+-+-------------------+-------------------+-+-+-->
66562306a36Sopenharmony_ci *                     |   ^                   0                   ^   |
66662306a36Sopenharmony_ci *                     ^   b=-fIFOut+fIFBW/2      -b=+fIFOut-fIFBW/2   ^
66762306a36Sopenharmony_ci *                     a=-fIFOut-fIFBW/2              -a=+fIFOut+fIFBW/2
66862306a36Sopenharmony_ci *
66962306a36Sopenharmony_ci *                  Note that some equations are doubled to prevent round-off
67062306a36Sopenharmony_ci *                  problems when calculating fIFBW/2
67162306a36Sopenharmony_ci *
67262306a36Sopenharmony_ci * @pAS_Info:	Avoid Spurs information block
67362306a36Sopenharmony_ci * @fm:		If spur, amount f_IF1 has to move negative
67462306a36Sopenharmony_ci * @fp:		If spur, amount f_IF1 has to move positive
67562306a36Sopenharmony_ci *
67662306a36Sopenharmony_ci *  Returns 1 if an LO spur would be present, otherwise 0.
67762306a36Sopenharmony_ci */
67862306a36Sopenharmony_cistatic u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
67962306a36Sopenharmony_ci			u32 *fm, u32 * fp)
68062306a36Sopenharmony_ci{
68162306a36Sopenharmony_ci	/*
68262306a36Sopenharmony_ci	 **  Calculate LO frequency settings.
68362306a36Sopenharmony_ci	 */
68462306a36Sopenharmony_ci	u32 n, n0;
68562306a36Sopenharmony_ci	const u32 f_LO1 = pAS_Info->f_LO1;
68662306a36Sopenharmony_ci	const u32 f_LO2 = pAS_Info->f_LO2;
68762306a36Sopenharmony_ci	const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
68862306a36Sopenharmony_ci	const u32 c = d - pAS_Info->f_out_bw;
68962306a36Sopenharmony_ci	const u32 f = pAS_Info->f_zif_bw / 2;
69062306a36Sopenharmony_ci	const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
69162306a36Sopenharmony_ci	s32 f_nsLO1, f_nsLO2;
69262306a36Sopenharmony_ci	s32 f_Spur;
69362306a36Sopenharmony_ci	u32 ma, mb, mc, md, me, mf;
69462306a36Sopenharmony_ci	u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	dprintk(2, "\n");
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	*fm = 0;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	/*
70162306a36Sopenharmony_ci	 ** For each edge (d, c & f), calculate a scale, based on the gcd
70262306a36Sopenharmony_ci	 ** of f_LO1, f_LO2 and the edge value.  Use the larger of this
70362306a36Sopenharmony_ci	 ** gcd-based scale factor or f_Scale.
70462306a36Sopenharmony_ci	 */
70562306a36Sopenharmony_ci	lo_gcd = gcd(f_LO1, f_LO2);
70662306a36Sopenharmony_ci	gd_Scale = max((u32) gcd(lo_gcd, d), f_Scale);
70762306a36Sopenharmony_ci	hgds = gd_Scale / 2;
70862306a36Sopenharmony_ci	gc_Scale = max((u32) gcd(lo_gcd, c), f_Scale);
70962306a36Sopenharmony_ci	hgcs = gc_Scale / 2;
71062306a36Sopenharmony_ci	gf_Scale = max((u32) gcd(lo_gcd, f), f_Scale);
71162306a36Sopenharmony_ci	hgfs = gf_Scale / 2;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/*  Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic  */
71662306a36Sopenharmony_ci	for (n = n0; n <= pAS_Info->maxH1; ++n) {
71762306a36Sopenharmony_ci		md = (n * ((f_LO1 + hgds) / gd_Scale) -
71862306a36Sopenharmony_ci		      ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci		/*  If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present  */
72162306a36Sopenharmony_ci		if (md >= pAS_Info->maxH1)
72262306a36Sopenharmony_ci			break;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci		ma = (n * ((f_LO1 + hgds) / gd_Scale) +
72562306a36Sopenharmony_ci		      ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci		/*  If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic  */
72862306a36Sopenharmony_ci		if (md == ma)
72962306a36Sopenharmony_ci			continue;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci		mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
73262306a36Sopenharmony_ci		      ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
73362306a36Sopenharmony_ci		if (mc != md) {
73462306a36Sopenharmony_ci			f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
73562306a36Sopenharmony_ci			f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
73662306a36Sopenharmony_ci			f_Spur =
73762306a36Sopenharmony_ci			    (gc_Scale * (f_nsLO1 - f_nsLO2)) +
73862306a36Sopenharmony_ci			    n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci			*fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
74162306a36Sopenharmony_ci			*fm = (((s32) d - f_Spur) / (mc - n)) + 1;
74262306a36Sopenharmony_ci			return 1;
74362306a36Sopenharmony_ci		}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci		/*  Location of Zero-IF-spur to be checked  */
74662306a36Sopenharmony_ci		me = (n * ((f_LO1 + hgfs) / gf_Scale) +
74762306a36Sopenharmony_ci		      ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
74862306a36Sopenharmony_ci		mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
74962306a36Sopenharmony_ci		      ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
75062306a36Sopenharmony_ci		if (me != mf) {
75162306a36Sopenharmony_ci			f_nsLO1 = n * (f_LO1 / gf_Scale);
75262306a36Sopenharmony_ci			f_nsLO2 = me * (f_LO2 / gf_Scale);
75362306a36Sopenharmony_ci			f_Spur =
75462306a36Sopenharmony_ci			    (gf_Scale * (f_nsLO1 - f_nsLO2)) +
75562306a36Sopenharmony_ci			    n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci			*fp = ((f_Spur + (s32) f) / (me - n)) + 1;
75862306a36Sopenharmony_ci			*fm = (((s32) f - f_Spur) / (me - n)) + 1;
75962306a36Sopenharmony_ci			return 1;
76062306a36Sopenharmony_ci		}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci		mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
76362306a36Sopenharmony_ci		      ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
76462306a36Sopenharmony_ci		if (ma != mb) {
76562306a36Sopenharmony_ci			f_nsLO1 = n * (f_LO1 / gc_Scale);
76662306a36Sopenharmony_ci			f_nsLO2 = ma * (f_LO2 / gc_Scale);
76762306a36Sopenharmony_ci			f_Spur =
76862306a36Sopenharmony_ci			    (gc_Scale * (f_nsLO1 - f_nsLO2)) +
76962306a36Sopenharmony_ci			    n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci			*fp = (((s32) d + f_Spur) / (ma - n)) + 1;
77262306a36Sopenharmony_ci			*fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
77362306a36Sopenharmony_ci			return 1;
77462306a36Sopenharmony_ci		}
77562306a36Sopenharmony_ci	}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	/*  No spurs found  */
77862306a36Sopenharmony_ci	return 0;
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci/*
78262306a36Sopenharmony_ci * MT_AvoidSpurs() - Main entry point to avoid spurs.
78362306a36Sopenharmony_ci *                   Checks for existing spurs in present LO1, LO2 freqs
78462306a36Sopenharmony_ci *                   and if present, chooses spur-free LO1, LO2 combination
78562306a36Sopenharmony_ci *                   that tunes the same input/output frequencies.
78662306a36Sopenharmony_ci */
78762306a36Sopenharmony_cistatic u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
78862306a36Sopenharmony_ci{
78962306a36Sopenharmony_ci	int status = 0;
79062306a36Sopenharmony_ci	u32 fm, fp;		/*  restricted range on LO's        */
79162306a36Sopenharmony_ci	pAS_Info->bSpurAvoided = 0;
79262306a36Sopenharmony_ci	pAS_Info->nSpursFound = 0;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	dprintk(2, "\n");
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	if (pAS_Info->maxH1 == 0)
79762306a36Sopenharmony_ci		return 0;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/*
80062306a36Sopenharmony_ci	 * Avoid LO Generated Spurs
80162306a36Sopenharmony_ci	 *
80262306a36Sopenharmony_ci	 * Make sure that have no LO-related spurs within the IF output
80362306a36Sopenharmony_ci	 * bandwidth.
80462306a36Sopenharmony_ci	 *
80562306a36Sopenharmony_ci	 * If there is an LO spur in this band, start at the current IF1 frequency
80662306a36Sopenharmony_ci	 * and work out until we find a spur-free frequency or run up against the
80762306a36Sopenharmony_ci	 * 1st IF SAW band edge.  Use temporary copies of fLO1 and fLO2 so that they
80862306a36Sopenharmony_ci	 * will be unchanged if a spur-free setting is not found.
80962306a36Sopenharmony_ci	 */
81062306a36Sopenharmony_ci	pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
81162306a36Sopenharmony_ci	if (pAS_Info->bSpurPresent) {
81262306a36Sopenharmony_ci		u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in;	/*  current attempt at a 1st IF  */
81362306a36Sopenharmony_ci		u32 zfLO1 = pAS_Info->f_LO1;	/*  current attempt at an LO1 freq  */
81462306a36Sopenharmony_ci		u32 zfLO2 = pAS_Info->f_LO2;	/*  current attempt at an LO2 freq  */
81562306a36Sopenharmony_ci		u32 delta_IF1;
81662306a36Sopenharmony_ci		u32 new_IF1;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci		/*
81962306a36Sopenharmony_ci		 **  Spur was found, attempt to find a spur-free 1st IF
82062306a36Sopenharmony_ci		 */
82162306a36Sopenharmony_ci		do {
82262306a36Sopenharmony_ci			pAS_Info->nSpursFound++;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci			/*  Raise f_IF1_upper, if needed  */
82562306a36Sopenharmony_ci			MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci			/*  Choose next IF1 that is closest to f_IF1_CENTER              */
82862306a36Sopenharmony_ci			new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci			if (new_IF1 > zfIF1) {
83162306a36Sopenharmony_ci				pAS_Info->f_LO1 += (new_IF1 - zfIF1);
83262306a36Sopenharmony_ci				pAS_Info->f_LO2 += (new_IF1 - zfIF1);
83362306a36Sopenharmony_ci			} else {
83462306a36Sopenharmony_ci				pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
83562306a36Sopenharmony_ci				pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
83662306a36Sopenharmony_ci			}
83762306a36Sopenharmony_ci			zfIF1 = new_IF1;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci			if (zfIF1 > pAS_Info->f_if1_Center)
84062306a36Sopenharmony_ci				delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
84162306a36Sopenharmony_ci			else
84262306a36Sopenharmony_ci				delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci			pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
84562306a36Sopenharmony_ci		/*
84662306a36Sopenharmony_ci		 *  Continue while the new 1st IF is still within the 1st IF bandwidth
84762306a36Sopenharmony_ci		 *  and there is a spur in the band (again)
84862306a36Sopenharmony_ci		 */
84962306a36Sopenharmony_ci		} while ((2 * delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && pAS_Info->bSpurPresent);
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci		/*
85262306a36Sopenharmony_ci		 * Use the LO-spur free values found.  If the search went all
85362306a36Sopenharmony_ci		 * the way to the 1st IF band edge and always found spurs, just
85462306a36Sopenharmony_ci		 * leave the original choice.  It's as "good" as any other.
85562306a36Sopenharmony_ci		 */
85662306a36Sopenharmony_ci		if (pAS_Info->bSpurPresent == 1) {
85762306a36Sopenharmony_ci			status |= MT2063_SPUR_PRESENT_ERR;
85862306a36Sopenharmony_ci			pAS_Info->f_LO1 = zfLO1;
85962306a36Sopenharmony_ci			pAS_Info->f_LO2 = zfLO2;
86062306a36Sopenharmony_ci		} else
86162306a36Sopenharmony_ci			pAS_Info->bSpurAvoided = 1;
86262306a36Sopenharmony_ci	}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	status |=
86562306a36Sopenharmony_ci	    ((pAS_Info->
86662306a36Sopenharmony_ci	      nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	return status;
86962306a36Sopenharmony_ci}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci/*
87262306a36Sopenharmony_ci * Constants used by the tuning algorithm
87362306a36Sopenharmony_ci */
87462306a36Sopenharmony_ci#define MT2063_REF_FREQ          (16000000UL)	/* Reference oscillator Frequency (in Hz) */
87562306a36Sopenharmony_ci#define MT2063_IF1_BW            (22000000UL)	/* The IF1 filter bandwidth (in Hz) */
87662306a36Sopenharmony_ci#define MT2063_TUNE_STEP_SIZE       (50000UL)	/* Tune in steps of 50 kHz */
87762306a36Sopenharmony_ci#define MT2063_SPUR_STEP_HZ        (250000UL)	/* Step size (in Hz) to move IF1 when avoiding spurs */
87862306a36Sopenharmony_ci#define MT2063_ZIF_BW             (2000000UL)	/* Zero-IF spur-free bandwidth (in Hz) */
87962306a36Sopenharmony_ci#define MT2063_MAX_HARMONICS_1         (15UL)	/* Highest intra-tuner LO Spur Harmonic to be avoided */
88062306a36Sopenharmony_ci#define MT2063_MAX_HARMONICS_2          (5UL)	/* Highest inter-tuner LO Spur Harmonic to be avoided */
88162306a36Sopenharmony_ci#define MT2063_MIN_LO_SEP         (1000000UL)	/* Minimum inter-tuner LO frequency separation */
88262306a36Sopenharmony_ci#define MT2063_LO1_FRACN_AVOID          (0UL)	/* LO1 FracN numerator avoid region (in Hz) */
88362306a36Sopenharmony_ci#define MT2063_LO2_FRACN_AVOID     (199999UL)	/* LO2 FracN numerator avoid region (in Hz) */
88462306a36Sopenharmony_ci#define MT2063_MIN_FIN_FREQ      (44000000UL)	/* Minimum input frequency (in Hz) */
88562306a36Sopenharmony_ci#define MT2063_MAX_FIN_FREQ    (1100000000UL)	/* Maximum input frequency (in Hz) */
88662306a36Sopenharmony_ci#define MT2063_MIN_FOUT_FREQ     (36000000UL)	/* Minimum output frequency (in Hz) */
88762306a36Sopenharmony_ci#define MT2063_MAX_FOUT_FREQ     (57000000UL)	/* Maximum output frequency (in Hz) */
88862306a36Sopenharmony_ci#define MT2063_MIN_DNC_FREQ    (1293000000UL)	/* Minimum LO2 frequency (in Hz) */
88962306a36Sopenharmony_ci#define MT2063_MAX_DNC_FREQ    (1614000000UL)	/* Maximum LO2 frequency (in Hz) */
89062306a36Sopenharmony_ci#define MT2063_MIN_UPC_FREQ    (1396000000UL)	/* Minimum LO1 frequency (in Hz) */
89162306a36Sopenharmony_ci#define MT2063_MAX_UPC_FREQ    (2750000000UL)	/* Maximum LO1 frequency (in Hz) */
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci/*
89462306a36Sopenharmony_ci *  Define the supported Part/Rev codes for the MT2063
89562306a36Sopenharmony_ci */
89662306a36Sopenharmony_ci#define MT2063_B0       (0x9B)
89762306a36Sopenharmony_ci#define MT2063_B1       (0x9C)
89862306a36Sopenharmony_ci#define MT2063_B2       (0x9D)
89962306a36Sopenharmony_ci#define MT2063_B3       (0x9E)
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci/**
90262306a36Sopenharmony_ci * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
90362306a36Sopenharmony_ci *
90462306a36Sopenharmony_ci * @state:	struct mt2063_state pointer
90562306a36Sopenharmony_ci *
90662306a36Sopenharmony_ci * This function returns 0, if no lock, 1 if locked and a value < 1 if error
90762306a36Sopenharmony_ci */
90862306a36Sopenharmony_cistatic int mt2063_lockStatus(struct mt2063_state *state)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci	const u32 nMaxWait = 100;	/*  wait a maximum of 100 msec   */
91162306a36Sopenharmony_ci	const u32 nPollRate = 2;	/*  poll status bits every 2 ms */
91262306a36Sopenharmony_ci	const u32 nMaxLoops = nMaxWait / nPollRate;
91362306a36Sopenharmony_ci	const u8 LO1LK = 0x80;
91462306a36Sopenharmony_ci	u8 LO2LK = 0x08;
91562306a36Sopenharmony_ci	int status;
91662306a36Sopenharmony_ci	u32 nDelays = 0;
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	dprintk(2, "\n");
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	/*  LO2 Lock bit was in a different place for B0 version  */
92162306a36Sopenharmony_ci	if (state->tuner_id == MT2063_B0)
92262306a36Sopenharmony_ci		LO2LK = 0x40;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	do {
92562306a36Sopenharmony_ci		status = mt2063_read(state, MT2063_REG_LO_STATUS,
92662306a36Sopenharmony_ci				     &state->reg[MT2063_REG_LO_STATUS], 1);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci		if (status < 0)
92962306a36Sopenharmony_ci			return status;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
93262306a36Sopenharmony_ci		    (LO1LK | LO2LK)) {
93362306a36Sopenharmony_ci			return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
93462306a36Sopenharmony_ci		}
93562306a36Sopenharmony_ci		msleep(nPollRate);	/*  Wait between retries  */
93662306a36Sopenharmony_ci	} while (++nDelays < nMaxLoops);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	/*
93962306a36Sopenharmony_ci	 * Got no lock or partial lock
94062306a36Sopenharmony_ci	 */
94162306a36Sopenharmony_ci	return 0;
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci/*
94562306a36Sopenharmony_ci *  Constants for setting receiver modes.
94662306a36Sopenharmony_ci *  (6 modes defined at this time, enumerated by mt2063_delivery_sys)
94762306a36Sopenharmony_ci *  (DNC1GC & DNC2GC are the values, which are used, when the specific
94862306a36Sopenharmony_ci *   DNC Output is selected, the other is always off)
94962306a36Sopenharmony_ci *
95062306a36Sopenharmony_ci *                enum mt2063_delivery_sys
95162306a36Sopenharmony_ci * -------------+----------------------------------------------
95262306a36Sopenharmony_ci * Mode 0 :     | MT2063_CABLE_QAM
95362306a36Sopenharmony_ci * Mode 1 :     | MT2063_CABLE_ANALOG
95462306a36Sopenharmony_ci * Mode 2 :     | MT2063_OFFAIR_COFDM
95562306a36Sopenharmony_ci * Mode 3 :     | MT2063_OFFAIR_COFDM_SAWLESS
95662306a36Sopenharmony_ci * Mode 4 :     | MT2063_OFFAIR_ANALOG
95762306a36Sopenharmony_ci * Mode 5 :     | MT2063_OFFAIR_8VSB
95862306a36Sopenharmony_ci * --------------+----------------------------------------------
95962306a36Sopenharmony_ci *
96062306a36Sopenharmony_ci *                |<----------   Mode  -------------->|
96162306a36Sopenharmony_ci *    Reg Field   |  0  |  1  |  2  |  3  |  4  |  5  |
96262306a36Sopenharmony_ci *    ------------+-----+-----+-----+-----+-----+-----+
96362306a36Sopenharmony_ci *    RFAGCen     | OFF | OFF | OFF | OFF | OFF | OFF
96462306a36Sopenharmony_ci *    LNARin      |   0 |   0 |   3 |   3 |  3  |  3
96562306a36Sopenharmony_ci *    FIFFQen     |   1 |   1 |   1 |   1 |  1  |  1
96662306a36Sopenharmony_ci *    FIFFq       |   0 |   0 |   0 |   0 |  0  |  0
96762306a36Sopenharmony_ci *    DNC1gc      |   0 |   0 |   0 |   0 |  0  |  0
96862306a36Sopenharmony_ci *    DNC2gc      |   0 |   0 |   0 |   0 |  0  |  0
96962306a36Sopenharmony_ci *    GCU Auto    |   1 |   1 |   1 |   1 |  1  |  1
97062306a36Sopenharmony_ci *    LNA max Atn |  31 |  31 |  31 |  31 | 31  | 31
97162306a36Sopenharmony_ci *    LNA Target  |  44 |  43 |  43 |  43 | 43  | 43
97262306a36Sopenharmony_ci *    ign  RF Ovl |   0 |   0 |   0 |   0 |  0  |  0
97362306a36Sopenharmony_ci *    RF  max Atn |  31 |  31 |  31 |  31 | 31  | 31
97462306a36Sopenharmony_ci *    PD1 Target  |  36 |  36 |  38 |  38 | 36  | 38
97562306a36Sopenharmony_ci *    ign FIF Ovl |   0 |   0 |   0 |   0 |  0  |  0
97662306a36Sopenharmony_ci *    FIF max Atn |   5 |   5 |   5 |   5 |  5  |  5
97762306a36Sopenharmony_ci *    PD2 Target  |  40 |  33 |  42 |  42 | 33  | 42
97862306a36Sopenharmony_ci */
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cienum mt2063_delivery_sys {
98162306a36Sopenharmony_ci	MT2063_CABLE_QAM = 0,
98262306a36Sopenharmony_ci	MT2063_CABLE_ANALOG,
98362306a36Sopenharmony_ci	MT2063_OFFAIR_COFDM,
98462306a36Sopenharmony_ci	MT2063_OFFAIR_COFDM_SAWLESS,
98562306a36Sopenharmony_ci	MT2063_OFFAIR_ANALOG,
98662306a36Sopenharmony_ci	MT2063_OFFAIR_8VSB,
98762306a36Sopenharmony_ci	MT2063_NUM_RCVR_MODES
98862306a36Sopenharmony_ci};
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_cistatic const char *mt2063_mode_name[] = {
99162306a36Sopenharmony_ci	[MT2063_CABLE_QAM]		= "digital cable",
99262306a36Sopenharmony_ci	[MT2063_CABLE_ANALOG]		= "analog cable",
99362306a36Sopenharmony_ci	[MT2063_OFFAIR_COFDM]		= "digital offair",
99462306a36Sopenharmony_ci	[MT2063_OFFAIR_COFDM_SAWLESS]	= "digital offair without SAW",
99562306a36Sopenharmony_ci	[MT2063_OFFAIR_ANALOG]		= "analog offair",
99662306a36Sopenharmony_ci	[MT2063_OFFAIR_8VSB]		= "analog offair 8vsb",
99762306a36Sopenharmony_ci};
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_cistatic const u8 RFAGCEN[]	= {  0,  0,  0,  0,  0,  0 };
100062306a36Sopenharmony_cistatic const u8 LNARIN[]	= {  0,  0,  3,  3,  3,  3 };
100162306a36Sopenharmony_cistatic const u8 FIFFQEN[]	= {  1,  1,  1,  1,  1,  1 };
100262306a36Sopenharmony_cistatic const u8 FIFFQ[]		= {  0,  0,  0,  0,  0,  0 };
100362306a36Sopenharmony_cistatic const u8 DNC1GC[]	= {  0,  0,  0,  0,  0,  0 };
100462306a36Sopenharmony_cistatic const u8 DNC2GC[]	= {  0,  0,  0,  0,  0,  0 };
100562306a36Sopenharmony_cistatic const u8 ACLNAMAX[]	= { 31, 31, 31, 31, 31, 31 };
100662306a36Sopenharmony_cistatic const u8 LNATGT[]	= { 44, 43, 43, 43, 43, 43 };
100762306a36Sopenharmony_cistatic const u8 RFOVDIS[]	= {  0,  0,  0,  0,  0,  0 };
100862306a36Sopenharmony_cistatic const u8 ACRFMAX[]	= { 31, 31, 31, 31, 31, 31 };
100962306a36Sopenharmony_cistatic const u8 PD1TGT[]	= { 36, 36, 38, 38, 36, 38 };
101062306a36Sopenharmony_cistatic const u8 FIFOVDIS[]	= {  0,  0,  0,  0,  0,  0 };
101162306a36Sopenharmony_cistatic const u8 ACFIFMAX[]	= { 29, 29, 29, 29, 29, 29 };
101262306a36Sopenharmony_cistatic const u8 PD2TGT[]	= { 40, 33, 38, 42, 30, 38 };
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci/*
101562306a36Sopenharmony_ci * mt2063_set_dnc_output_enable()
101662306a36Sopenharmony_ci */
101762306a36Sopenharmony_cistatic u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
101862306a36Sopenharmony_ci					enum MT2063_DNC_Output_Enable *pValue)
101962306a36Sopenharmony_ci{
102062306a36Sopenharmony_ci	dprintk(2, "\n");
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) {	/* if DNC1 is off */
102362306a36Sopenharmony_ci		if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)	/* if DNC2 is off */
102462306a36Sopenharmony_ci			*pValue = MT2063_DNC_NONE;
102562306a36Sopenharmony_ci		else
102662306a36Sopenharmony_ci			*pValue = MT2063_DNC_2;
102762306a36Sopenharmony_ci	} else {	/* DNC1 is on */
102862306a36Sopenharmony_ci		if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)	/* if DNC2 is off */
102962306a36Sopenharmony_ci			*pValue = MT2063_DNC_1;
103062306a36Sopenharmony_ci		else
103162306a36Sopenharmony_ci			*pValue = MT2063_DNC_BOTH;
103262306a36Sopenharmony_ci	}
103362306a36Sopenharmony_ci	return 0;
103462306a36Sopenharmony_ci}
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci/*
103762306a36Sopenharmony_ci * mt2063_set_dnc_output_enable()
103862306a36Sopenharmony_ci */
103962306a36Sopenharmony_cistatic u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
104062306a36Sopenharmony_ci					enum MT2063_DNC_Output_Enable nValue)
104162306a36Sopenharmony_ci{
104262306a36Sopenharmony_ci	int status = 0;	/* Status to be returned        */
104362306a36Sopenharmony_ci	u8 val = 0;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	dprintk(2, "\n");
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	/* selects, which DNC output is used */
104862306a36Sopenharmony_ci	switch (nValue) {
104962306a36Sopenharmony_ci	case MT2063_DNC_NONE:
105062306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;	/* Set DNC1GC=3 */
105162306a36Sopenharmony_ci		if (state->reg[MT2063_REG_DNC_GAIN] !=
105262306a36Sopenharmony_ci		    val)
105362306a36Sopenharmony_ci			status |=
105462306a36Sopenharmony_ci			    mt2063_setreg(state,
105562306a36Sopenharmony_ci					  MT2063_REG_DNC_GAIN,
105662306a36Sopenharmony_ci					  val);
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;	/* Set DNC2GC=3 */
105962306a36Sopenharmony_ci		if (state->reg[MT2063_REG_VGA_GAIN] !=
106062306a36Sopenharmony_ci		    val)
106162306a36Sopenharmony_ci			status |=
106262306a36Sopenharmony_ci			    mt2063_setreg(state,
106362306a36Sopenharmony_ci					  MT2063_REG_VGA_GAIN,
106462306a36Sopenharmony_ci					  val);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_RSVD_20] & ~0x40);	/* Set PD2MUX=0 */
106762306a36Sopenharmony_ci		if (state->reg[MT2063_REG_RSVD_20] !=
106862306a36Sopenharmony_ci		    val)
106962306a36Sopenharmony_ci			status |=
107062306a36Sopenharmony_ci			    mt2063_setreg(state,
107162306a36Sopenharmony_ci					  MT2063_REG_RSVD_20,
107262306a36Sopenharmony_ci					  val);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		break;
107562306a36Sopenharmony_ci	case MT2063_DNC_1:
107662306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);	/* Set DNC1GC=x */
107762306a36Sopenharmony_ci		if (state->reg[MT2063_REG_DNC_GAIN] !=
107862306a36Sopenharmony_ci		    val)
107962306a36Sopenharmony_ci			status |=
108062306a36Sopenharmony_ci			    mt2063_setreg(state,
108162306a36Sopenharmony_ci					  MT2063_REG_DNC_GAIN,
108262306a36Sopenharmony_ci					  val);
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;	/* Set DNC2GC=3 */
108562306a36Sopenharmony_ci		if (state->reg[MT2063_REG_VGA_GAIN] !=
108662306a36Sopenharmony_ci		    val)
108762306a36Sopenharmony_ci			status |=
108862306a36Sopenharmony_ci			    mt2063_setreg(state,
108962306a36Sopenharmony_ci					  MT2063_REG_VGA_GAIN,
109062306a36Sopenharmony_ci					  val);
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_RSVD_20] & ~0x40);	/* Set PD2MUX=0 */
109362306a36Sopenharmony_ci		if (state->reg[MT2063_REG_RSVD_20] !=
109462306a36Sopenharmony_ci		    val)
109562306a36Sopenharmony_ci			status |=
109662306a36Sopenharmony_ci			    mt2063_setreg(state,
109762306a36Sopenharmony_ci					  MT2063_REG_RSVD_20,
109862306a36Sopenharmony_ci					  val);
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci		break;
110162306a36Sopenharmony_ci	case MT2063_DNC_2:
110262306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;	/* Set DNC1GC=3 */
110362306a36Sopenharmony_ci		if (state->reg[MT2063_REG_DNC_GAIN] !=
110462306a36Sopenharmony_ci		    val)
110562306a36Sopenharmony_ci			status |=
110662306a36Sopenharmony_ci			    mt2063_setreg(state,
110762306a36Sopenharmony_ci					  MT2063_REG_DNC_GAIN,
110862306a36Sopenharmony_ci					  val);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);	/* Set DNC2GC=x */
111162306a36Sopenharmony_ci		if (state->reg[MT2063_REG_VGA_GAIN] !=
111262306a36Sopenharmony_ci		    val)
111362306a36Sopenharmony_ci			status |=
111462306a36Sopenharmony_ci			    mt2063_setreg(state,
111562306a36Sopenharmony_ci					  MT2063_REG_VGA_GAIN,
111662306a36Sopenharmony_ci					  val);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_RSVD_20] | 0x40);	/* Set PD2MUX=1 */
111962306a36Sopenharmony_ci		if (state->reg[MT2063_REG_RSVD_20] !=
112062306a36Sopenharmony_ci		    val)
112162306a36Sopenharmony_ci			status |=
112262306a36Sopenharmony_ci			    mt2063_setreg(state,
112362306a36Sopenharmony_ci					  MT2063_REG_RSVD_20,
112462306a36Sopenharmony_ci					  val);
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci		break;
112762306a36Sopenharmony_ci	case MT2063_DNC_BOTH:
112862306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);	/* Set DNC1GC=x */
112962306a36Sopenharmony_ci		if (state->reg[MT2063_REG_DNC_GAIN] !=
113062306a36Sopenharmony_ci		    val)
113162306a36Sopenharmony_ci			status |=
113262306a36Sopenharmony_ci			    mt2063_setreg(state,
113362306a36Sopenharmony_ci					  MT2063_REG_DNC_GAIN,
113462306a36Sopenharmony_ci					  val);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);	/* Set DNC2GC=x */
113762306a36Sopenharmony_ci		if (state->reg[MT2063_REG_VGA_GAIN] !=
113862306a36Sopenharmony_ci		    val)
113962306a36Sopenharmony_ci			status |=
114062306a36Sopenharmony_ci			    mt2063_setreg(state,
114162306a36Sopenharmony_ci					  MT2063_REG_VGA_GAIN,
114262306a36Sopenharmony_ci					  val);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_RSVD_20] | 0x40);	/* Set PD2MUX=1 */
114562306a36Sopenharmony_ci		if (state->reg[MT2063_REG_RSVD_20] !=
114662306a36Sopenharmony_ci		    val)
114762306a36Sopenharmony_ci			status |=
114862306a36Sopenharmony_ci			    mt2063_setreg(state,
114962306a36Sopenharmony_ci					  MT2063_REG_RSVD_20,
115062306a36Sopenharmony_ci					  val);
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci		break;
115362306a36Sopenharmony_ci	default:
115462306a36Sopenharmony_ci		break;
115562306a36Sopenharmony_ci	}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	return status;
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci/*
116162306a36Sopenharmony_ci * MT2063_SetReceiverMode() - Set the MT2063 receiver mode, according with
116262306a36Sopenharmony_ci *			      the selected enum mt2063_delivery_sys type.
116362306a36Sopenharmony_ci *
116462306a36Sopenharmony_ci *  (DNC1GC & DNC2GC are the values, which are used, when the specific
116562306a36Sopenharmony_ci *   DNC Output is selected, the other is always off)
116662306a36Sopenharmony_ci *
116762306a36Sopenharmony_ci * @state:	ptr to mt2063_state structure
116862306a36Sopenharmony_ci * @Mode:	desired receiver delivery system
116962306a36Sopenharmony_ci *
117062306a36Sopenharmony_ci * Note: Register cache must be valid for it to work
117162306a36Sopenharmony_ci */
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_cistatic u32 MT2063_SetReceiverMode(struct mt2063_state *state,
117462306a36Sopenharmony_ci				  enum mt2063_delivery_sys Mode)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci	int status = 0;	/* Status to be returned        */
117762306a36Sopenharmony_ci	u8 val;
117862306a36Sopenharmony_ci	u32 longval;
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	dprintk(2, "\n");
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	if (Mode >= MT2063_NUM_RCVR_MODES)
118362306a36Sopenharmony_ci		status = -ERANGE;
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	/* RFAGCen */
118662306a36Sopenharmony_ci	if (status >= 0) {
118762306a36Sopenharmony_ci		val =
118862306a36Sopenharmony_ci		    (state->
118962306a36Sopenharmony_ci		     reg[MT2063_REG_PD1_TGT] & ~0x40) | (RFAGCEN[Mode]
119062306a36Sopenharmony_ci								   ? 0x40 :
119162306a36Sopenharmony_ci								   0x00);
119262306a36Sopenharmony_ci		if (state->reg[MT2063_REG_PD1_TGT] != val)
119362306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	/* LNARin */
119762306a36Sopenharmony_ci	if (status >= 0) {
119862306a36Sopenharmony_ci		u8 val = (state->reg[MT2063_REG_CTRL_2C] & ~0x03) |
119962306a36Sopenharmony_ci			 (LNARIN[Mode] & 0x03);
120062306a36Sopenharmony_ci		if (state->reg[MT2063_REG_CTRL_2C] != val)
120162306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
120262306a36Sopenharmony_ci	}
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	/* FIFFQEN and FIFFQ */
120562306a36Sopenharmony_ci	if (status >= 0) {
120662306a36Sopenharmony_ci		val =
120762306a36Sopenharmony_ci		    (state->
120862306a36Sopenharmony_ci		     reg[MT2063_REG_FIFF_CTRL2] & ~0xF0) |
120962306a36Sopenharmony_ci		    (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
121062306a36Sopenharmony_ci		if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
121162306a36Sopenharmony_ci			status |=
121262306a36Sopenharmony_ci			    mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val);
121362306a36Sopenharmony_ci			/* trigger FIFF calibration, needed after changing FIFFQ */
121462306a36Sopenharmony_ci			val =
121562306a36Sopenharmony_ci			    (state->reg[MT2063_REG_FIFF_CTRL] | 0x01);
121662306a36Sopenharmony_ci			status |=
121762306a36Sopenharmony_ci			    mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
121862306a36Sopenharmony_ci			val =
121962306a36Sopenharmony_ci			    (state->
122062306a36Sopenharmony_ci			     reg[MT2063_REG_FIFF_CTRL] & ~0x01);
122162306a36Sopenharmony_ci			status |=
122262306a36Sopenharmony_ci			    mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
122362306a36Sopenharmony_ci		}
122462306a36Sopenharmony_ci	}
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	/* DNC1GC & DNC2GC */
122762306a36Sopenharmony_ci	status |= mt2063_get_dnc_output_enable(state, &longval);
122862306a36Sopenharmony_ci	status |= mt2063_set_dnc_output_enable(state, longval);
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	/* acLNAmax */
123162306a36Sopenharmony_ci	if (status >= 0) {
123262306a36Sopenharmony_ci		u8 val = (state->reg[MT2063_REG_LNA_OV] & ~0x1F) |
123362306a36Sopenharmony_ci			 (ACLNAMAX[Mode] & 0x1F);
123462306a36Sopenharmony_ci		if (state->reg[MT2063_REG_LNA_OV] != val)
123562306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
123662306a36Sopenharmony_ci	}
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	/* LNATGT */
123962306a36Sopenharmony_ci	if (status >= 0) {
124062306a36Sopenharmony_ci		u8 val = (state->reg[MT2063_REG_LNA_TGT] & ~0x3F) |
124162306a36Sopenharmony_ci			 (LNATGT[Mode] & 0x3F);
124262306a36Sopenharmony_ci		if (state->reg[MT2063_REG_LNA_TGT] != val)
124362306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
124462306a36Sopenharmony_ci	}
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	/* ACRF */
124762306a36Sopenharmony_ci	if (status >= 0) {
124862306a36Sopenharmony_ci		u8 val = (state->reg[MT2063_REG_RF_OV] & ~0x1F) |
124962306a36Sopenharmony_ci			 (ACRFMAX[Mode] & 0x1F);
125062306a36Sopenharmony_ci		if (state->reg[MT2063_REG_RF_OV] != val)
125162306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
125262306a36Sopenharmony_ci	}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	/* PD1TGT */
125562306a36Sopenharmony_ci	if (status >= 0) {
125662306a36Sopenharmony_ci		u8 val = (state->reg[MT2063_REG_PD1_TGT] & ~0x3F) |
125762306a36Sopenharmony_ci			 (PD1TGT[Mode] & 0x3F);
125862306a36Sopenharmony_ci		if (state->reg[MT2063_REG_PD1_TGT] != val)
125962306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
126062306a36Sopenharmony_ci	}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	/* FIFATN */
126362306a36Sopenharmony_ci	if (status >= 0) {
126462306a36Sopenharmony_ci		u8 val = ACFIFMAX[Mode];
126562306a36Sopenharmony_ci		if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
126662306a36Sopenharmony_ci			val = 5;
126762306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_FIF_OV] & ~0x1F) |
126862306a36Sopenharmony_ci		      (val & 0x1F);
126962306a36Sopenharmony_ci		if (state->reg[MT2063_REG_FIF_OV] != val)
127062306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
127162306a36Sopenharmony_ci	}
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	/* PD2TGT */
127462306a36Sopenharmony_ci	if (status >= 0) {
127562306a36Sopenharmony_ci		u8 val = (state->reg[MT2063_REG_PD2_TGT] & ~0x3F) |
127662306a36Sopenharmony_ci		    (PD2TGT[Mode] & 0x3F);
127762306a36Sopenharmony_ci		if (state->reg[MT2063_REG_PD2_TGT] != val)
127862306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
127962306a36Sopenharmony_ci	}
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	/* Ignore ATN Overload */
128262306a36Sopenharmony_ci	if (status >= 0) {
128362306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_LNA_TGT] & ~0x80) |
128462306a36Sopenharmony_ci		      (RFOVDIS[Mode] ? 0x80 : 0x00);
128562306a36Sopenharmony_ci		if (state->reg[MT2063_REG_LNA_TGT] != val)
128662306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
128762306a36Sopenharmony_ci	}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_ci	/* Ignore FIF Overload */
129062306a36Sopenharmony_ci	if (status >= 0) {
129162306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_PD1_TGT] & ~0x80) |
129262306a36Sopenharmony_ci		      (FIFOVDIS[Mode] ? 0x80 : 0x00);
129362306a36Sopenharmony_ci		if (state->reg[MT2063_REG_PD1_TGT] != val)
129462306a36Sopenharmony_ci			status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
129562306a36Sopenharmony_ci	}
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	if (status >= 0) {
129862306a36Sopenharmony_ci		state->rcvr_mode = Mode;
129962306a36Sopenharmony_ci		dprintk(1, "mt2063 mode changed to %s\n",
130062306a36Sopenharmony_ci			mt2063_mode_name[state->rcvr_mode]);
130162306a36Sopenharmony_ci	}
130262306a36Sopenharmony_ci
130362306a36Sopenharmony_ci	return status;
130462306a36Sopenharmony_ci}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci/*
130762306a36Sopenharmony_ci * MT2063_ClearPowerMaskBits () - Clears the power-down mask bits for various
130862306a36Sopenharmony_ci *				  sections of the MT2063
130962306a36Sopenharmony_ci *
131062306a36Sopenharmony_ci * @Bits:		Mask bits to be cleared.
131162306a36Sopenharmony_ci *
131262306a36Sopenharmony_ci * See definition of MT2063_Mask_Bits type for description
131362306a36Sopenharmony_ci * of each of the power bits.
131462306a36Sopenharmony_ci */
131562306a36Sopenharmony_cistatic u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
131662306a36Sopenharmony_ci				     enum MT2063_Mask_Bits Bits)
131762306a36Sopenharmony_ci{
131862306a36Sopenharmony_ci	int status = 0;
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	dprintk(2, "\n");
132162306a36Sopenharmony_ci	Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);	/* Only valid bits for this tuner */
132262306a36Sopenharmony_ci	if ((Bits & 0xFF00) != 0) {
132362306a36Sopenharmony_ci		state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
132462306a36Sopenharmony_ci		status |=
132562306a36Sopenharmony_ci		    mt2063_write(state,
132662306a36Sopenharmony_ci				    MT2063_REG_PWR_2,
132762306a36Sopenharmony_ci				    &state->reg[MT2063_REG_PWR_2], 1);
132862306a36Sopenharmony_ci	}
132962306a36Sopenharmony_ci	if ((Bits & 0xFF) != 0) {
133062306a36Sopenharmony_ci		state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
133162306a36Sopenharmony_ci		status |=
133262306a36Sopenharmony_ci		    mt2063_write(state,
133362306a36Sopenharmony_ci				    MT2063_REG_PWR_1,
133462306a36Sopenharmony_ci				    &state->reg[MT2063_REG_PWR_1], 1);
133562306a36Sopenharmony_ci	}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	return status;
133862306a36Sopenharmony_ci}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci/*
134162306a36Sopenharmony_ci * MT2063_SoftwareShutdown() - Enables or disables software shutdown function.
134262306a36Sopenharmony_ci *			       When Shutdown is 1, any section whose power
134362306a36Sopenharmony_ci *			       mask is set will be shutdown.
134462306a36Sopenharmony_ci */
134562306a36Sopenharmony_cistatic u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
134662306a36Sopenharmony_ci{
134762306a36Sopenharmony_ci	int status;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	dprintk(2, "\n");
135062306a36Sopenharmony_ci	if (Shutdown == 1)
135162306a36Sopenharmony_ci		state->reg[MT2063_REG_PWR_1] |= 0x04;
135262306a36Sopenharmony_ci	else
135362306a36Sopenharmony_ci		state->reg[MT2063_REG_PWR_1] &= ~0x04;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	status = mt2063_write(state,
135662306a36Sopenharmony_ci			    MT2063_REG_PWR_1,
135762306a36Sopenharmony_ci			    &state->reg[MT2063_REG_PWR_1], 1);
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	if (Shutdown != 1) {
136062306a36Sopenharmony_ci		state->reg[MT2063_REG_BYP_CTRL] =
136162306a36Sopenharmony_ci		    (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
136262306a36Sopenharmony_ci		status |=
136362306a36Sopenharmony_ci		    mt2063_write(state,
136462306a36Sopenharmony_ci				    MT2063_REG_BYP_CTRL,
136562306a36Sopenharmony_ci				    &state->reg[MT2063_REG_BYP_CTRL],
136662306a36Sopenharmony_ci				    1);
136762306a36Sopenharmony_ci		state->reg[MT2063_REG_BYP_CTRL] =
136862306a36Sopenharmony_ci		    (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
136962306a36Sopenharmony_ci		status |=
137062306a36Sopenharmony_ci		    mt2063_write(state,
137162306a36Sopenharmony_ci				    MT2063_REG_BYP_CTRL,
137262306a36Sopenharmony_ci				    &state->reg[MT2063_REG_BYP_CTRL],
137362306a36Sopenharmony_ci				    1);
137462306a36Sopenharmony_ci	}
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	return status;
137762306a36Sopenharmony_ci}
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_cistatic u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
138062306a36Sopenharmony_ci{
138162306a36Sopenharmony_ci	return f_ref * (f_LO / f_ref)
138262306a36Sopenharmony_ci	    + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
138362306a36Sopenharmony_ci}
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci/**
138662306a36Sopenharmony_ci * MT2063_fLO_FractionalTerm - Calculates the portion contributed by FracN / denom.
138762306a36Sopenharmony_ci *                        This function preserves maximum precision without
138862306a36Sopenharmony_ci *                        risk of overflow.  It accurately calculates
138962306a36Sopenharmony_ci *                        f_ref * num / denom to within 1 HZ with fixed math.
139062306a36Sopenharmony_ci *
139162306a36Sopenharmony_ci * @f_ref:	SRO frequency.
139262306a36Sopenharmony_ci * @num:	Fractional portion of the multiplier
139362306a36Sopenharmony_ci * @denom:	denominator portion of the ratio
139462306a36Sopenharmony_ci *
139562306a36Sopenharmony_ci * This calculation handles f_ref as two separate 14-bit fields.
139662306a36Sopenharmony_ci * Therefore, a maximum value of 2^28-1 may safely be used for f_ref.
139762306a36Sopenharmony_ci * This is the genesis of the magic number "14" and the magic mask value of
139862306a36Sopenharmony_ci * 0x03FFF.
139962306a36Sopenharmony_ci *
140062306a36Sopenharmony_ci * This routine successfully handles denom values up to and including 2^18.
140162306a36Sopenharmony_ci *  Returns:        f_ref * num / denom
140262306a36Sopenharmony_ci */
140362306a36Sopenharmony_cistatic u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, u32 denom)
140462306a36Sopenharmony_ci{
140562306a36Sopenharmony_ci	u32 t1 = (f_ref >> 14) * num;
140662306a36Sopenharmony_ci	u32 term1 = t1 / denom;
140762306a36Sopenharmony_ci	u32 loss = t1 % denom;
140862306a36Sopenharmony_ci	u32 term2 =
140962306a36Sopenharmony_ci	    (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
141062306a36Sopenharmony_ci	return (term1 << 14) + term2;
141162306a36Sopenharmony_ci}
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci/*
141462306a36Sopenharmony_ci * MT2063_CalcLO1Mult - Calculates Integer divider value and the numerator
141562306a36Sopenharmony_ci *                value for a FracN PLL.
141662306a36Sopenharmony_ci *
141762306a36Sopenharmony_ci *                This function assumes that the f_LO and f_Ref are
141862306a36Sopenharmony_ci *                evenly divisible by f_LO_Step.
141962306a36Sopenharmony_ci *
142062306a36Sopenharmony_ci * @Div:	OUTPUT: Whole number portion of the multiplier
142162306a36Sopenharmony_ci * @FracN:	OUTPUT: Fractional portion of the multiplier
142262306a36Sopenharmony_ci * @f_LO:	desired LO frequency.
142362306a36Sopenharmony_ci * @f_LO_Step:	Minimum step size for the LO (in Hz).
142462306a36Sopenharmony_ci * @f_Ref:	SRO frequency.
142562306a36Sopenharmony_ci * @f_Avoid:	Range of PLL frequencies to avoid near integer multiples
142662306a36Sopenharmony_ci *		of f_Ref (in Hz).
142762306a36Sopenharmony_ci *
142862306a36Sopenharmony_ci * Returns:        Recalculated LO frequency.
142962306a36Sopenharmony_ci */
143062306a36Sopenharmony_cistatic u32 MT2063_CalcLO1Mult(u32 *Div,
143162306a36Sopenharmony_ci			      u32 *FracN,
143262306a36Sopenharmony_ci			      u32 f_LO,
143362306a36Sopenharmony_ci			      u32 f_LO_Step, u32 f_Ref)
143462306a36Sopenharmony_ci{
143562306a36Sopenharmony_ci	/*  Calculate the whole number portion of the divider */
143662306a36Sopenharmony_ci	*Div = f_LO / f_Ref;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	/*  Calculate the numerator value (round to nearest f_LO_Step) */
143962306a36Sopenharmony_ci	*FracN =
144062306a36Sopenharmony_ci	    (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
144162306a36Sopenharmony_ci	     (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
144462306a36Sopenharmony_ci}
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci/**
144762306a36Sopenharmony_ci * MT2063_CalcLO2Mult - Calculates Integer divider value and the numerator
144862306a36Sopenharmony_ci *                 value for a FracN PLL.
144962306a36Sopenharmony_ci *
145062306a36Sopenharmony_ci *                  This function assumes that the f_LO and f_Ref are
145162306a36Sopenharmony_ci *                  evenly divisible by f_LO_Step.
145262306a36Sopenharmony_ci *
145362306a36Sopenharmony_ci * @Div:	OUTPUT: Whole number portion of the multiplier
145462306a36Sopenharmony_ci * @FracN:	OUTPUT: Fractional portion of the multiplier
145562306a36Sopenharmony_ci * @f_LO:	desired LO frequency.
145662306a36Sopenharmony_ci * @f_LO_Step:	Minimum step size for the LO (in Hz).
145762306a36Sopenharmony_ci * @f_Ref:	SRO frequency.
145862306a36Sopenharmony_ci *
145962306a36Sopenharmony_ci * Returns: Recalculated LO frequency.
146062306a36Sopenharmony_ci */
146162306a36Sopenharmony_cistatic u32 MT2063_CalcLO2Mult(u32 *Div,
146262306a36Sopenharmony_ci			      u32 *FracN,
146362306a36Sopenharmony_ci			      u32 f_LO,
146462306a36Sopenharmony_ci			      u32 f_LO_Step, u32 f_Ref)
146562306a36Sopenharmony_ci{
146662306a36Sopenharmony_ci	/*  Calculate the whole number portion of the divider */
146762306a36Sopenharmony_ci	*Div = f_LO / f_Ref;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	/*  Calculate the numerator value (round to nearest f_LO_Step) */
147062306a36Sopenharmony_ci	*FracN =
147162306a36Sopenharmony_ci	    (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
147262306a36Sopenharmony_ci	     (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
147562306a36Sopenharmony_ci							    8191);
147662306a36Sopenharmony_ci}
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci/*
147962306a36Sopenharmony_ci * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
148062306a36Sopenharmony_ci *			   used for a given input frequency.
148162306a36Sopenharmony_ci *
148262306a36Sopenharmony_ci * @state:	ptr to tuner data structure
148362306a36Sopenharmony_ci * @f_in:	RF input center frequency (in Hz).
148462306a36Sopenharmony_ci *
148562306a36Sopenharmony_ci * Returns: ClearTune filter number (0-31)
148662306a36Sopenharmony_ci */
148762306a36Sopenharmony_cistatic u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
148862306a36Sopenharmony_ci{
148962306a36Sopenharmony_ci	u32 RFBand;
149062306a36Sopenharmony_ci	u32 idx;		/*  index loop                      */
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	/*
149362306a36Sopenharmony_ci	 **  Find RF Band setting
149462306a36Sopenharmony_ci	 */
149562306a36Sopenharmony_ci	RFBand = 31;		/*  def when f_in > all    */
149662306a36Sopenharmony_ci	for (idx = 0; idx < 31; ++idx) {
149762306a36Sopenharmony_ci		if (state->CTFiltMax[idx] >= f_in) {
149862306a36Sopenharmony_ci			RFBand = idx;
149962306a36Sopenharmony_ci			break;
150062306a36Sopenharmony_ci		}
150162306a36Sopenharmony_ci	}
150262306a36Sopenharmony_ci	return RFBand;
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci/*
150662306a36Sopenharmony_ci * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
150762306a36Sopenharmony_ci */
150862306a36Sopenharmony_cistatic u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
150962306a36Sopenharmony_ci{				/* RF input center frequency   */
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	int status = 0;
151262306a36Sopenharmony_ci	u32 LO1;		/*  1st LO register value           */
151362306a36Sopenharmony_ci	u32 Num1;		/*  Numerator for LO1 reg. value    */
151462306a36Sopenharmony_ci	u32 f_IF1;		/*  1st IF requested                */
151562306a36Sopenharmony_ci	u32 LO2;		/*  2nd LO register value           */
151662306a36Sopenharmony_ci	u32 Num2;		/*  Numerator for LO2 reg. value    */
151762306a36Sopenharmony_ci	u32 ofLO1, ofLO2;	/*  last time's LO frequencies      */
151862306a36Sopenharmony_ci	u8 fiffc = 0x80;	/*  FIFF center freq from tuner     */
151962306a36Sopenharmony_ci	u32 fiffof;		/*  Offset from FIFF center freq    */
152062306a36Sopenharmony_ci	const u8 LO1LK = 0x80;	/*  Mask for LO1 Lock bit           */
152162306a36Sopenharmony_ci	u8 LO2LK = 0x08;	/*  Mask for LO2 Lock bit           */
152262306a36Sopenharmony_ci	u8 val;
152362306a36Sopenharmony_ci	u32 RFBand;
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	dprintk(2, "\n");
152662306a36Sopenharmony_ci	/*  Check the input and output frequency ranges                   */
152762306a36Sopenharmony_ci	if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
152862306a36Sopenharmony_ci		return -EINVAL;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
153162306a36Sopenharmony_ci	    || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
153262306a36Sopenharmony_ci		return -EINVAL;
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci	/*
153562306a36Sopenharmony_ci	 * Save original LO1 and LO2 register values
153662306a36Sopenharmony_ci	 */
153762306a36Sopenharmony_ci	ofLO1 = state->AS_Data.f_LO1;
153862306a36Sopenharmony_ci	ofLO2 = state->AS_Data.f_LO2;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	/*
154162306a36Sopenharmony_ci	 * Find and set RF Band setting
154262306a36Sopenharmony_ci	 */
154362306a36Sopenharmony_ci	if (state->ctfilt_sw == 1) {
154462306a36Sopenharmony_ci		val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
154562306a36Sopenharmony_ci		if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
154662306a36Sopenharmony_ci			status |=
154762306a36Sopenharmony_ci			    mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
154862306a36Sopenharmony_ci		}
154962306a36Sopenharmony_ci		val = state->reg[MT2063_REG_CTUNE_OV];
155062306a36Sopenharmony_ci		RFBand = FindClearTuneFilter(state, f_in);
155162306a36Sopenharmony_ci		state->reg[MT2063_REG_CTUNE_OV] =
155262306a36Sopenharmony_ci		    (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
155362306a36Sopenharmony_ci			      | RFBand);
155462306a36Sopenharmony_ci		if (state->reg[MT2063_REG_CTUNE_OV] != val) {
155562306a36Sopenharmony_ci			status |=
155662306a36Sopenharmony_ci			    mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
155762306a36Sopenharmony_ci		}
155862306a36Sopenharmony_ci	}
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	/*
156162306a36Sopenharmony_ci	 * Read the FIFF Center Frequency from the tuner
156262306a36Sopenharmony_ci	 */
156362306a36Sopenharmony_ci	if (status >= 0) {
156462306a36Sopenharmony_ci		status |=
156562306a36Sopenharmony_ci		    mt2063_read(state,
156662306a36Sopenharmony_ci				   MT2063_REG_FIFFC,
156762306a36Sopenharmony_ci				   &state->reg[MT2063_REG_FIFFC], 1);
156862306a36Sopenharmony_ci		fiffc = state->reg[MT2063_REG_FIFFC];
156962306a36Sopenharmony_ci	}
157062306a36Sopenharmony_ci	/*
157162306a36Sopenharmony_ci	 * Assign in the requested values
157262306a36Sopenharmony_ci	 */
157362306a36Sopenharmony_ci	state->AS_Data.f_in = f_in;
157462306a36Sopenharmony_ci	/*  Request a 1st IF such that LO1 is on a step size */
157562306a36Sopenharmony_ci	state->AS_Data.f_if1_Request =
157662306a36Sopenharmony_ci	    MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
157762306a36Sopenharmony_ci			     state->AS_Data.f_LO1_Step,
157862306a36Sopenharmony_ci			     state->AS_Data.f_ref) - f_in;
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	/*
158162306a36Sopenharmony_ci	 * Calculate frequency settings.  f_IF1_FREQ + f_in is the
158262306a36Sopenharmony_ci	 * desired LO1 frequency
158362306a36Sopenharmony_ci	 */
158462306a36Sopenharmony_ci	MT2063_ResetExclZones(&state->AS_Data);
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci	f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	state->AS_Data.f_LO1 =
158962306a36Sopenharmony_ci	    MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
159062306a36Sopenharmony_ci			     state->AS_Data.f_ref);
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	state->AS_Data.f_LO2 =
159362306a36Sopenharmony_ci	    MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
159462306a36Sopenharmony_ci			     state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	/*
159762306a36Sopenharmony_ci	 * Check for any LO spurs in the output bandwidth and adjust
159862306a36Sopenharmony_ci	 * the LO settings to avoid them if needed
159962306a36Sopenharmony_ci	 */
160062306a36Sopenharmony_ci	status |= MT2063_AvoidSpurs(&state->AS_Data);
160162306a36Sopenharmony_ci	/*
160262306a36Sopenharmony_ci	 * MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
160362306a36Sopenharmony_ci	 * Recalculate the LO frequencies and the values to be placed
160462306a36Sopenharmony_ci	 * in the tuning registers.
160562306a36Sopenharmony_ci	 */
160662306a36Sopenharmony_ci	state->AS_Data.f_LO1 =
160762306a36Sopenharmony_ci	    MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
160862306a36Sopenharmony_ci			       state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
160962306a36Sopenharmony_ci	state->AS_Data.f_LO2 =
161062306a36Sopenharmony_ci	    MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
161162306a36Sopenharmony_ci			     state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
161262306a36Sopenharmony_ci	state->AS_Data.f_LO2 =
161362306a36Sopenharmony_ci	    MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
161462306a36Sopenharmony_ci			       state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci	/*
161762306a36Sopenharmony_ci	 *  Check the upconverter and downconverter frequency ranges
161862306a36Sopenharmony_ci	 */
161962306a36Sopenharmony_ci	if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
162062306a36Sopenharmony_ci	    || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
162162306a36Sopenharmony_ci		status |= MT2063_UPC_RANGE;
162262306a36Sopenharmony_ci	if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
162362306a36Sopenharmony_ci	    || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
162462306a36Sopenharmony_ci		status |= MT2063_DNC_RANGE;
162562306a36Sopenharmony_ci	/*  LO2 Lock bit was in a different place for B0 version  */
162662306a36Sopenharmony_ci	if (state->tuner_id == MT2063_B0)
162762306a36Sopenharmony_ci		LO2LK = 0x40;
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	/*
163062306a36Sopenharmony_ci	 *  If we have the same LO frequencies and we're already locked,
163162306a36Sopenharmony_ci	 *  then skip re-programming the LO registers.
163262306a36Sopenharmony_ci	 */
163362306a36Sopenharmony_ci	if ((ofLO1 != state->AS_Data.f_LO1)
163462306a36Sopenharmony_ci	    || (ofLO2 != state->AS_Data.f_LO2)
163562306a36Sopenharmony_ci	    || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
163662306a36Sopenharmony_ci		(LO1LK | LO2LK))) {
163762306a36Sopenharmony_ci		/*
163862306a36Sopenharmony_ci		 * Calculate the FIFFOF register value
163962306a36Sopenharmony_ci		 *
164062306a36Sopenharmony_ci		 *           IF1_Actual
164162306a36Sopenharmony_ci		 * FIFFOF = ------------ - 8 * FIFFC - 4992
164262306a36Sopenharmony_ci		 *            f_ref/64
164362306a36Sopenharmony_ci		 */
164462306a36Sopenharmony_ci		fiffof =
164562306a36Sopenharmony_ci		    (state->AS_Data.f_LO1 -
164662306a36Sopenharmony_ci		     f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
164762306a36Sopenharmony_ci		    4992;
164862306a36Sopenharmony_ci		if (fiffof > 0xFF)
164962306a36Sopenharmony_ci			fiffof = 0xFF;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci		/*
165262306a36Sopenharmony_ci		 * Place all of the calculated values into the local tuner
165362306a36Sopenharmony_ci		 * register fields.
165462306a36Sopenharmony_ci		 */
165562306a36Sopenharmony_ci		if (status >= 0) {
165662306a36Sopenharmony_ci			state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF);	/* DIV1q */
165762306a36Sopenharmony_ci			state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F);	/* NUM1q */
165862306a36Sopenharmony_ci			state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1)	/* DIV2q */
165962306a36Sopenharmony_ci								   |(Num2 >> 12));	/* NUM2q (hi) */
166062306a36Sopenharmony_ci			state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4);	/* NUM2q (mid) */
166162306a36Sopenharmony_ci			state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F));	/* NUM2q (lo) */
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci			/*
166462306a36Sopenharmony_ci			 * Now write out the computed register values
166562306a36Sopenharmony_ci			 * IMPORTANT: There is a required order for writing
166662306a36Sopenharmony_ci			 *            (0x05 must follow all the others).
166762306a36Sopenharmony_ci			 */
166862306a36Sopenharmony_ci			status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5);	/* 0x01 - 0x05 */
166962306a36Sopenharmony_ci			if (state->tuner_id == MT2063_B0) {
167062306a36Sopenharmony_ci				/* Re-write the one-shot bits to trigger the tune operation */
167162306a36Sopenharmony_ci				status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1);	/* 0x05 */
167262306a36Sopenharmony_ci			}
167362306a36Sopenharmony_ci			/* Write out the FIFF offset only if it's changing */
167462306a36Sopenharmony_ci			if (state->reg[MT2063_REG_FIFF_OFFSET] !=
167562306a36Sopenharmony_ci			    (u8) fiffof) {
167662306a36Sopenharmony_ci				state->reg[MT2063_REG_FIFF_OFFSET] =
167762306a36Sopenharmony_ci				    (u8) fiffof;
167862306a36Sopenharmony_ci				status |=
167962306a36Sopenharmony_ci				    mt2063_write(state,
168062306a36Sopenharmony_ci						    MT2063_REG_FIFF_OFFSET,
168162306a36Sopenharmony_ci						    &state->
168262306a36Sopenharmony_ci						    reg[MT2063_REG_FIFF_OFFSET],
168362306a36Sopenharmony_ci						    1);
168462306a36Sopenharmony_ci			}
168562306a36Sopenharmony_ci		}
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci		/*
168862306a36Sopenharmony_ci		 * Check for LO's locking
168962306a36Sopenharmony_ci		 */
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_ci		if (status < 0)
169262306a36Sopenharmony_ci			return status;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci		status = mt2063_lockStatus(state);
169562306a36Sopenharmony_ci		if (status < 0)
169662306a36Sopenharmony_ci			return status;
169762306a36Sopenharmony_ci		if (!status)
169862306a36Sopenharmony_ci			return -EINVAL;		/* Couldn't lock */
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci		/*
170162306a36Sopenharmony_ci		 * If we locked OK, assign calculated data to mt2063_state structure
170262306a36Sopenharmony_ci		 */
170362306a36Sopenharmony_ci		state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
170462306a36Sopenharmony_ci	}
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	return status;
170762306a36Sopenharmony_ci}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_cistatic const u8 MT2063B0_defaults[] = {
171062306a36Sopenharmony_ci	/* Reg,  Value */
171162306a36Sopenharmony_ci	0x19, 0x05,
171262306a36Sopenharmony_ci	0x1B, 0x1D,
171362306a36Sopenharmony_ci	0x1C, 0x1F,
171462306a36Sopenharmony_ci	0x1D, 0x0F,
171562306a36Sopenharmony_ci	0x1E, 0x3F,
171662306a36Sopenharmony_ci	0x1F, 0x0F,
171762306a36Sopenharmony_ci	0x20, 0x3F,
171862306a36Sopenharmony_ci	0x22, 0x21,
171962306a36Sopenharmony_ci	0x23, 0x3F,
172062306a36Sopenharmony_ci	0x24, 0x20,
172162306a36Sopenharmony_ci	0x25, 0x3F,
172262306a36Sopenharmony_ci	0x27, 0xEE,
172362306a36Sopenharmony_ci	0x2C, 0x27,	/*  bit at 0x20 is cleared below  */
172462306a36Sopenharmony_ci	0x30, 0x03,
172562306a36Sopenharmony_ci	0x2C, 0x07,	/*  bit at 0x20 is cleared here   */
172662306a36Sopenharmony_ci	0x2D, 0x87,
172762306a36Sopenharmony_ci	0x2E, 0xAA,
172862306a36Sopenharmony_ci	0x28, 0xE1,	/*  Set the FIFCrst bit here      */
172962306a36Sopenharmony_ci	0x28, 0xE0,	/*  Clear the FIFCrst bit here    */
173062306a36Sopenharmony_ci	0x00
173162306a36Sopenharmony_ci};
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
173462306a36Sopenharmony_cistatic const u8 MT2063B1_defaults[] = {
173562306a36Sopenharmony_ci	/* Reg,  Value */
173662306a36Sopenharmony_ci	0x05, 0xF0,
173762306a36Sopenharmony_ci	0x11, 0x10,	/* New Enable AFCsd */
173862306a36Sopenharmony_ci	0x19, 0x05,
173962306a36Sopenharmony_ci	0x1A, 0x6C,
174062306a36Sopenharmony_ci	0x1B, 0x24,
174162306a36Sopenharmony_ci	0x1C, 0x28,
174262306a36Sopenharmony_ci	0x1D, 0x8F,
174362306a36Sopenharmony_ci	0x1E, 0x14,
174462306a36Sopenharmony_ci	0x1F, 0x8F,
174562306a36Sopenharmony_ci	0x20, 0x57,
174662306a36Sopenharmony_ci	0x22, 0x21,	/* New - ver 1.03 */
174762306a36Sopenharmony_ci	0x23, 0x3C,	/* New - ver 1.10 */
174862306a36Sopenharmony_ci	0x24, 0x20,	/* New - ver 1.03 */
174962306a36Sopenharmony_ci	0x2C, 0x24,	/*  bit at 0x20 is cleared below  */
175062306a36Sopenharmony_ci	0x2D, 0x87,	/*  FIFFQ=0  */
175162306a36Sopenharmony_ci	0x2F, 0xF3,
175262306a36Sopenharmony_ci	0x30, 0x0C,	/* New - ver 1.11 */
175362306a36Sopenharmony_ci	0x31, 0x1B,	/* New - ver 1.11 */
175462306a36Sopenharmony_ci	0x2C, 0x04,	/*  bit at 0x20 is cleared here  */
175562306a36Sopenharmony_ci	0x28, 0xE1,	/*  Set the FIFCrst bit here      */
175662306a36Sopenharmony_ci	0x28, 0xE0,	/*  Clear the FIFCrst bit here    */
175762306a36Sopenharmony_ci	0x00
175862306a36Sopenharmony_ci};
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
176162306a36Sopenharmony_cistatic const u8 MT2063B3_defaults[] = {
176262306a36Sopenharmony_ci	/* Reg,  Value */
176362306a36Sopenharmony_ci	0x05, 0xF0,
176462306a36Sopenharmony_ci	0x19, 0x3D,
176562306a36Sopenharmony_ci	0x2C, 0x24,	/*  bit at 0x20 is cleared below  */
176662306a36Sopenharmony_ci	0x2C, 0x04,	/*  bit at 0x20 is cleared here  */
176762306a36Sopenharmony_ci	0x28, 0xE1,	/*  Set the FIFCrst bit here      */
176862306a36Sopenharmony_ci	0x28, 0xE0,	/*  Clear the FIFCrst bit here    */
176962306a36Sopenharmony_ci	0x00
177062306a36Sopenharmony_ci};
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_cistatic int mt2063_init(struct dvb_frontend *fe)
177362306a36Sopenharmony_ci{
177462306a36Sopenharmony_ci	int status;
177562306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
177662306a36Sopenharmony_ci	u8 all_resets = 0xF0;	/* reset/load bits */
177762306a36Sopenharmony_ci	const u8 *def = NULL;
177862306a36Sopenharmony_ci	char *step;
177962306a36Sopenharmony_ci	u32 FCRUN;
178062306a36Sopenharmony_ci	s32 maxReads;
178162306a36Sopenharmony_ci	u32 fcu_osc;
178262306a36Sopenharmony_ci	u32 i;
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	dprintk(2, "\n");
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci	state->rcvr_mode = MT2063_CABLE_QAM;
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	/*  Read the Part/Rev code from the tuner */
178962306a36Sopenharmony_ci	status = mt2063_read(state, MT2063_REG_PART_REV,
179062306a36Sopenharmony_ci			     &state->reg[MT2063_REG_PART_REV], 1);
179162306a36Sopenharmony_ci	if (status < 0) {
179262306a36Sopenharmony_ci		printk(KERN_ERR "Can't read mt2063 part ID\n");
179362306a36Sopenharmony_ci		return status;
179462306a36Sopenharmony_ci	}
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	/* Check the part/rev code */
179762306a36Sopenharmony_ci	switch (state->reg[MT2063_REG_PART_REV]) {
179862306a36Sopenharmony_ci	case MT2063_B0:
179962306a36Sopenharmony_ci		step = "B0";
180062306a36Sopenharmony_ci		break;
180162306a36Sopenharmony_ci	case MT2063_B1:
180262306a36Sopenharmony_ci		step = "B1";
180362306a36Sopenharmony_ci		break;
180462306a36Sopenharmony_ci	case MT2063_B2:
180562306a36Sopenharmony_ci		step = "B2";
180662306a36Sopenharmony_ci		break;
180762306a36Sopenharmony_ci	case MT2063_B3:
180862306a36Sopenharmony_ci		step = "B3";
180962306a36Sopenharmony_ci		break;
181062306a36Sopenharmony_ci	default:
181162306a36Sopenharmony_ci		printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
181262306a36Sopenharmony_ci		       state->reg[MT2063_REG_PART_REV]);
181362306a36Sopenharmony_ci		return -ENODEV;	/*  Wrong tuner Part/Rev code */
181462306a36Sopenharmony_ci	}
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	/*  Check the 2nd byte of the Part/Rev code from the tuner */
181762306a36Sopenharmony_ci	status = mt2063_read(state, MT2063_REG_RSVD_3B,
181862306a36Sopenharmony_ci			     &state->reg[MT2063_REG_RSVD_3B], 1);
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	/* b7 != 0 ==> NOT MT2063 */
182162306a36Sopenharmony_ci	if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
182262306a36Sopenharmony_ci		printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
182362306a36Sopenharmony_ci		       state->reg[MT2063_REG_PART_REV],
182462306a36Sopenharmony_ci		       state->reg[MT2063_REG_RSVD_3B]);
182562306a36Sopenharmony_ci		return -ENODEV;	/*  Wrong tuner Part/Rev code */
182662306a36Sopenharmony_ci	}
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci	printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	/*  Reset the tuner  */
183162306a36Sopenharmony_ci	status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
183262306a36Sopenharmony_ci	if (status < 0)
183362306a36Sopenharmony_ci		return status;
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	/* change all of the default values that vary from the HW reset values */
183662306a36Sopenharmony_ci	/*  def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
183762306a36Sopenharmony_ci	switch (state->reg[MT2063_REG_PART_REV]) {
183862306a36Sopenharmony_ci	case MT2063_B3:
183962306a36Sopenharmony_ci		def = MT2063B3_defaults;
184062306a36Sopenharmony_ci		break;
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	case MT2063_B1:
184362306a36Sopenharmony_ci		def = MT2063B1_defaults;
184462306a36Sopenharmony_ci		break;
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	case MT2063_B0:
184762306a36Sopenharmony_ci		def = MT2063B0_defaults;
184862306a36Sopenharmony_ci		break;
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	default:
185162306a36Sopenharmony_ci		return -ENODEV;
185262306a36Sopenharmony_ci	}
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	while (status >= 0 && *def) {
185562306a36Sopenharmony_ci		u8 reg = *def++;
185662306a36Sopenharmony_ci		u8 val = *def++;
185762306a36Sopenharmony_ci		status = mt2063_write(state, reg, &val, 1);
185862306a36Sopenharmony_ci	}
185962306a36Sopenharmony_ci	if (status < 0)
186062306a36Sopenharmony_ci		return status;
186162306a36Sopenharmony_ci
186262306a36Sopenharmony_ci	/*  Wait for FIFF location to complete.  */
186362306a36Sopenharmony_ci	FCRUN = 1;
186462306a36Sopenharmony_ci	maxReads = 10;
186562306a36Sopenharmony_ci	while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
186662306a36Sopenharmony_ci		msleep(2);
186762306a36Sopenharmony_ci		status = mt2063_read(state,
186862306a36Sopenharmony_ci					 MT2063_REG_XO_STATUS,
186962306a36Sopenharmony_ci					 &state->
187062306a36Sopenharmony_ci					 reg[MT2063_REG_XO_STATUS], 1);
187162306a36Sopenharmony_ci		FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
187262306a36Sopenharmony_ci	}
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	if (FCRUN != 0 || status < 0)
187562306a36Sopenharmony_ci		return -ENODEV;
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	status = mt2063_read(state,
187862306a36Sopenharmony_ci			   MT2063_REG_FIFFC,
187962306a36Sopenharmony_ci			   &state->reg[MT2063_REG_FIFFC], 1);
188062306a36Sopenharmony_ci	if (status < 0)
188162306a36Sopenharmony_ci		return status;
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	/* Read back all the registers from the tuner */
188462306a36Sopenharmony_ci	status = mt2063_read(state,
188562306a36Sopenharmony_ci				MT2063_REG_PART_REV,
188662306a36Sopenharmony_ci				state->reg, MT2063_REG_END_REGS);
188762306a36Sopenharmony_ci	if (status < 0)
188862306a36Sopenharmony_ci		return status;
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	/*  Initialize the tuner state.  */
189162306a36Sopenharmony_ci	state->tuner_id = state->reg[MT2063_REG_PART_REV];
189262306a36Sopenharmony_ci	state->AS_Data.f_ref = MT2063_REF_FREQ;
189362306a36Sopenharmony_ci	state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
189462306a36Sopenharmony_ci				      ((u32) state->reg[MT2063_REG_FIFFC] + 640);
189562306a36Sopenharmony_ci	state->AS_Data.f_if1_bw = MT2063_IF1_BW;
189662306a36Sopenharmony_ci	state->AS_Data.f_out = 43750000UL;
189762306a36Sopenharmony_ci	state->AS_Data.f_out_bw = 6750000UL;
189862306a36Sopenharmony_ci	state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
189962306a36Sopenharmony_ci	state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
190062306a36Sopenharmony_ci	state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
190162306a36Sopenharmony_ci	state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
190262306a36Sopenharmony_ci	state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
190362306a36Sopenharmony_ci	state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
190462306a36Sopenharmony_ci	state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
190562306a36Sopenharmony_ci	state->AS_Data.f_LO1 = 2181000000UL;
190662306a36Sopenharmony_ci	state->AS_Data.f_LO2 = 1486249786UL;
190762306a36Sopenharmony_ci	state->f_IF1_actual = state->AS_Data.f_if1_Center;
190862306a36Sopenharmony_ci	state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
190962306a36Sopenharmony_ci	state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
191062306a36Sopenharmony_ci	state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
191162306a36Sopenharmony_ci	state->num_regs = MT2063_REG_END_REGS;
191262306a36Sopenharmony_ci	state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
191362306a36Sopenharmony_ci	state->ctfilt_sw = 0;
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci	state->CTFiltMax[0] = 69230000;
191662306a36Sopenharmony_ci	state->CTFiltMax[1] = 105770000;
191762306a36Sopenharmony_ci	state->CTFiltMax[2] = 140350000;
191862306a36Sopenharmony_ci	state->CTFiltMax[3] = 177110000;
191962306a36Sopenharmony_ci	state->CTFiltMax[4] = 212860000;
192062306a36Sopenharmony_ci	state->CTFiltMax[5] = 241130000;
192162306a36Sopenharmony_ci	state->CTFiltMax[6] = 274370000;
192262306a36Sopenharmony_ci	state->CTFiltMax[7] = 309820000;
192362306a36Sopenharmony_ci	state->CTFiltMax[8] = 342450000;
192462306a36Sopenharmony_ci	state->CTFiltMax[9] = 378870000;
192562306a36Sopenharmony_ci	state->CTFiltMax[10] = 416210000;
192662306a36Sopenharmony_ci	state->CTFiltMax[11] = 456500000;
192762306a36Sopenharmony_ci	state->CTFiltMax[12] = 495790000;
192862306a36Sopenharmony_ci	state->CTFiltMax[13] = 534530000;
192962306a36Sopenharmony_ci	state->CTFiltMax[14] = 572610000;
193062306a36Sopenharmony_ci	state->CTFiltMax[15] = 598970000;
193162306a36Sopenharmony_ci	state->CTFiltMax[16] = 635910000;
193262306a36Sopenharmony_ci	state->CTFiltMax[17] = 672130000;
193362306a36Sopenharmony_ci	state->CTFiltMax[18] = 714840000;
193462306a36Sopenharmony_ci	state->CTFiltMax[19] = 739660000;
193562306a36Sopenharmony_ci	state->CTFiltMax[20] = 770410000;
193662306a36Sopenharmony_ci	state->CTFiltMax[21] = 814660000;
193762306a36Sopenharmony_ci	state->CTFiltMax[22] = 846950000;
193862306a36Sopenharmony_ci	state->CTFiltMax[23] = 867820000;
193962306a36Sopenharmony_ci	state->CTFiltMax[24] = 915980000;
194062306a36Sopenharmony_ci	state->CTFiltMax[25] = 947450000;
194162306a36Sopenharmony_ci	state->CTFiltMax[26] = 983110000;
194262306a36Sopenharmony_ci	state->CTFiltMax[27] = 1021630000;
194362306a36Sopenharmony_ci	state->CTFiltMax[28] = 1061870000;
194462306a36Sopenharmony_ci	state->CTFiltMax[29] = 1098330000;
194562306a36Sopenharmony_ci	state->CTFiltMax[30] = 1138990000;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	/*
194862306a36Sopenharmony_ci	 **   Fetch the FCU osc value and use it and the fRef value to
194962306a36Sopenharmony_ci	 **   scale all of the Band Max values
195062306a36Sopenharmony_ci	 */
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
195362306a36Sopenharmony_ci	status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
195462306a36Sopenharmony_ci			      &state->reg[MT2063_REG_CTUNE_CTRL], 1);
195562306a36Sopenharmony_ci	if (status < 0)
195662306a36Sopenharmony_ci		return status;
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci	/*  Read the ClearTune filter calibration value  */
195962306a36Sopenharmony_ci	status = mt2063_read(state, MT2063_REG_FIFFC,
196062306a36Sopenharmony_ci			     &state->reg[MT2063_REG_FIFFC], 1);
196162306a36Sopenharmony_ci	if (status < 0)
196262306a36Sopenharmony_ci		return status;
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	fcu_osc = state->reg[MT2063_REG_FIFFC];
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
196762306a36Sopenharmony_ci	status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
196862306a36Sopenharmony_ci			      &state->reg[MT2063_REG_CTUNE_CTRL], 1);
196962306a36Sopenharmony_ci	if (status < 0)
197062306a36Sopenharmony_ci		return status;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	/*  Adjust each of the values in the ClearTune filter cross-over table  */
197362306a36Sopenharmony_ci	for (i = 0; i < 31; i++)
197462306a36Sopenharmony_ci		state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	status = MT2063_SoftwareShutdown(state, 1);
197762306a36Sopenharmony_ci	if (status < 0)
197862306a36Sopenharmony_ci		return status;
197962306a36Sopenharmony_ci	status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
198062306a36Sopenharmony_ci	if (status < 0)
198162306a36Sopenharmony_ci		return status;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	state->init = true;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	return 0;
198662306a36Sopenharmony_ci}
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_cistatic int mt2063_get_status(struct dvb_frontend *fe, u32 *tuner_status)
198962306a36Sopenharmony_ci{
199062306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
199162306a36Sopenharmony_ci	int status;
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci	dprintk(2, "\n");
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	if (!state->init)
199662306a36Sopenharmony_ci		return -ENODEV;
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	*tuner_status = 0;
199962306a36Sopenharmony_ci	status = mt2063_lockStatus(state);
200062306a36Sopenharmony_ci	if (status < 0)
200162306a36Sopenharmony_ci		return status;
200262306a36Sopenharmony_ci	if (status)
200362306a36Sopenharmony_ci		*tuner_status = TUNER_STATUS_LOCKED;
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_ci	dprintk(1, "Tuner status: %d", *tuner_status);
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_ci	return 0;
200862306a36Sopenharmony_ci}
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_cistatic void mt2063_release(struct dvb_frontend *fe)
201162306a36Sopenharmony_ci{
201262306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	dprintk(2, "\n");
201562306a36Sopenharmony_ci
201662306a36Sopenharmony_ci	fe->tuner_priv = NULL;
201762306a36Sopenharmony_ci	kfree(state);
201862306a36Sopenharmony_ci}
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_cistatic int mt2063_set_analog_params(struct dvb_frontend *fe,
202162306a36Sopenharmony_ci				    struct analog_parameters *params)
202262306a36Sopenharmony_ci{
202362306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
202462306a36Sopenharmony_ci	s32 pict_car;
202562306a36Sopenharmony_ci	s32 pict2chanb_vsb;
202662306a36Sopenharmony_ci	s32 ch_bw;
202762306a36Sopenharmony_ci	s32 if_mid;
202862306a36Sopenharmony_ci	s32 rcvr_mode;
202962306a36Sopenharmony_ci	int status;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	dprintk(2, "\n");
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	if (!state->init) {
203462306a36Sopenharmony_ci		status = mt2063_init(fe);
203562306a36Sopenharmony_ci		if (status < 0)
203662306a36Sopenharmony_ci			return status;
203762306a36Sopenharmony_ci	}
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci	switch (params->mode) {
204062306a36Sopenharmony_ci	case V4L2_TUNER_RADIO:
204162306a36Sopenharmony_ci		pict_car = 38900000;
204262306a36Sopenharmony_ci		ch_bw = 8000000;
204362306a36Sopenharmony_ci		pict2chanb_vsb = -(ch_bw / 2);
204462306a36Sopenharmony_ci		rcvr_mode = MT2063_OFFAIR_ANALOG;
204562306a36Sopenharmony_ci		break;
204662306a36Sopenharmony_ci	case V4L2_TUNER_ANALOG_TV:
204762306a36Sopenharmony_ci		rcvr_mode = MT2063_CABLE_ANALOG;
204862306a36Sopenharmony_ci		if (params->std & ~V4L2_STD_MN) {
204962306a36Sopenharmony_ci			pict_car = 38900000;
205062306a36Sopenharmony_ci			ch_bw = 6000000;
205162306a36Sopenharmony_ci			pict2chanb_vsb = -1250000;
205262306a36Sopenharmony_ci		} else if (params->std & V4L2_STD_PAL_G) {
205362306a36Sopenharmony_ci			pict_car = 38900000;
205462306a36Sopenharmony_ci			ch_bw = 7000000;
205562306a36Sopenharmony_ci			pict2chanb_vsb = -1250000;
205662306a36Sopenharmony_ci		} else {		/* PAL/SECAM standards */
205762306a36Sopenharmony_ci			pict_car = 38900000;
205862306a36Sopenharmony_ci			ch_bw = 8000000;
205962306a36Sopenharmony_ci			pict2chanb_vsb = -1250000;
206062306a36Sopenharmony_ci		}
206162306a36Sopenharmony_ci		break;
206262306a36Sopenharmony_ci	default:
206362306a36Sopenharmony_ci		return -EINVAL;
206462306a36Sopenharmony_ci	}
206562306a36Sopenharmony_ci	if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	state->AS_Data.f_LO2_Step = 125000;	/* FIXME: probably 5000 for FM */
206862306a36Sopenharmony_ci	state->AS_Data.f_out = if_mid;
206962306a36Sopenharmony_ci	state->AS_Data.f_out_bw = ch_bw + 750000;
207062306a36Sopenharmony_ci	status = MT2063_SetReceiverMode(state, rcvr_mode);
207162306a36Sopenharmony_ci	if (status < 0)
207262306a36Sopenharmony_ci		return status;
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
207562306a36Sopenharmony_ci		params->frequency, ch_bw, pict2chanb_vsb);
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci	status = MT2063_Tune(state, (params->frequency + (pict2chanb_vsb + (ch_bw / 2))));
207862306a36Sopenharmony_ci	if (status < 0)
207962306a36Sopenharmony_ci		return status;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	state->frequency = params->frequency;
208262306a36Sopenharmony_ci	return 0;
208362306a36Sopenharmony_ci}
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci/*
208662306a36Sopenharmony_ci * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
208762306a36Sopenharmony_ci * So, the amount of the needed bandwidth is given by:
208862306a36Sopenharmony_ci *	Bw = Symbol_rate * (1 + 0.15)
208962306a36Sopenharmony_ci * As such, the maximum symbol rate supported by 6 MHz is given by:
209062306a36Sopenharmony_ci *	max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
209162306a36Sopenharmony_ci */
209262306a36Sopenharmony_ci#define MAX_SYMBOL_RATE_6MHz	5217391
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_cistatic int mt2063_set_params(struct dvb_frontend *fe)
209562306a36Sopenharmony_ci{
209662306a36Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
209762306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
209862306a36Sopenharmony_ci	int status;
209962306a36Sopenharmony_ci	s32 pict_car;
210062306a36Sopenharmony_ci	s32 pict2chanb_vsb;
210162306a36Sopenharmony_ci	s32 ch_bw;
210262306a36Sopenharmony_ci	s32 if_mid;
210362306a36Sopenharmony_ci	s32 rcvr_mode;
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	if (!state->init) {
210662306a36Sopenharmony_ci		status = mt2063_init(fe);
210762306a36Sopenharmony_ci		if (status < 0)
210862306a36Sopenharmony_ci			return status;
210962306a36Sopenharmony_ci	}
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_ci	dprintk(2, "\n");
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci	if (c->bandwidth_hz == 0)
211462306a36Sopenharmony_ci		return -EINVAL;
211562306a36Sopenharmony_ci	if (c->bandwidth_hz <= 6000000)
211662306a36Sopenharmony_ci		ch_bw = 6000000;
211762306a36Sopenharmony_ci	else if (c->bandwidth_hz <= 7000000)
211862306a36Sopenharmony_ci		ch_bw = 7000000;
211962306a36Sopenharmony_ci	else
212062306a36Sopenharmony_ci		ch_bw = 8000000;
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	switch (c->delivery_system) {
212362306a36Sopenharmony_ci	case SYS_DVBT:
212462306a36Sopenharmony_ci		rcvr_mode = MT2063_OFFAIR_COFDM;
212562306a36Sopenharmony_ci		pict_car = 36125000;
212662306a36Sopenharmony_ci		pict2chanb_vsb = -(ch_bw / 2);
212762306a36Sopenharmony_ci		break;
212862306a36Sopenharmony_ci	case SYS_DVBC_ANNEX_A:
212962306a36Sopenharmony_ci	case SYS_DVBC_ANNEX_C:
213062306a36Sopenharmony_ci		rcvr_mode = MT2063_CABLE_QAM;
213162306a36Sopenharmony_ci		pict_car = 36125000;
213262306a36Sopenharmony_ci		pict2chanb_vsb = -(ch_bw / 2);
213362306a36Sopenharmony_ci		break;
213462306a36Sopenharmony_ci	default:
213562306a36Sopenharmony_ci		return -EINVAL;
213662306a36Sopenharmony_ci	}
213762306a36Sopenharmony_ci	if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci	state->AS_Data.f_LO2_Step = 125000;	/* FIXME: probably 5000 for FM */
214062306a36Sopenharmony_ci	state->AS_Data.f_out = if_mid;
214162306a36Sopenharmony_ci	state->AS_Data.f_out_bw = ch_bw + 750000;
214262306a36Sopenharmony_ci	status = MT2063_SetReceiverMode(state, rcvr_mode);
214362306a36Sopenharmony_ci	if (status < 0)
214462306a36Sopenharmony_ci		return status;
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci	dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
214762306a36Sopenharmony_ci		c->frequency, ch_bw, pict2chanb_vsb);
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci	status = MT2063_Tune(state, (c->frequency + (pict2chanb_vsb + (ch_bw / 2))));
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ci	if (status < 0)
215262306a36Sopenharmony_ci		return status;
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	state->frequency = c->frequency;
215562306a36Sopenharmony_ci	return 0;
215662306a36Sopenharmony_ci}
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_cistatic int mt2063_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
215962306a36Sopenharmony_ci{
216062306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	dprintk(2, "\n");
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci	if (!state->init)
216562306a36Sopenharmony_ci		return -ENODEV;
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci	*freq = state->AS_Data.f_out;
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci	dprintk(1, "IF frequency: %d\n", *freq);
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci	return 0;
217262306a36Sopenharmony_ci}
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_cistatic int mt2063_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
217562306a36Sopenharmony_ci{
217662306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	dprintk(2, "\n");
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_ci	if (!state->init)
218162306a36Sopenharmony_ci		return -ENODEV;
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	*bw = state->AS_Data.f_out_bw - 750000;
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci	dprintk(1, "bandwidth: %d\n", *bw);
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci	return 0;
218862306a36Sopenharmony_ci}
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_cistatic const struct dvb_tuner_ops mt2063_ops = {
219162306a36Sopenharmony_ci	.info = {
219262306a36Sopenharmony_ci		 .name = "MT2063 Silicon Tuner",
219362306a36Sopenharmony_ci		 .frequency_min_hz  =  45 * MHz,
219462306a36Sopenharmony_ci		 .frequency_max_hz  = 865 * MHz,
219562306a36Sopenharmony_ci	 },
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	.init = mt2063_init,
219862306a36Sopenharmony_ci	.sleep = MT2063_Sleep,
219962306a36Sopenharmony_ci	.get_status = mt2063_get_status,
220062306a36Sopenharmony_ci	.set_analog_params = mt2063_set_analog_params,
220162306a36Sopenharmony_ci	.set_params    = mt2063_set_params,
220262306a36Sopenharmony_ci	.get_if_frequency = mt2063_get_if_frequency,
220362306a36Sopenharmony_ci	.get_bandwidth = mt2063_get_bandwidth,
220462306a36Sopenharmony_ci	.release = mt2063_release,
220562306a36Sopenharmony_ci};
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_cistruct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
220862306a36Sopenharmony_ci				   struct mt2063_config *config,
220962306a36Sopenharmony_ci				   struct i2c_adapter *i2c)
221062306a36Sopenharmony_ci{
221162306a36Sopenharmony_ci	struct mt2063_state *state = NULL;
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	dprintk(2, "\n");
221462306a36Sopenharmony_ci
221562306a36Sopenharmony_ci	state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
221662306a36Sopenharmony_ci	if (!state)
221762306a36Sopenharmony_ci		return NULL;
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci	state->config = config;
222062306a36Sopenharmony_ci	state->i2c = i2c;
222162306a36Sopenharmony_ci	state->frontend = fe;
222262306a36Sopenharmony_ci	state->reference = config->refclock / 1000;	/* kHz */
222362306a36Sopenharmony_ci	fe->tuner_priv = state;
222462306a36Sopenharmony_ci	fe->ops.tuner_ops = mt2063_ops;
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
222762306a36Sopenharmony_ci	return fe;
222862306a36Sopenharmony_ci}
222962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt2063_attach);
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci#if 0
223262306a36Sopenharmony_ci/*
223362306a36Sopenharmony_ci * Ancillary routines visible outside mt2063
223462306a36Sopenharmony_ci * FIXME: Remove them in favor of using standard tuner callbacks
223562306a36Sopenharmony_ci */
223662306a36Sopenharmony_cistatic int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
223762306a36Sopenharmony_ci{
223862306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
223962306a36Sopenharmony_ci	int err = 0;
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	dprintk(2, "\n");
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci	err = MT2063_SoftwareShutdown(state, 1);
224462306a36Sopenharmony_ci	if (err < 0)
224562306a36Sopenharmony_ci		printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci	return err;
224862306a36Sopenharmony_ci}
224962306a36Sopenharmony_ci
225062306a36Sopenharmony_cistatic int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
225162306a36Sopenharmony_ci{
225262306a36Sopenharmony_ci	struct mt2063_state *state = fe->tuner_priv;
225362306a36Sopenharmony_ci	int err = 0;
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	dprintk(2, "\n");
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci	err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
225862306a36Sopenharmony_ci	if (err < 0)
225962306a36Sopenharmony_ci		printk(KERN_ERR "%s: Invalid parameter\n", __func__);
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	return err;
226262306a36Sopenharmony_ci}
226362306a36Sopenharmony_ci#endif
226462306a36Sopenharmony_ci
226562306a36Sopenharmony_ciMODULE_AUTHOR("Mauro Carvalho Chehab");
226662306a36Sopenharmony_ciMODULE_DESCRIPTION("MT2063 Silicon tuner");
226762306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2268