blob: 0bf629292fe448644ccf3ba9ca0de12727015b45 [file] [log] [blame]
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03005
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006#include "mt2063.h"
7
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03008static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03009module_param(verbose, int, 0644);
10
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -030011/* positive error codes used internally */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030012
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030013/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030014#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030015
16/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
17#define MT2063_SPUR_CNT_MASK (0x001f0000)
18#define MT2063_SPUR_SHIFT (16)
19
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030020/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
21#define MT2063_UPC_RANGE (0x04000000)
22
23/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
24#define MT2063_DNC_RANGE (0x08000000)
25
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026/*
27 * Constant defining the version of the following structure
28 * and therefore the API for this code.
29 *
30 * When compiling the tuner driver, the preprocessor will
31 * check against this version number to make sure that
32 * it matches the version that the tuner driver knows about.
33 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030034
35/* DECT Frequency Avoidance */
36#define MT2063_DECT_AVOID_US_FREQS 0x00000001
37
38#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
39
40#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
41
42#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
43
44enum MT2063_DECT_Avoid_Type {
45 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
46 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
47 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
48 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
49};
50
51#define MT2063_MAX_ZONES 48
52
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030053struct MT2063_ExclZone_t {
54 u32 min_;
55 u32 max_;
56 struct MT2063_ExclZone_t *next_;
57};
58
59/*
60 * Structure of data needed for Spur Avoidance
61 */
62struct MT2063_AvoidSpursData_t {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030063 u32 f_ref;
64 u32 f_in;
65 u32 f_LO1;
66 u32 f_if1_Center;
67 u32 f_if1_Request;
68 u32 f_if1_bw;
69 u32 f_LO2;
70 u32 f_out;
71 u32 f_out_bw;
72 u32 f_LO1_Step;
73 u32 f_LO2_Step;
74 u32 f_LO1_FracN_Avoid;
75 u32 f_LO2_FracN_Avoid;
76 u32 f_zif_bw;
77 u32 f_min_LO_Separation;
78 u32 maxH1;
79 u32 maxH2;
80 enum MT2063_DECT_Avoid_Type avoidDECT;
81 u32 bSpurPresent;
82 u32 bSpurAvoided;
83 u32 nSpursFound;
84 u32 nZones;
85 struct MT2063_ExclZone_t *freeZones;
86 struct MT2063_ExclZone_t *usedZones;
87 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
88};
89
90/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030091 * Parameter for function MT2063_SetPowerMask that specifies the power down
92 * of various sections of the MT2063.
93 */
94enum MT2063_Mask_Bits {
95 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
96 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
97 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
98 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
99 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
100 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
101 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
102 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
103 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
104 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
105 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
106 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
107 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
108 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
109 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
110};
111
112/*
113 * Parameter for function MT2063_GetParam & MT2063_SetParam that
114 * specifies the tuning algorithm parameter to be read/written.
115 */
116enum MT2063_Param {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300117 /* min tuning step size (default: 50000 Hz) */
118 MT2063_STEPSIZE,
119
120 /* input center frequency set by MT2063_Tune() */
121 MT2063_INPUT_FREQ,
122
123 /* LO1 Frequency set by MT2063_Tune() */
124 MT2063_LO1_FREQ,
125
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300126 /* LO2 Frequency set by MT2063_Tune() */
127 MT2063_LO2_FREQ,
128
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300129 /* output center frequency set by MT2063_Tune() */
130 MT2063_OUTPUT_FREQ,
131
132 /* output bandwidth set by MT2063_Tune() */
133 MT2063_OUTPUT_BW,
134
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300135 /* Receiver Mode for some parameters. 1 is DVB-T */
136 MT2063_RCVR_MODE,
137
138 /* directly set LNA attenuation, parameter is value to set */
139 MT2063_ACLNA,
140
141 /* maximum LNA attenuation, parameter is value to set */
142 MT2063_ACLNA_MAX,
143
144 /* directly set ATN attenuation. Paremeter is value to set. */
145 MT2063_ACRF,
146
147 /* maxium ATN attenuation. Paremeter is value to set. */
148 MT2063_ACRF_MAX,
149
150 /* directly set FIF attenuation. Paremeter is value to set. */
151 MT2063_ACFIF,
152
153 /* maxium FIF attenuation. Paremeter is value to set. */
154 MT2063_ACFIF_MAX,
155
156 /* LNA Rin */
157 MT2063_LNA_RIN,
158
159 /* Power Detector LNA level target */
160 MT2063_LNA_TGT,
161
162 /* Power Detector 1 level */
163 MT2063_PD1,
164
165 /* Power Detector 1 level target */
166 MT2063_PD1_TGT,
167
168 /* Power Detector 2 level */
169 MT2063_PD2,
170
171 /* Power Detector 2 level target */
172 MT2063_PD2_TGT,
173
174 /* Selects, which DNC is activ */
175 MT2063_DNC_OUTPUT_ENABLE,
176
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300177 MT2063_EOP /* last entry in enumerated list */
178};
179
180/*
181 * Parameter for selecting tuner mode
182 */
183enum MT2063_RCVR_MODES {
184 MT2063_CABLE_QAM = 0, /* Digital cable */
185 MT2063_CABLE_ANALOG, /* Analog cable */
186 MT2063_OFFAIR_COFDM, /* Digital offair */
187 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
188 MT2063_OFFAIR_ANALOG, /* Analog offair */
189 MT2063_OFFAIR_8VSB, /* Analog offair */
190 MT2063_NUM_RCVR_MODES
191};
192
193/*
194 * Possible values for MT2063_DNC_OUTPUT
195 */
196enum MT2063_DNC_Output_Enable {
197 MT2063_DNC_NONE = 0,
198 MT2063_DNC_1,
199 MT2063_DNC_2,
200 MT2063_DNC_BOTH
201};
202
203/*
204** Two-wire serial bus subaddresses of the tuner registers.
205** Also known as the tuner's register addresses.
206*/
207enum MT2063_Register_Offsets {
208 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
209 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
210 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
211 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
212 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
213 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
214 MT2063_REG_RSVD_06, /* 0x06: Reserved */
215 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
216 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
217 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
218 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
219 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
220 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
221 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
222 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
223 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
224 MT2063_REG_RSVD_10, /* 0x10: Reserved */
225 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
226 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
227 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
228 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
229 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
230 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
231 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
232 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
233 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
234 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
235 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
236 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
237 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
238 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
239 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
240 MT2063_REG_RSVD_20, /* 0x20: Reserved */
241 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
242 MT2063_REG_RSVD_22, /* 0x22: Reserved */
243 MT2063_REG_RSVD_23, /* 0x23: Reserved */
244 MT2063_REG_RSVD_24, /* 0x24: Reserved */
245 MT2063_REG_RSVD_25, /* 0x25: Reserved */
246 MT2063_REG_RSVD_26, /* 0x26: Reserved */
247 MT2063_REG_RSVD_27, /* 0x27: Reserved */
248 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
249 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
250 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
251 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
252 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
253 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
254 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
255 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
256 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
257 MT2063_REG_RSVD_31, /* 0x31: Reserved */
258 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
259 MT2063_REG_RSVD_33, /* 0x33: Reserved */
260 MT2063_REG_RSVD_34, /* 0x34: Reserved */
261 MT2063_REG_RSVD_35, /* 0x35: Reserved */
262 MT2063_REG_RSVD_36, /* 0x36: Reserved */
263 MT2063_REG_RSVD_37, /* 0x37: Reserved */
264 MT2063_REG_RSVD_38, /* 0x38: Reserved */
265 MT2063_REG_RSVD_39, /* 0x39: Reserved */
266 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
267 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
268 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
269 MT2063_REG_END_REGS
270};
271
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300272enum MTTune_atv_standard {
273 MTTUNEA_UNKNOWN = 0,
274 MTTUNEA_PAL_B,
275 MTTUNEA_PAL_G,
276 MTTUNEA_PAL_I,
277 MTTUNEA_PAL_L,
278 MTTUNEA_PAL_MN,
279 MTTUNEA_PAL_DK,
280 MTTUNEA_DIGITAL,
281 MTTUNEA_FMRADIO,
282 MTTUNEA_DVBC,
283 MTTUNEA_DVBT
284};
285
286
287struct mt2063_state {
288 struct i2c_adapter *i2c;
289
290 const struct mt2063_config *config;
291 struct dvb_tuner_ops ops;
292 struct dvb_frontend *frontend;
293 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300294
295 enum MTTune_atv_standard tv_type;
296 u32 frequency;
297 u32 srate;
298 u32 bandwidth;
299 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300300
301 u32 tuner_id;
302 struct MT2063_AvoidSpursData_t AS_Data;
303 u32 f_IF1_actual;
304 u32 rcvr_mode;
305 u32 ctfilt_sw;
306 u32 CTFiltMax[31];
307 u32 num_regs;
308 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300309};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300310
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300311/* Prototypes */
312static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
313 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300314static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
315static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
316static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
317static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300318 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300319static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown);
320static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits);
321
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300322
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -0300323/*
324 * Ancillary routines visible outside mt2063
325 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300326unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300327{
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300328 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300329 int err = 0;
330
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -0300331 err = MT2063_SoftwareShutdown(state, 1);
332 if (err < 0)
333 printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300334
335 return err;
336}
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -0300337EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300338
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300339unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300340{
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300341 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300342 int err = 0;
343
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -0300344 err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
345 if (err < 0)
346 printk(KERN_ERR "%s: Invalid parameter\n", __func__);
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300347
348 return err;
349}
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -0300350EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300351
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300352/*
353 * mt2063_write - Write data into the I2C bus
354 */
355static u32 mt2063_write(struct mt2063_state *state,
356 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300357{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300358 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300359 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300360 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300361 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300362 .addr = state->config->tuner_address,
363 .flags = 0,
364 .buf = buf,
365 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300366 };
367
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300368 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300369 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300370
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300371 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300372 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300373 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300374
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300375 if (ret < 0)
376 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300377
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300378 return ret;
379}
380
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300381/*
382 * mt2063_read - Read data from the I2C bus
383 */
384static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300385 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300386{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300387 u32 status = 0; /* Status to be returned */
388 struct dvb_frontend *fe = state->frontend;
389 u32 i = 0;
390
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300391 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300392
393 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300394 int ret;
395 u8 b0[] = { subAddress + i };
396 struct i2c_msg msg[] = {
397 {
398 .addr = state->config->tuner_address,
399 .flags = I2C_M_RD,
400 .buf = b0,
401 .len = 1
402 }, {
403 .addr = state->config->tuner_address,
404 .flags = I2C_M_RD,
405 .buf = pData + 1,
406 .len = 1
407 }
408 };
409
410 ret = i2c_transfer(state->i2c, msg, 2);
411 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300412 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300413 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300414 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300415 return (status);
416}
417
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300418/*
419 * FIXME: Is this really needed?
420 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300421static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300422{
423 /*
424 ** ToDo: Add code here to implement a OS blocking
425 ** for a period of "nMinDelayTime" milliseconds.
426 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300427 msleep(10);
428
429 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300430}
431
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300432/*
433 * Microtune spur avoidance
434 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300435
436/* Implement ceiling, floor functions. */
437#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300438#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300439
440struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300441 s32 min_;
442 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300443};
444
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300445/*
446** Reset all exclusion zones.
447** Add zones to protect the PLL FracN regions near zero
448**
449** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
450** frequencies into MT_ResetExclZones().
451*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300452static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300453{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300454 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300455
456 pAS_Info->nZones = 0; /* this clears the used list */
457 pAS_Info->usedZones = NULL; /* reset ptr */
458 pAS_Info->freeZones = NULL; /* reset ptr */
459
460 center =
461 pAS_Info->f_ref *
462 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
463 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
464 while (center <
465 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
466 pAS_Info->f_LO1_FracN_Avoid) {
467 /* Exclude LO1 FracN */
468 MT2063_AddExclZone(pAS_Info,
469 center - pAS_Info->f_LO1_FracN_Avoid,
470 center - 1);
471 MT2063_AddExclZone(pAS_Info, center + 1,
472 center + pAS_Info->f_LO1_FracN_Avoid);
473 center += pAS_Info->f_ref;
474 }
475
476 center =
477 pAS_Info->f_ref *
478 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
479 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
480 while (center <
481 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
482 pAS_Info->f_LO2_FracN_Avoid) {
483 /* Exclude LO2 FracN */
484 MT2063_AddExclZone(pAS_Info,
485 center - pAS_Info->f_LO2_FracN_Avoid,
486 center - 1);
487 MT2063_AddExclZone(pAS_Info, center + 1,
488 center + pAS_Info->f_LO2_FracN_Avoid);
489 center += pAS_Info->f_ref;
490 }
491
492 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
493 /* Exclude LO1 values that conflict with DECT channels */
494 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
495 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
496 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
497 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
498 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
499 }
500
501 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
502 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
503 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
504 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
505 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
506 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
507 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
508 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
509 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
510 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
511 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
512 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300513}
514
515static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
516 *pAS_Info,
517 struct MT2063_ExclZone_t *pPrevNode)
518{
519 struct MT2063_ExclZone_t *pNode;
520 /* Check for a node in the free list */
521 if (pAS_Info->freeZones != NULL) {
522 /* Use one from the free list */
523 pNode = pAS_Info->freeZones;
524 pAS_Info->freeZones = pNode->next_;
525 } else {
526 /* Grab a node from the array */
527 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
528 }
529
530 if (pPrevNode != NULL) {
531 pNode->next_ = pPrevNode->next_;
532 pPrevNode->next_ = pNode;
533 } else { /* insert at the beginning of the list */
534
535 pNode->next_ = pAS_Info->usedZones;
536 pAS_Info->usedZones = pNode;
537 }
538
539 pAS_Info->nZones++;
540 return pNode;
541}
542
543static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
544 *pAS_Info,
545 struct MT2063_ExclZone_t *pPrevNode,
546 struct MT2063_ExclZone_t
547 *pNodeToRemove)
548{
549 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
550
551 /* Make previous node point to the subsequent node */
552 if (pPrevNode != NULL)
553 pPrevNode->next_ = pNext;
554
555 /* Add pNodeToRemove to the beginning of the freeZones */
556 pNodeToRemove->next_ = pAS_Info->freeZones;
557 pAS_Info->freeZones = pNodeToRemove;
558
559 /* Decrement node count */
560 pAS_Info->nZones--;
561
562 return pNext;
563}
564
565/*****************************************************************************
566**
567** Name: MT_AddExclZone
568**
569** Description: Add (and merge) an exclusion zone into the list.
570** If the range (f_min, f_max) is totally outside the
571** 1st IF BW, ignore the entry.
572** If the range (f_min, f_max) is negative, ignore the entry.
573**
574** Revision History:
575**
576** SCR Date Author Description
577** -------------------------------------------------------------------------
578** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
579** (f_min, f_max) < 0, ignore the entry.
580**
581*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300582static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300583 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300584{
585 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
586 struct MT2063_ExclZone_t *pPrev = NULL;
587 struct MT2063_ExclZone_t *pNext = NULL;
588
589 /* Check to see if this overlaps the 1st IF filter */
590 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
591 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
592 && (f_min < f_max)) {
593 /*
594 ** 1 2 3 4 5 6
595 **
596 ** New entry: |---| |--| |--| |-| |---| |--|
597 ** or or or or or
598 ** Existing: |--| |--| |--| |---| |-| |--|
599 */
600
601 /* Check for our place in the list */
602 while ((pNode != NULL) && (pNode->max_ < f_min)) {
603 pPrev = pNode;
604 pNode = pNode->next_;
605 }
606
607 if ((pNode != NULL) && (pNode->min_ < f_max)) {
608 /* Combine me with pNode */
609 if (f_min < pNode->min_)
610 pNode->min_ = f_min;
611 if (f_max > pNode->max_)
612 pNode->max_ = f_max;
613 } else {
614 pNode = InsertNode(pAS_Info, pPrev);
615 pNode->min_ = f_min;
616 pNode->max_ = f_max;
617 }
618
619 /* Look for merging possibilities */
620 pNext = pNode->next_;
621 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
622 if (pNext->max_ > pNode->max_)
623 pNode->max_ = pNext->max_;
624 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
625 }
626 }
627}
628
629/*****************************************************************************
630**
631** Name: MT_ChooseFirstIF
632**
633** Description: Choose the best available 1st IF
634** If f_Desired is not excluded, choose that first.
635** Otherwise, return the value closest to f_Center that is
636** not excluded
637**
638** Revision History:
639**
640** SCR Date Author Description
641** -------------------------------------------------------------------------
642** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
643** tuner DLL.
644** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
645** Added logic to force f_Center within 1/2 f_Step.
646**
647*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300648static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300649{
650 /*
651 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
652 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
653 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
654 ** However, the sum must be.
655 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300656 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300657 pAS_Info->f_LO1_Step *
658 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
659 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
660 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300661 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300662 (pAS_Info->f_LO1_Step >
663 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
664 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300665 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300666
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300667 s32 i;
668 s32 j = 0;
669 u32 bDesiredExcluded = 0;
670 u32 bZeroExcluded = 0;
671 s32 tmpMin, tmpMax;
672 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300673 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
674 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
675
676 if (pAS_Info->nZones == 0)
677 return f_Desired;
678
679 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
680 if (pAS_Info->f_if1_Center > f_Desired)
681 f_Center =
682 f_Desired +
683 f_Step *
684 ((pAS_Info->f_if1_Center - f_Desired +
685 f_Step / 2) / f_Step);
686 else
687 f_Center =
688 f_Desired -
689 f_Step *
690 ((f_Desired - pAS_Info->f_if1_Center +
691 f_Step / 2) / f_Step);
692
693 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300694 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300695 // return 0;
696
697 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
698 while (pNode != NULL) {
699 /* floor function */
700 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300701 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300702
703 /* ceil function */
704 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300705 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300706
707 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
708 bDesiredExcluded = 1;
709
710 if ((tmpMin < 0) && (tmpMax > 0))
711 bZeroExcluded = 1;
712
713 /* See if this zone overlaps the previous */
714 if ((j > 0) && (tmpMin < zones[j - 1].max_))
715 zones[j - 1].max_ = tmpMax;
716 else {
717 /* Add new zone */
718 //assert(j<MT2063_MAX_ZONES);
719 //if (j>=MT2063_MAX_ZONES)
720 //break;
721
722 zones[j].min_ = tmpMin;
723 zones[j].max_ = tmpMax;
724 j++;
725 }
726 pNode = pNode->next_;
727 }
728
729 /*
730 ** If the desired is okay, return with it
731 */
732 if (bDesiredExcluded == 0)
733 return f_Desired;
734
735 /*
736 ** If the desired is excluded and the center is okay, return with it
737 */
738 if (bZeroExcluded == 0)
739 return f_Center;
740
741 /* Find the value closest to 0 (f_Center) */
742 bestDiff = zones[0].min_;
743 for (i = 0; i < j; i++) {
744 if (abs(zones[i].min_) < abs(bestDiff))
745 bestDiff = zones[i].min_;
746 if (abs(zones[i].max_) < abs(bestDiff))
747 bestDiff = zones[i].max_;
748 }
749
750 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300751 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300752
753 return f_Center + (bestDiff * f_Step);
754}
755
756/****************************************************************************
757**
758** Name: gcd
759**
760** Description: Uses Euclid's algorithm
761**
762** Parameters: u, v - unsigned values whose GCD is desired.
763**
764** Global: None
765**
766** Returns: greatest common divisor of u and v, if either value
767** is 0, the other value is returned as the result.
768**
769** Dependencies: None.
770**
771** Revision History:
772**
773** SCR Date Author Description
774** -------------------------------------------------------------------------
775** N/A 06-01-2004 JWS Original
776** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
777** unsigned numbers.
778**
779****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300780static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300781{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300782 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300783
784 while (v != 0) {
785 r = u % v;
786 u = v;
787 v = r;
788 }
789
790 return u;
791}
792
793/****************************************************************************
794**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300795** Name: IsSpurInBand
796**
797** Description: Checks to see if a spur will be present within the IF's
798** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
799**
800** ma mb mc md
801** <--+-+-+-------------------+-------------------+-+-+-->
802** | ^ 0 ^ |
803** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
804** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
805**
806** Note that some equations are doubled to prevent round-off
807** problems when calculating fIFBW/2
808**
809** Parameters: pAS_Info - Avoid Spurs information block
810** fm - If spur, amount f_IF1 has to move negative
811** fp - If spur, amount f_IF1 has to move positive
812**
813** Global: None
814**
815** Returns: 1 if an LO spur would be present, otherwise 0.
816**
817** Dependencies: None.
818**
819** Revision History:
820**
821** SCR Date Author Description
822** -------------------------------------------------------------------------
823** N/A 11-28-2002 DAD Implemented algorithm from applied patent
824**
825****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300826static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
827 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300828{
829 /*
830 ** Calculate LO frequency settings.
831 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300832 u32 n, n0;
833 const u32 f_LO1 = pAS_Info->f_LO1;
834 const u32 f_LO2 = pAS_Info->f_LO2;
835 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
836 const u32 c = d - pAS_Info->f_out_bw;
837 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -0300838 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300839 s32 f_nsLO1, f_nsLO2;
840 s32 f_Spur;
841 u32 ma, mb, mc, md, me, mf;
842 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300843 *fm = 0;
844
845 /*
846 ** For each edge (d, c & f), calculate a scale, based on the gcd
847 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
848 ** gcd-based scale factor or f_Scale.
849 */
850 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300851 gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300852 hgds = gd_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300853 gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300854 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -0300855 gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300856 hgfs = gf_Scale / 2;
857
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300858 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300859
860 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
861 for (n = n0; n <= pAS_Info->maxH1; ++n) {
862 md = (n * ((f_LO1 + hgds) / gd_Scale) -
863 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
864
865 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
866 if (md >= pAS_Info->maxH1)
867 break;
868
869 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
870 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
871
872 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
873 if (md == ma)
874 continue;
875
876 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
877 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
878 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300879 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
880 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300881 f_Spur =
882 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
883 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
884
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300885 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
886 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300887 return 1;
888 }
889
890 /* Location of Zero-IF-spur to be checked */
891 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
892 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
893 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
894 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
895 if (me != mf) {
896 f_nsLO1 = n * (f_LO1 / gf_Scale);
897 f_nsLO2 = me * (f_LO2 / gf_Scale);
898 f_Spur =
899 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
900 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
901
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300902 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
903 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300904 return 1;
905 }
906
907 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
908 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
909 if (ma != mb) {
910 f_nsLO1 = n * (f_LO1 / gc_Scale);
911 f_nsLO2 = ma * (f_LO2 / gc_Scale);
912 f_Spur =
913 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
914 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
915
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300916 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
917 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300918 return 1;
919 }
920 }
921
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300922 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300923 return 0;
924}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300925
926/*****************************************************************************
927**
928** Name: MT_AvoidSpurs
929**
930** Description: Main entry point to avoid spurs.
931** Checks for existing spurs in present LO1, LO2 freqs
932** and if present, chooses spur-free LO1, LO2 combination
933** that tunes the same input/output frequencies.
934**
935** Revision History:
936**
937** SCR Date Author Description
938** -------------------------------------------------------------------------
939** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
940**
941*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300942static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300943{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300944 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300945 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300946 pAS_Info->bSpurAvoided = 0;
947 pAS_Info->nSpursFound = 0;
948
949 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300950 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300951
952 /*
953 ** Avoid LO Generated Spurs
954 **
955 ** Make sure that have no LO-related spurs within the IF output
956 ** bandwidth.
957 **
958 ** If there is an LO spur in this band, start at the current IF1 frequency
959 ** and work out until we find a spur-free frequency or run up against the
960 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
961 ** will be unchanged if a spur-free setting is not found.
962 */
963 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
964 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300965 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
966 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
967 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
968 u32 delta_IF1;
969 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300970
971 /*
972 ** Spur was found, attempt to find a spur-free 1st IF
973 */
974 do {
975 pAS_Info->nSpursFound++;
976
977 /* Raise f_IF1_upper, if needed */
978 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
979
980 /* Choose next IF1 that is closest to f_IF1_CENTER */
981 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
982
983 if (new_IF1 > zfIF1) {
984 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
985 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
986 } else {
987 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
988 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
989 }
990 zfIF1 = new_IF1;
991
992 if (zfIF1 > pAS_Info->f_if1_Center)
993 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
994 else
995 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
996 }
997 /*
998 ** Continue while the new 1st IF is still within the 1st IF bandwidth
999 ** and there is a spur in the band (again)
1000 */
1001 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1002 pAS_Info->f_if1_bw)
1003 && (pAS_Info->bSpurPresent =
1004 IsSpurInBand(pAS_Info, &fm, &fp)));
1005
1006 /*
1007 ** Use the LO-spur free values found. If the search went all the way to
1008 ** the 1st IF band edge and always found spurs, just leave the original
1009 ** choice. It's as "good" as any other.
1010 */
1011 if (pAS_Info->bSpurPresent == 1) {
1012 status |= MT2063_SPUR_PRESENT_ERR;
1013 pAS_Info->f_LO1 = zfLO1;
1014 pAS_Info->f_LO2 = zfLO2;
1015 } else
1016 pAS_Info->bSpurAvoided = 1;
1017 }
1018
1019 status |=
1020 ((pAS_Info->
1021 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1022
1023 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001024}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001025
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001026/*
1027** The expected version of MT_AvoidSpursData_t
1028** If the version is different, an updated file is needed from Microtune
1029*/
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001030
1031typedef enum {
1032 MT2063_SET_ATTEN,
1033 MT2063_INCR_ATTEN,
1034 MT2063_DECR_ATTEN
1035} MT2063_ATTEN_CNTL_MODE;
1036
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001037/*
Mauro Carvalho Chehab66aea302011-07-21 03:57:10 -03001038 * Constants used by the tuning algorithm
1039 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001040#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1041#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1042#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1043#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1044#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1045#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1046#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1047#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1048#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1049#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1050#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1051#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1052#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1053#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1054#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1055#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1056#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1057#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1058
1059/*
1060** Define the supported Part/Rev codes for the MT2063
1061*/
1062#define MT2063_B0 (0x9B)
1063#define MT2063_B1 (0x9C)
1064#define MT2063_B2 (0x9D)
1065#define MT2063_B3 (0x9E)
1066
1067/*
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001068** Constants for setting receiver modes.
1069** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1070** (DNC1GC & DNC2GC are the values, which are used, when the specific
1071** DNC Output is selected, the other is always off)
1072**
1073** If PAL-L or L' is received, set:
1074** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1075**
1076** --------------+----------------------------------------------
1077** Mode 0 : | MT2063_CABLE_QAM
1078** Mode 1 : | MT2063_CABLE_ANALOG
1079** Mode 2 : | MT2063_OFFAIR_COFDM
1080** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1081** Mode 4 : | MT2063_OFFAIR_ANALOG
1082** Mode 5 : | MT2063_OFFAIR_8VSB
1083** --------------+----+----+----+----+-----+-----+--------------
1084** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1085** --------------+----+----+----+----+-----+-----+
1086**
1087**
1088*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001089static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1090static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1091static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1092static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1093static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1094static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1095static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1096static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1097static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1098static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1099static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1100static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1101static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1102static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001103
1104/*
1105** Local Function Prototypes - not available for external access.
1106*/
1107
1108/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001109static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1110 u32 f_LO_Step, u32 f_Ref);
1111static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1112 u32 f_LO_Step, u32 f_Ref);
1113static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1114 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001115
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001116/**
1117 * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
1118 *
1119 * @state: struct mt2063_state pointer
1120 *
1121 * This function returns 0, if no lock, 1 if locked and a value < 1 if error
1122 */
1123unsigned int mt2063_lockStatus(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001124{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001125 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1126 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1127 const u32 nMaxLoops = nMaxWait / nPollRate;
1128 const u8 LO1LK = 0x80;
1129 u8 LO2LK = 0x08;
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001130 u32 status;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001131 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001132
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001133 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001134 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001135 LO2LK = 0x40;
1136
1137 do {
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001138 status = mt2063_read(state, MT2063_REG_LO_STATUS,
1139 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001140
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001141 if (status < 0)
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001142 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001143
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001144 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001145 (LO1LK | LO2LK)) {
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001146 return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001147 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001148 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001149 }
1150 while (++nDelays < nMaxLoops);
1151
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03001152 /*
1153 * Got no lock or partial lock
1154 */
1155 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001156}
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -03001157EXPORT_SYMBOL_GPL(mt2063_lockStatus);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001158
1159/****************************************************************************
1160**
1161** Name: MT2063_GetParam
1162**
1163** Description: Gets a tuning algorithm parameter.
1164**
1165** This function provides access to the internals of the
1166** tuning algorithm - mostly for testing purposes.
1167**
1168** Parameters: h - Tuner handle (returned by MT2063_Open)
1169** param - Tuning algorithm parameter
1170** (see enum MT2063_Param)
1171** pValue - ptr to returned value
1172**
1173** param Description
1174** ---------------------- --------------------------------
1175** MT2063_IC_ADDR Serial Bus address of this tuner
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001176** MT2063_SRO_FREQ crystal frequency
1177** MT2063_STEPSIZE minimum tuning step size
1178** MT2063_INPUT_FREQ input center frequency
1179** MT2063_LO1_FREQ LO1 Frequency
1180** MT2063_LO1_STEPSIZE LO1 minimum step size
1181** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1182** MT2063_IF1_ACTUAL Current 1st IF in use
1183** MT2063_IF1_REQUEST Requested 1st IF
1184** MT2063_IF1_CENTER Center of 1st IF SAW filter
1185** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1186** MT2063_ZIF_BW zero-IF bandwidth
1187** MT2063_LO2_FREQ LO2 Frequency
1188** MT2063_LO2_STEPSIZE LO2 minimum step size
1189** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1190** MT2063_OUTPUT_FREQ output center frequency
1191** MT2063_OUTPUT_BW output bandwidth
1192** MT2063_LO_SEPARATION min inter-tuner LO separation
1193** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1194** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1195** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1196** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1197** MT2063_NUM_SPURS # of spurs found/avoided
1198** MT2063_SPUR_AVOIDED >0 spurs avoided
1199** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1200** MT2063_RCVR_MODE Predefined modes.
1201** MT2063_ACLNA LNA attenuator gain code
1202** MT2063_ACRF RF attenuator gain code
1203** MT2063_ACFIF FIF attenuator gain code
1204** MT2063_ACLNA_MAX LNA attenuator limit
1205** MT2063_ACRF_MAX RF attenuator limit
1206** MT2063_ACFIF_MAX FIF attenuator limit
1207** MT2063_PD1 Actual value of PD1
1208** MT2063_PD2 Actual value of PD2
1209** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1210** MT2063_VGAGC VGA gain code
1211** MT2063_VGAOI VGA output current
1212** MT2063_TAGC TAGC setting
1213** MT2063_AMPGC AMP gain code
1214** MT2063_AVOID_DECT Avoid DECT Frequencies
1215** MT2063_CTFILT_SW Cleartune filter selection
1216**
1217** Usage: status |= MT2063_GetParam(hMT2063,
1218** MT2063_IF1_ACTUAL,
1219** &f_IF1_Actual);
1220**
1221** Returns: status:
1222** MT_OK - No errors
1223** MT_INV_HANDLE - Invalid tuner handle
1224** MT_ARG_NULL - Null pointer argument passed
1225** MT_ARG_RANGE - Invalid parameter requested
1226**
1227** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1228**
1229** See Also: MT2063_SetParam, MT2063_Open
1230**
1231** Revision History:
1232**
1233** SCR Date Author Description
1234** -------------------------------------------------------------------------
1235** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1236** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1237** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1238** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1239** in GetParam.
1240** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1241** Split SetParam up to ACLNA / ACLNA_MAX
1242** removed ACLNA_INRC/DECR (+RF & FIF)
1243** removed GCUAUTO / BYPATNDN/UP
1244** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1245** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1246** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1247**
1248****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001249static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001250{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001251 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001252 u32 Div;
1253 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001254
1255 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001256 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001257
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001258 switch (param) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001259 /* input center frequency */
1260 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001261 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001262 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001263
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001264 /* LO1 Frequency */
1265 case MT2063_LO1_FREQ:
1266 {
1267 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1268 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001269 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001270 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001271 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001272 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001273 Div = state->reg[MT2063_REG_LO1C_1];
1274 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1275 state->AS_Data.f_LO1 =
1276 (state->AS_Data.f_ref * Div) +
1277 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001278 f_ref, Num, 64);
1279 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001280 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001281 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001282
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001283 /* Bandwidth of 1st IF SAW filter */
1284 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001285 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001286 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001287
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001288 /* zero-IF bandwidth */
1289 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001290 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001291 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001292
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001293 /* LO2 Frequency */
1294 case MT2063_LO2_FREQ:
1295 {
1296 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1297 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001298 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001299 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001300 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001301 reg[MT2063_REG_LO2C_1], 3);
1302 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001303 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001304 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001305 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001306 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001307 (state->
1308 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001309 reg
1310 [MT2063_REG_LO2C_3]
1311 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001312 state->AS_Data.f_LO2 =
1313 (state->AS_Data.f_ref * Div) +
1314 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001315 f_ref, Num, 8191);
1316 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001317 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001318 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001319
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001320 /* LO2 FracN keep-out region */
1321 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001322 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001323 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001324
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001325 /* output center frequency */
1326 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001327 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001328 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001329
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001330 /* output bandwidth */
1331 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001332 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001333 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001334
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001335 /* Predefined receiver setup combination */
1336 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001337 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001338 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001339
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001340 case MT2063_PD1:
1341 case MT2063_PD2: {
1342 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001343 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001344 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1345 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001346
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001347 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001348
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001349 /* Initiate ADC output to reg 0x0A */
1350 if (reg != orig)
1351 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001352 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001353 MT2063_REG_BYP_CTRL,
1354 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001355
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001356 if (status < 0)
1357 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001358
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001359 for (i = 0; i < 8; i++) {
1360 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001361 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001362 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001363 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001364 reg
1365 [MT2063_REG_ADC_OUT],
1366 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001367
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001368 if (status >= 0)
1369 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001370 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001371 reg[MT2063_REG_ADC_OUT];
1372 else {
1373 if (i)
1374 *pValue /= i;
1375 return (status);
1376 }
1377 }
1378 *pValue /= 8; /* divide by number of reads */
1379 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001380
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001381 /* Restore value of Register BYP_CTRL */
1382 if (reg != orig)
1383 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001384 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001385 MT2063_REG_BYP_CTRL,
1386 &orig, 1);
1387 }
1388 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001389
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001390 /* Get LNA attenuator code */
1391 case MT2063_ACLNA:
1392 {
1393 u8 val;
1394 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001395 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001396 &val);
1397 *pValue = val & 0x1f;
1398 }
1399 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001400
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001401 /* Get RF attenuator code */
1402 case MT2063_ACRF:
1403 {
1404 u8 val;
1405 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001406 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001407 &val);
1408 *pValue = val & 0x1f;
1409 }
1410 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001411
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001412 /* Get FIF attenuator code */
1413 case MT2063_ACFIF:
1414 {
1415 u8 val;
1416 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001417 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001418 &val);
1419 *pValue = val & 0x1f;
1420 }
1421 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001422
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001423 /* Get LNA attenuator limit */
1424 case MT2063_ACLNA_MAX:
1425 {
1426 u8 val;
1427 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001428 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001429 &val);
1430 *pValue = val & 0x1f;
1431 }
1432 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001433
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001434 /* Get RF attenuator limit */
1435 case MT2063_ACRF_MAX:
1436 {
1437 u8 val;
1438 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001439 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001440 &val);
1441 *pValue = val & 0x1f;
1442 }
1443 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001444
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001445 /* Get FIF attenuator limit */
1446 case MT2063_ACFIF_MAX:
1447 {
1448 u8 val;
1449 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001450 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001451 &val);
1452 *pValue = val & 0x1f;
1453 }
1454 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001455
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001456 /* Get current used DNC output */
1457 case MT2063_DNC_OUTPUT_ENABLE:
1458 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001459 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1460 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001461 *pValue =
1462 (u32) MT2063_DNC_NONE;
1463 else
1464 *pValue =
1465 (u32) MT2063_DNC_2;
1466 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001467
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001468 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001469 *pValue =
1470 (u32) MT2063_DNC_1;
1471 else
1472 *pValue =
1473 (u32) MT2063_DNC_BOTH;
1474 }
1475 }
1476 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001477
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001478 default:
1479 status |= -ERANGE;
1480 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001481 return (status);
1482}
1483
1484/****************************************************************************
1485**
1486** Name: MT2063_GetReg
1487**
1488** Description: Gets an MT2063 register.
1489**
1490** Parameters: h - Tuner handle (returned by MT2063_Open)
1491** reg - MT2063 register/subaddress location
1492** *val - MT2063 register/subaddress value
1493**
1494** Returns: status:
1495** MT_OK - No errors
1496** MT_COMM_ERR - Serial bus communications error
1497** MT_INV_HANDLE - Invalid tuner handle
1498** MT_ARG_NULL - Null pointer argument passed
1499** MT_ARG_RANGE - Argument out of range
1500**
1501** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1502**
1503** Use this function if you need to read a register from
1504** the MT2063.
1505**
1506** Revision History:
1507**
1508** SCR Date Author Description
1509** -------------------------------------------------------------------------
1510** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1511**
1512****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001513static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001514{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001515 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001516
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001517 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001518 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001519
1520 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001521 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001522
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001523 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001524
1525 return (status);
1526}
1527
1528/******************************************************************************
1529**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001530** Name: MT2063_SetReceiverMode
1531**
1532** Description: Set the MT2063 receiver mode
1533**
1534** --------------+----------------------------------------------
1535** Mode 0 : | MT2063_CABLE_QAM
1536** Mode 1 : | MT2063_CABLE_ANALOG
1537** Mode 2 : | MT2063_OFFAIR_COFDM
1538** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1539** Mode 4 : | MT2063_OFFAIR_ANALOG
1540** Mode 5 : | MT2063_OFFAIR_8VSB
1541** --------------+----+----+----+----+-----+--------------------
1542** (DNC1GC & DNC2GC are the values, which are used, when the specific
1543** DNC Output is selected, the other is always off)
1544**
1545** |<---------- Mode -------------->|
1546** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1547** ------------+-----+-----+-----+-----+-----+-----+
1548** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1549** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1550** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1551** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1552** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1553** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1554** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1555** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1556** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1557** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1558** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1559** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1560** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1561** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1562** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1563**
1564**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001565** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001566** Mode - desired reciever mode
1567**
1568** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1569**
1570** Returns: status:
1571** MT_OK - No errors
1572** MT_COMM_ERR - Serial bus communications error
1573**
1574** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1575** Assumes that the tuner cache is valid.
1576**
1577** Revision History:
1578**
1579** SCR Date Author Description
1580** -------------------------------------------------------------------------
1581** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1582** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1583** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1584** modulation
1585** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1586** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1587** the same settings as with MT Launcher
1588** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1589** Add SetParam DNC_OUTPUT_ENABLE
1590** Removed VGAGC from receiver mode,
1591** default now 1
1592** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1593** Add SetParam AMPGC, removed from rcvr-mode
1594** Corrected names of GCU values
1595** reorganized receiver modes, removed,
1596** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1597** Actualized Receiver-Mode values
1598** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1599** N/A 11-27-2007 PINZ Improved buffered writing
1600** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1601** correct wakeup of the LNA after shutdown
1602** Set AFCsd = 1 as default
1603** Changed CAP1sel default
1604** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1605** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1606** Split SetParam up to ACLNA / ACLNA_MAX
1607** removed ACLNA_INRC/DECR (+RF & FIF)
1608** removed GCUAUTO / BYPATNDN/UP
1609**
1610******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001611static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001612 enum MT2063_RCVR_MODES Mode)
1613{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001614 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001615 u8 val;
1616 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001617
1618 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001619 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001620
1621 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001622 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001623 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001624 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001625 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001626 ? 0x40 :
1627 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001628 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1629 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001630 }
1631 }
1632
1633 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001634 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001635 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001636 }
1637
1638 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001639 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001640 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001641 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001642 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001643 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001644 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001645 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001646 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001647 /* trigger FIFF calibration, needed after changing FIFFQ */
1648 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001649 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001650 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001651 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001652 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001653 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001654 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001655 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001656 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001657 }
1658 }
1659
1660 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001661 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
1662 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001663
1664 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001665 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001666 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001667 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001668 }
1669
1670 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001671 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001672 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001673 }
1674
1675 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001676 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001677 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001678 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001679 }
1680
1681 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001682 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001683 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001684 }
1685
1686 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001687 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001688 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001689 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001690 }
1691
1692 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001693 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001694 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001695 }
1696
1697 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001698 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001699 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001700 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001701 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001702 ? 0x80 :
1703 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001704 if (state->reg[MT2063_REG_LNA_TGT] != val) {
1705 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001706 }
1707 }
1708
1709 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001710 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001711 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001712 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001713 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001714 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001715 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1716 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001717 }
1718 }
1719
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001720 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001721 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001722
1723 return (status);
1724}
1725
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001726/****************************************************************************
1727**
1728** Name: MT2063_SetParam
1729**
1730** Description: Sets a tuning algorithm parameter.
1731**
1732** This function provides access to the internals of the
1733** tuning algorithm. You can override many of the tuning
1734** algorithm defaults using this function.
1735**
1736** Parameters: h - Tuner handle (returned by MT2063_Open)
1737** param - Tuning algorithm parameter
1738** (see enum MT2063_Param)
1739** nValue - value to be set
1740**
1741** param Description
1742** ---------------------- --------------------------------
1743** MT2063_SRO_FREQ crystal frequency
1744** MT2063_STEPSIZE minimum tuning step size
1745** MT2063_LO1_FREQ LO1 frequency
1746** MT2063_LO1_STEPSIZE LO1 minimum step size
1747** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1748** MT2063_IF1_REQUEST Requested 1st IF
1749** MT2063_ZIF_BW zero-IF bandwidth
1750** MT2063_LO2_FREQ LO2 frequency
1751** MT2063_LO2_STEPSIZE LO2 minimum step size
1752** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1753** MT2063_OUTPUT_FREQ output center frequency
1754** MT2063_OUTPUT_BW output bandwidth
1755** MT2063_LO_SEPARATION min inter-tuner LO separation
1756** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1757** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1758** MT2063_RCVR_MODE Predefined modes
1759** MT2063_LNA_RIN Set LNA Rin (*)
1760** MT2063_LNA_TGT Set target power level at LNA (*)
1761** MT2063_PD1_TGT Set target power level at PD1 (*)
1762** MT2063_PD2_TGT Set target power level at PD2 (*)
1763** MT2063_ACLNA_MAX LNA attenuator limit (*)
1764** MT2063_ACRF_MAX RF attenuator limit (*)
1765** MT2063_ACFIF_MAX FIF attenuator limit (*)
1766** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1767** MT2063_VGAGC VGA gain code
1768** MT2063_VGAOI VGA output current
1769** MT2063_TAGC TAGC setting
1770** MT2063_AMPGC AMP gain code
1771** MT2063_AVOID_DECT Avoid DECT Frequencies
1772** MT2063_CTFILT_SW Cleartune filter selection
1773**
1774** (*) This parameter is set by MT2063_RCVR_MODE, do not call
1775** additionally.
1776**
1777** Usage: status |= MT2063_SetParam(hMT2063,
1778** MT2063_STEPSIZE,
1779** 50000);
1780**
1781** Returns: status:
1782** MT_OK - No errors
1783** MT_INV_HANDLE - Invalid tuner handle
1784** MT_ARG_NULL - Null pointer argument passed
1785** MT_ARG_RANGE - Invalid parameter requested
1786** or set value out of range
1787** or non-writable parameter
1788**
1789** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1790**
1791** See Also: MT2063_GetParam, MT2063_Open
1792**
1793** Revision History:
1794**
1795** SCR Date Author Description
1796** -------------------------------------------------------------------------
1797** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1798** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1799** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1800** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1801** Split SetParam up to ACLNA / ACLNA_MAX
1802** removed ACLNA_INRC/DECR (+RF & FIF)
1803** removed GCUAUTO / BYPATNDN/UP
1804** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1805** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1806** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1807**
1808****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001809static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03001810 enum MT2063_Param param,
1811 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001812{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001813 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001814 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001815
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001816 switch (param) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001817 /* LO1 frequency */
1818 case MT2063_LO1_FREQ:
1819 {
1820 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
1821 /* Capture the Divider and Numerator portions of other LO */
1822 u8 tempLO2CQ[3];
1823 u8 tempLO2C[3];
1824 u8 tmpOneShot;
1825 u32 Div, FracN;
1826 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001827
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001828 /* Buffer the queue for restoration later and get actual LO2 values. */
1829 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001830 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001831 MT2063_REG_LO2CQ_1,
1832 &(tempLO2CQ[0]), 3);
1833 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001834 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001835 MT2063_REG_LO2C_1,
1836 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001837
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001838 /* clear the one-shot bits */
1839 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
1840 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001841
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001842 /* only write the queue values if they are different from the actual. */
1843 if ((tempLO2CQ[0] != tempLO2C[0]) ||
1844 (tempLO2CQ[1] != tempLO2C[1]) ||
1845 (tempLO2CQ[2] != tempLO2C[2])) {
1846 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001847 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001848 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001849 MT2063_REG_LO2CQ_1,
1850 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001851
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001852 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001853 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001854 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001855 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001856 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001857 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001858 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001859 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001860 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001861 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001862 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001863
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001864 /* Calculate the Divider and Numberator components of LO1 */
1865 status =
1866 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001867 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001868 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001869 state->AS_Data.f_ref);
1870 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001871 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001872 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001873 (u8) (FracN);
1874 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001875 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001876 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001877 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001878 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001879
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001880 /* set the one-shot bit to load the pair of LO values */
1881 tmpOneShot = tempLO2CQ[2] | 0xE0;
1882 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001883 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001884 MT2063_REG_LO2CQ_3,
1885 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001886
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001887 /* only restore the queue values if they were different from the actual. */
1888 if (restore) {
1889 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001890 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001891 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001892 MT2063_REG_LO2CQ_1,
1893 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001894
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001895 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001896 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001897 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001898 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001899 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001900 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001901 tempLO2CQ[2];
1902 }
1903
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001904 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001905 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001906 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001907 }
1908 break;
1909
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001910 /* zero-IF bandwidth */
1911 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001912 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001913 break;
1914
1915 /* LO2 frequency */
1916 case MT2063_LO2_FREQ:
1917 {
1918 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
1919 /* Capture the Divider and Numerator portions of other LO */
1920 u8 tempLO1CQ[2];
1921 u8 tempLO1C[2];
1922 u32 Div2;
1923 u32 FracN2;
1924 u8 tmpOneShot;
1925 u8 restore = 0;
1926
1927 /* Buffer the queue for restoration later and get actual LO2 values. */
1928 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001929 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001930 MT2063_REG_LO1CQ_1,
1931 &(tempLO1CQ[0]), 2);
1932 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001933 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001934 MT2063_REG_LO1C_1,
1935 &(tempLO1C[0]), 2);
1936
1937 /* only write the queue values if they are different from the actual. */
1938 if ((tempLO1CQ[0] != tempLO1C[0])
1939 || (tempLO1CQ[1] != tempLO1C[1])) {
1940 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001941 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001942 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001943 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001944 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001945
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001946 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001947 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001948 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001949 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001950 tempLO1C[1];
1951 restore = 1;
1952 }
1953
1954 /* Calculate the Divider and Numberator components of LO2 */
1955 status =
1956 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001957 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001958 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001959 state->AS_Data.f_ref);
1960 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001961 (u8) ((Div2 << 1) |
1962 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001963 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001964 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001965 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001966 (u8) ((FracN2 & 0x0F));
1967 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001968 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001969 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001970 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001971 reg[MT2063_REG_LO1CQ_1], 3);
1972
1973 /* set the one-shot bit to load the LO values */
1974 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001975 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001976 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001977 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001978 MT2063_REG_LO2CQ_3,
1979 &tmpOneShot, 1);
1980
1981 /* only restore LO1 queue value if they were different from the actual. */
1982 if (restore) {
1983 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001984 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001985 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001986 MT2063_REG_LO1CQ_1,
1987 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001988
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001989 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001990 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001991 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001992 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001993 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001994 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001996 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001997 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001998 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001999 }
2000 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002001
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002002 /* LO2 FracN keep-out region */
2003 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002004 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002005 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002006
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002007 /* output center frequency */
2008 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002009 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002010 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002011
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002012 /* output bandwidth */
2013 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002014 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002015 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002016
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002017 case MT2063_RCVR_MODE:
2018 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002019 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002020 (enum MT2063_RCVR_MODES)
2021 nValue);
2022 break;
2023
2024 /* Set LNA Rin -- nValue is desired value */
2025 case MT2063_LNA_RIN:
2026 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002027 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002028 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2029 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002030 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002031 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002032 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002033 val);
2034 }
2035 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002036
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002037 /* Set target power level at LNA -- nValue is desired value */
2038 case MT2063_LNA_TGT:
2039 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002040 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002041 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2042 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002043 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002044 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002045 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002046 val);
2047 }
2048 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002049
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002050 /* Set target power level at PD1 -- nValue is desired value */
2051 case MT2063_PD1_TGT:
2052 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002053 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002054 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2055 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002056 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002057 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002058 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002059 val);
2060 }
2061 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002062
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002063 /* Set target power level at PD2 -- nValue is desired value */
2064 case MT2063_PD2_TGT:
2065 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002066 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002067 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2068 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002069 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002070 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002071 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002072 val);
2073 }
2074 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002075
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002076 /* Set LNA atten limit -- nValue is desired value */
2077 case MT2063_ACLNA_MAX:
2078 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002079 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002080 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2081 &
2082 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002083 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002084 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002085 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002086 val);
2087 }
2088 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002089
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002090 /* Set RF atten limit -- nValue is desired value */
2091 case MT2063_ACRF_MAX:
2092 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002093 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002094 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2095 &
2096 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002097 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002098 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002099 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002100 }
2101 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002102
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002103 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2104 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002105 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002106 && nValue > 5)
2107 nValue = 5;
2108 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002109 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002110 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2111 &
2112 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002113 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002114 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002115 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002116 val);
2117 }
2118 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002119
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002120 case MT2063_DNC_OUTPUT_ENABLE:
2121 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002122 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002123 case MT2063_DNC_NONE:
2124 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002125 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2126 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002127 val)
2128 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002129 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002130 MT2063_REG_DNC_GAIN,
2131 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002132
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002133 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2134 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002135 val)
2136 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002137 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002138 MT2063_REG_VGA_GAIN,
2139 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002140
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002141 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2142 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002143 val)
2144 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002145 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002146 MT2063_REG_RSVD_20,
2147 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002148
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002149 break;
2150 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002151 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002152 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002153 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2154 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002155 val)
2156 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002157 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002158 MT2063_REG_DNC_GAIN,
2159 val);
2160
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002161 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2162 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002163 val)
2164 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002165 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002166 MT2063_REG_VGA_GAIN,
2167 val);
2168
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002169 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2170 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002171 val)
2172 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002173 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002174 MT2063_REG_RSVD_20,
2175 val);
2176
2177 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002178 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002179 case MT2063_DNC_2:
2180 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002181 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2182 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002183 val)
2184 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002185 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002186 MT2063_REG_DNC_GAIN,
2187 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002188
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002189 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2190 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002191 val)
2192 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002193 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002194 MT2063_REG_VGA_GAIN,
2195 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002196
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002197 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2198 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002199 val)
2200 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002201 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002202 MT2063_REG_RSVD_20,
2203 val);
2204
2205 break;
2206 }
2207 case MT2063_DNC_BOTH:
2208 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002209 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2210 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002211 val)
2212 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002213 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002214 MT2063_REG_DNC_GAIN,
2215 val);
2216
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002217 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2218 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002219 val)
2220 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002221 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002222 MT2063_REG_VGA_GAIN,
2223 val);
2224
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002225 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2226 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002227 val)
2228 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002229 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002230 MT2063_REG_RSVD_20,
2231 val);
2232
2233 break;
2234 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002235 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002236 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002237 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002238 break;
2239
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002240 default:
2241 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002242 }
2243 return (status);
2244}
2245
2246/****************************************************************************
2247**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002248** Name: MT2063_ClearPowerMaskBits
2249**
2250** Description: Clears the power-down mask bits for various sections of
2251** the MT2063
2252**
2253** Parameters: h - Tuner handle (returned by MT2063_Open)
2254** Bits - Mask bits to be cleared.
2255**
2256** See definition of MT2063_Mask_Bits type for description
2257** of each of the power bits.
2258**
2259** Returns: status:
2260** MT_OK - No errors
2261** MT_INV_HANDLE - Invalid tuner handle
2262** MT_COMM_ERR - Serial bus communications error
2263**
2264** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2265**
2266** Revision History:
2267**
2268** SCR Date Author Description
2269** -------------------------------------------------------------------------
2270** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2271**
2272****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002273static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002274{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002275 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002276
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002277 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
2278 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002279 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002280 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002281 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002282 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002283 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002284 }
2285 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002286 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002287 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002288 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002289 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002290 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002291 }
2292
2293 return (status);
2294}
2295
2296/****************************************************************************
2297**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002298** Name: MT2063_SoftwareShutdown
2299**
2300** Description: Enables or disables software shutdown function. When
2301** Shutdown==1, any section whose power mask is set will be
2302** shutdown.
2303**
2304** Parameters: h - Tuner handle (returned by MT2063_Open)
2305** Shutdown - 1 = shutdown the masked sections, otherwise
2306** power all sections on
2307**
2308** Returns: status:
2309** MT_OK - No errors
2310** MT_INV_HANDLE - Invalid tuner handle
2311** MT_COMM_ERR - Serial bus communications error
2312**
2313** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2314**
2315** Revision History:
2316**
2317** SCR Date Author Description
2318** -------------------------------------------------------------------------
2319** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2320** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
2321** correct wakeup of the LNA
2322**
2323****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002324static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002325{
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002326 u32 status; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002327
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002328 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002329 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002330 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002331 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002332
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002333 status = mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002334 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002335 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002336
2337 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002338 state->reg[MT2063_REG_BYP_CTRL] =
2339 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002340 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002341 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002342 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002343 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002344 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002345 state->reg[MT2063_REG_BYP_CTRL] =
2346 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002347 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002348 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002349 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002350 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002351 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002352 }
2353
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002354 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002355}
2356
2357/****************************************************************************
2358**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002359** Name: MT2063_SetReg
2360**
2361** Description: Sets an MT2063 register.
2362**
2363** Parameters: h - Tuner handle (returned by MT2063_Open)
2364** reg - MT2063 register/subaddress location
2365** val - MT2063 register/subaddress value
2366**
2367** Returns: status:
2368** MT_OK - No errors
2369** MT_COMM_ERR - Serial bus communications error
2370** MT_INV_HANDLE - Invalid tuner handle
2371** MT_ARG_RANGE - Argument out of range
2372**
2373** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2374**
2375** Use this function if you need to override a default
2376** register value
2377**
2378** Revision History:
2379**
2380** SCR Date Author Description
2381** -------------------------------------------------------------------------
2382** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2383**
2384****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002385static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002386{
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002387 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002388
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002389 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002390 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002391
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002392 status = mt2063_write(state, reg, &val, 1);
2393 if (status < 0)
2394 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002395
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002396 state->reg[reg] = val;
2397
2398 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002399}
2400
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002401static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002402{
2403 return f_ref * (f_LO / f_ref)
2404 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
2405}
2406
2407/****************************************************************************
2408**
2409** Name: fLO_FractionalTerm
2410**
2411** Description: Calculates the portion contributed by FracN / denom.
2412**
2413** This function preserves maximum precision without
2414** risk of overflow. It accurately calculates
2415** f_ref * num / denom to within 1 HZ with fixed math.
2416**
2417** Parameters: num - Fractional portion of the multiplier
2418** denom - denominator portion of the ratio
2419** This routine successfully handles denom values
2420** up to and including 2^18.
2421** f_Ref - SRO frequency. This calculation handles
2422** f_ref as two separate 14-bit fields.
2423** Therefore, a maximum value of 2^28-1
2424** may safely be used for f_ref. This is
2425** the genesis of the magic number "14" and the
2426** magic mask value of 0x03FFF.
2427**
2428** Returns: f_ref * num / denom
2429**
2430** Revision History:
2431**
2432** SCR Date Author Description
2433** -------------------------------------------------------------------------
2434** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2435**
2436****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002437static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
2438 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002439{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002440 u32 t1 = (f_ref >> 14) * num;
2441 u32 term1 = t1 / denom;
2442 u32 loss = t1 % denom;
2443 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002444 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
2445 return ((term1 << 14) + term2);
2446}
2447
2448/****************************************************************************
2449**
2450** Name: CalcLO1Mult
2451**
2452** Description: Calculates Integer divider value and the numerator
2453** value for a FracN PLL.
2454**
2455** This function assumes that the f_LO and f_Ref are
2456** evenly divisible by f_LO_Step.
2457**
2458** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2459** FracN - OUTPUT: Fractional portion of the multiplier
2460** f_LO - desired LO frequency.
2461** f_LO_Step - Minimum step size for the LO (in Hz).
2462** f_Ref - SRO frequency.
2463** f_Avoid - Range of PLL frequencies to avoid near
2464** integer multiples of f_Ref (in Hz).
2465**
2466** Returns: Recalculated LO frequency.
2467**
2468** Revision History:
2469**
2470** SCR Date Author Description
2471** -------------------------------------------------------------------------
2472** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2473**
2474****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002475static u32 MT2063_CalcLO1Mult(u32 * Div,
2476 u32 * FracN,
2477 u32 f_LO,
2478 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002479{
2480 /* Calculate the whole number portion of the divider */
2481 *Div = f_LO / f_Ref;
2482
2483 /* Calculate the numerator value (round to nearest f_LO_Step) */
2484 *FracN =
2485 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2486 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2487
2488 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
2489}
2490
2491/****************************************************************************
2492**
2493** Name: CalcLO2Mult
2494**
2495** Description: Calculates Integer divider value and the numerator
2496** value for a FracN PLL.
2497**
2498** This function assumes that the f_LO and f_Ref are
2499** evenly divisible by f_LO_Step.
2500**
2501** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2502** FracN - OUTPUT: Fractional portion of the multiplier
2503** f_LO - desired LO frequency.
2504** f_LO_Step - Minimum step size for the LO (in Hz).
2505** f_Ref - SRO frequency.
2506** f_Avoid - Range of PLL frequencies to avoid near
2507** integer multiples of f_Ref (in Hz).
2508**
2509** Returns: Recalculated LO frequency.
2510**
2511** Revision History:
2512**
2513** SCR Date Author Description
2514** -------------------------------------------------------------------------
2515** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2516**
2517****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002518static u32 MT2063_CalcLO2Mult(u32 * Div,
2519 u32 * FracN,
2520 u32 f_LO,
2521 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002522{
2523 /* Calculate the whole number portion of the divider */
2524 *Div = f_LO / f_Ref;
2525
2526 /* Calculate the numerator value (round to nearest f_LO_Step) */
2527 *FracN =
2528 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2529 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2530
2531 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
2532 8191);
2533}
2534
2535/****************************************************************************
2536**
2537** Name: FindClearTuneFilter
2538**
2539** Description: Calculate the corrrect ClearTune filter to be used for
2540** a given input frequency.
2541**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002542** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002543** f_in - RF input center frequency (in Hz).
2544**
2545** Returns: ClearTune filter number (0-31)
2546**
2547** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
2548**
2549** Revision History:
2550**
2551** SCR Date Author Description
2552** -------------------------------------------------------------------------
2553** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
2554** cross-over frequency values.
2555**
2556****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002557static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002558{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002559 u32 RFBand;
2560 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002561
2562 /*
2563 ** Find RF Band setting
2564 */
2565 RFBand = 31; /* def when f_in > all */
2566 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002567 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002568 RFBand = idx;
2569 break;
2570 }
2571 }
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002572 return RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002573}
2574
2575/****************************************************************************
2576**
2577** Name: MT2063_Tune
2578**
2579** Description: Change the tuner's tuned frequency to RFin.
2580**
2581** Parameters: h - Open handle to the tuner (from MT2063_Open).
2582** f_in - RF input center frequency (in Hz).
2583**
2584** Returns: status:
2585** MT_OK - No errors
2586** MT_INV_HANDLE - Invalid tuner handle
2587** MT_UPC_UNLOCK - Upconverter PLL unlocked
2588** MT_DNC_UNLOCK - Downconverter PLL unlocked
2589** MT_COMM_ERR - Serial bus communications error
2590** MT_SPUR_CNT_MASK - Count of avoided LO spurs
2591** MT_SPUR_PRESENT - LO spur possible in output
2592** MT_FIN_RANGE - Input freq out of range
2593** MT_FOUT_RANGE - Output freq out of range
2594** MT_UPC_RANGE - Upconverter freq out of range
2595** MT_DNC_RANGE - Downconverter freq out of range
2596**
2597** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
2598**
2599** MT_ReadSub - Read data from the two-wire serial bus
2600** MT_WriteSub - Write data to the two-wire serial bus
2601** MT_Sleep - Delay execution for x milliseconds
2602** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
2603**
2604** Revision History:
2605**
2606** SCR Date Author Description
2607** -------------------------------------------------------------------------
2608** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2609** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
2610** cross-over frequency values.
2611** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2612** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2613** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2614**
2615****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002616static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002617{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002618
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002619 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002620 u32 LO1; /* 1st LO register value */
2621 u32 Num1; /* Numerator for LO1 reg. value */
2622 u32 f_IF1; /* 1st IF requested */
2623 u32 LO2; /* 2nd LO register value */
2624 u32 Num2; /* Numerator for LO2 reg. value */
2625 u32 ofLO1, ofLO2; /* last time's LO frequencies */
2626 u32 ofin, ofout; /* last time's I/O frequencies */
2627 u8 fiffc = 0x80; /* FIFF center freq from tuner */
2628 u32 fiffof; /* Offset from FIFF center freq */
2629 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
2630 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
2631 u8 val;
2632 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002633
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002634 /* Check the input and output frequency ranges */
2635 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002636 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002637
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002638 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
2639 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002640 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002641
2642 /*
2643 ** Save original LO1 and LO2 register values
2644 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002645 ofLO1 = state->AS_Data.f_LO1;
2646 ofLO2 = state->AS_Data.f_LO2;
2647 ofin = state->AS_Data.f_in;
2648 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002649
2650 /*
2651 ** Find and set RF Band setting
2652 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002653 if (state->ctfilt_sw == 1) {
2654 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
2655 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002656 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002657 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002658 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002659 val = state->reg[MT2063_REG_CTUNE_OV];
2660 RFBand = FindClearTuneFilter(state, f_in);
2661 state->reg[MT2063_REG_CTUNE_OV] =
2662 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002663 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002664 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002665 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002666 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002667 }
2668 }
2669
2670 /*
2671 ** Read the FIFF Center Frequency from the tuner
2672 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002673 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002674 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002675 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002676 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002677 &state->reg[MT2063_REG_FIFFC], 1);
2678 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002679 }
2680 /*
2681 ** Assign in the requested values
2682 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002683 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002684 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002685 state->AS_Data.f_if1_Request =
2686 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
2687 state->AS_Data.f_LO1_Step,
2688 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002689
2690 /*
2691 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
2692 ** desired LO1 frequency
2693 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002694 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002695
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002696 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002697
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002698 state->AS_Data.f_LO1 =
2699 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
2700 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002701
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002702 state->AS_Data.f_LO2 =
2703 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
2704 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002705
2706 /*
2707 ** Check for any LO spurs in the output bandwidth and adjust
2708 ** the LO settings to avoid them if needed
2709 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002710 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002711 /*
2712 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
2713 ** Recalculate the LO frequencies and the values to be placed
2714 ** in the tuning registers.
2715 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002716 state->AS_Data.f_LO1 =
2717 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
2718 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
2719 state->AS_Data.f_LO2 =
2720 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
2721 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
2722 state->AS_Data.f_LO2 =
2723 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
2724 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002725
2726 /*
2727 ** Check the upconverter and downconverter frequency ranges
2728 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002729 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
2730 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002731 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002732 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
2733 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002734 status |= MT2063_DNC_RANGE;
2735 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002736 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002737 LO2LK = 0x40;
2738
2739 /*
2740 ** If we have the same LO frequencies and we're already locked,
2741 ** then skip re-programming the LO registers.
2742 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002743 if ((ofLO1 != state->AS_Data.f_LO1)
2744 || (ofLO2 != state->AS_Data.f_LO2)
2745 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002746 (LO1LK | LO2LK))) {
2747 /*
2748 ** Calculate the FIFFOF register value
2749 **
2750 ** IF1_Actual
2751 ** FIFFOF = ------------ - 8 * FIFFC - 4992
2752 ** f_ref/64
2753 */
2754 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002755 (state->AS_Data.f_LO1 -
2756 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002757 4992;
2758 if (fiffof > 0xFF)
2759 fiffof = 0xFF;
2760
2761 /*
2762 ** Place all of the calculated values into the local tuner
2763 ** register fields.
2764 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002765 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002766 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
2767 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
2768 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002769 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002770 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
2771 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002772
2773 /*
2774 ** Now write out the computed register values
2775 ** IMPORTANT: There is a required order for writing
2776 ** (0x05 must follow all the others).
2777 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002778 status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002779 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002780 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002781 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002782 }
2783 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002784 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002785 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002786 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002787 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002788 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002789 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002790 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002791 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002792 reg[MT2063_REG_FIFF_OFFSET],
2793 1);
2794 }
2795 }
2796
2797 /*
2798 ** Check for LO's locking
2799 */
2800
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002801 if (status < 0)
2802 return status;
2803
2804 status = mt2063_lockStatus(state);
2805 if (status < 0)
2806 return status;
2807 if (!status)
2808 return -EINVAL; /* Couldn't lock */
2809
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002810 /*
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002811 * If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002812 */
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002813 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002814 }
2815
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03002816 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002817}
2818
Mauro Carvalho Chehabfad11db2011-07-21 10:35:30 -03002819unsigned int mt2063_setTune(void *h, u32 f_in, u32 bw_in,
2820 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002821{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002822 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002823 s32 pict_car = 0;
2824 s32 pict2chanb_vsb = 0;
2825 s32 pict2chanb_snd = 0;
2826 s32 pict2snd1 = 0;
2827 s32 pict2snd2 = 0;
2828 s32 ch_bw = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002829 s32 if_mid = 0;
2830 s32 rcvr_mode = 0;
2831 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002832
2833 switch (tv_type) {
2834 case MTTUNEA_PAL_B:{
2835 pict_car = 38900000;
2836 ch_bw = 8000000;
2837 pict2chanb_vsb = -1250000;
2838 pict2snd1 = 5500000;
2839 pict2snd2 = 5742000;
2840 rcvr_mode = 1;
2841 break;
2842 }
2843 case MTTUNEA_PAL_G:{
2844 pict_car = 38900000;
2845 ch_bw = 7000000;
2846 pict2chanb_vsb = -1250000;
2847 pict2snd1 = 5500000;
2848 pict2snd2 = 0;
2849 rcvr_mode = 1;
2850 break;
2851 }
2852 case MTTUNEA_PAL_I:{
2853 pict_car = 38900000;
2854 ch_bw = 8000000;
2855 pict2chanb_vsb = -1250000;
2856 pict2snd1 = 6000000;
2857 pict2snd2 = 0;
2858 rcvr_mode = 1;
2859 break;
2860 }
2861 case MTTUNEA_PAL_L:{
2862 pict_car = 38900000;
2863 ch_bw = 8000000;
2864 pict2chanb_vsb = -1250000;
2865 pict2snd1 = 6500000;
2866 pict2snd2 = 0;
2867 rcvr_mode = 1;
2868 break;
2869 }
2870 case MTTUNEA_PAL_MN:{
2871 pict_car = 38900000;
2872 ch_bw = 6000000;
2873 pict2chanb_vsb = -1250000;
2874 pict2snd1 = 4500000;
2875 pict2snd2 = 0;
2876 rcvr_mode = 1;
2877 break;
2878 }
2879 case MTTUNEA_PAL_DK:{
2880 pict_car = 38900000;
2881 ch_bw = 8000000;
2882 pict2chanb_vsb = -1250000;
2883 pict2snd1 = 6500000;
2884 pict2snd2 = 0;
2885 rcvr_mode = 1;
2886 break;
2887 }
2888 case MTTUNEA_DIGITAL:{
2889 pict_car = 36125000;
2890 ch_bw = 8000000;
2891 pict2chanb_vsb = -(ch_bw / 2);
2892 pict2snd1 = 0;
2893 pict2snd2 = 0;
2894 rcvr_mode = 2;
2895 break;
2896 }
2897 case MTTUNEA_FMRADIO:{
2898 pict_car = 38900000;
2899 ch_bw = 8000000;
2900 pict2chanb_vsb = -(ch_bw / 2);
2901 pict2snd1 = 0;
2902 pict2snd2 = 0;
2903 rcvr_mode = 4;
2904 //f_in -= 2900000;
2905 break;
2906 }
2907 case MTTUNEA_DVBC:{
2908 pict_car = 36125000;
2909 ch_bw = 8000000;
2910 pict2chanb_vsb = -(ch_bw / 2);
2911 pict2snd1 = 0;
2912 pict2snd2 = 0;
2913 rcvr_mode = MT2063_CABLE_QAM;
2914 break;
2915 }
2916 case MTTUNEA_DVBT:{
2917 pict_car = 36125000;
2918 ch_bw = bw_in; //8000000
2919 pict2chanb_vsb = -(ch_bw / 2);
2920 pict2snd1 = 0;
2921 pict2snd2 = 0;
2922 rcvr_mode = MT2063_OFFAIR_COFDM;
2923 break;
2924 }
2925 case MTTUNEA_UNKNOWN:
2926 break;
2927 default:
2928 break;
2929 }
2930
2931 pict2chanb_snd = pict2chanb_vsb - ch_bw;
2932 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
2933
2934 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
2935 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
2936 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
2937 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
2938
2939 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
2940 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
2941 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
2942
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002943 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002944}
2945
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03002946static const u8 MT2063B0_defaults[] = {
2947 /* Reg, Value */
2948 0x19, 0x05,
2949 0x1B, 0x1D,
2950 0x1C, 0x1F,
2951 0x1D, 0x0F,
2952 0x1E, 0x3F,
2953 0x1F, 0x0F,
2954 0x20, 0x3F,
2955 0x22, 0x21,
2956 0x23, 0x3F,
2957 0x24, 0x20,
2958 0x25, 0x3F,
2959 0x27, 0xEE,
2960 0x2C, 0x27, /* bit at 0x20 is cleared below */
2961 0x30, 0x03,
2962 0x2C, 0x07, /* bit at 0x20 is cleared here */
2963 0x2D, 0x87,
2964 0x2E, 0xAA,
2965 0x28, 0xE1, /* Set the FIFCrst bit here */
2966 0x28, 0xE0, /* Clear the FIFCrst bit here */
2967 0x00
2968};
2969
2970/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2971static const u8 MT2063B1_defaults[] = {
2972 /* Reg, Value */
2973 0x05, 0xF0,
2974 0x11, 0x10, /* New Enable AFCsd */
2975 0x19, 0x05,
2976 0x1A, 0x6C,
2977 0x1B, 0x24,
2978 0x1C, 0x28,
2979 0x1D, 0x8F,
2980 0x1E, 0x14,
2981 0x1F, 0x8F,
2982 0x20, 0x57,
2983 0x22, 0x21, /* New - ver 1.03 */
2984 0x23, 0x3C, /* New - ver 1.10 */
2985 0x24, 0x20, /* New - ver 1.03 */
2986 0x2C, 0x24, /* bit at 0x20 is cleared below */
2987 0x2D, 0x87, /* FIFFQ=0 */
2988 0x2F, 0xF3,
2989 0x30, 0x0C, /* New - ver 1.11 */
2990 0x31, 0x1B, /* New - ver 1.11 */
2991 0x2C, 0x04, /* bit at 0x20 is cleared here */
2992 0x28, 0xE1, /* Set the FIFCrst bit here */
2993 0x28, 0xE0, /* Clear the FIFCrst bit here */
2994 0x00
2995};
2996
2997/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2998static const u8 MT2063B3_defaults[] = {
2999 /* Reg, Value */
3000 0x05, 0xF0,
3001 0x19, 0x3D,
3002 0x2C, 0x24, /* bit at 0x20 is cleared below */
3003 0x2C, 0x04, /* bit at 0x20 is cleared here */
3004 0x28, 0xE1, /* Set the FIFCrst bit here */
3005 0x28, 0xE0, /* Clear the FIFCrst bit here */
3006 0x00
3007};
3008
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003009static int mt2063_init(struct dvb_frontend *fe)
3010{
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003011 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003012 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003013 u8 all_resets = 0xF0; /* reset/load bits */
3014 const u8 *def = NULL;
3015 u32 FCRUN;
3016 s32 maxReads;
3017 u32 fcu_osc;
3018 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003019
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003020 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003021
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003022 /* Read the Part/Rev code from the tuner */
3023 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
3024 if (status < 0)
3025 return status;
3026
3027 /* Check the part/rev code */
3028 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
3029 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
3030 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
3031 return -ENODEV; /* Wrong tuner Part/Rev code */
3032
3033 /* Check the 2nd byte of the Part/Rev code from the tuner */
3034 status = mt2063_read(state, MT2063_REG_RSVD_3B,
3035 &state->reg[MT2063_REG_RSVD_3B], 1);
3036
3037 /* b7 != 0 ==> NOT MT2063 */
3038 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
3039 return -ENODEV; /* Wrong tuner Part/Rev code */
3040
3041 /* Reset the tuner */
3042 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
3043 if (status < 0)
3044 return status;
3045
3046 /* change all of the default values that vary from the HW reset values */
3047 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
3048 switch (state->reg[MT2063_REG_PART_REV]) {
3049 case MT2063_B3:
3050 def = MT2063B3_defaults;
3051 break;
3052
3053 case MT2063_B1:
3054 def = MT2063B1_defaults;
3055 break;
3056
3057 case MT2063_B0:
3058 def = MT2063B0_defaults;
3059 break;
3060
3061 default:
3062 return -ENODEV;
3063 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003064 }
3065
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003066 while (status >= 0 && *def) {
3067 u8 reg = *def++;
3068 u8 val = *def++;
3069 status = mt2063_write(state, reg, &val, 1);
3070 }
3071 if (status < 0)
3072 return status;
3073
3074 /* Wait for FIFF location to complete. */
3075 FCRUN = 1;
3076 maxReads = 10;
3077 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3078 msleep(2);
3079 status = mt2063_read(state,
3080 MT2063_REG_XO_STATUS,
3081 &state->
3082 reg[MT2063_REG_XO_STATUS], 1);
3083 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
3084 }
3085
3086 if (FCRUN != 0 || status < 0)
3087 return -ENODEV;
3088
3089 status = mt2063_read(state,
3090 MT2063_REG_FIFFC,
3091 &state->reg[MT2063_REG_FIFFC], 1);
3092 if (status < 0)
3093 return status;
3094
3095 /* Read back all the registers from the tuner */
3096 status = mt2063_read(state,
3097 MT2063_REG_PART_REV,
3098 state->reg, MT2063_REG_END_REGS);
3099 if (status < 0)
3100 return status;
3101
3102 /* Initialize the tuner state. */
3103 state->tuner_id = state->reg[MT2063_REG_PART_REV];
3104 state->AS_Data.f_ref = MT2063_REF_FREQ;
3105 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
3106 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
3107 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
3108 state->AS_Data.f_out = 43750000UL;
3109 state->AS_Data.f_out_bw = 6750000UL;
3110 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3111 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
3112 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3113 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3114 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3115 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3116 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
3117 state->AS_Data.f_LO1 = 2181000000UL;
3118 state->AS_Data.f_LO2 = 1486249786UL;
3119 state->f_IF1_actual = state->AS_Data.f_if1_Center;
3120 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
3121 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3122 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3123 state->num_regs = MT2063_REG_END_REGS;
3124 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3125 state->ctfilt_sw = 0;
3126
3127 state->CTFiltMax[0] = 69230000;
3128 state->CTFiltMax[1] = 105770000;
3129 state->CTFiltMax[2] = 140350000;
3130 state->CTFiltMax[3] = 177110000;
3131 state->CTFiltMax[4] = 212860000;
3132 state->CTFiltMax[5] = 241130000;
3133 state->CTFiltMax[6] = 274370000;
3134 state->CTFiltMax[7] = 309820000;
3135 state->CTFiltMax[8] = 342450000;
3136 state->CTFiltMax[9] = 378870000;
3137 state->CTFiltMax[10] = 416210000;
3138 state->CTFiltMax[11] = 456500000;
3139 state->CTFiltMax[12] = 495790000;
3140 state->CTFiltMax[13] = 534530000;
3141 state->CTFiltMax[14] = 572610000;
3142 state->CTFiltMax[15] = 598970000;
3143 state->CTFiltMax[16] = 635910000;
3144 state->CTFiltMax[17] = 672130000;
3145 state->CTFiltMax[18] = 714840000;
3146 state->CTFiltMax[19] = 739660000;
3147 state->CTFiltMax[20] = 770410000;
3148 state->CTFiltMax[21] = 814660000;
3149 state->CTFiltMax[22] = 846950000;
3150 state->CTFiltMax[23] = 867820000;
3151 state->CTFiltMax[24] = 915980000;
3152 state->CTFiltMax[25] = 947450000;
3153 state->CTFiltMax[26] = 983110000;
3154 state->CTFiltMax[27] = 1021630000;
3155 state->CTFiltMax[28] = 1061870000;
3156 state->CTFiltMax[29] = 1098330000;
3157 state->CTFiltMax[30] = 1138990000;
3158
3159 /*
3160 ** Fetch the FCU osc value and use it and the fRef value to
3161 ** scale all of the Band Max values
3162 */
3163
3164 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3165 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3166 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3167 if (status < 0)
3168 return status;
3169
3170 /* Read the ClearTune filter calibration value */
3171 status = mt2063_read(state, MT2063_REG_FIFFC,
3172 &state->reg[MT2063_REG_FIFFC], 1);
3173 if (status < 0)
3174 return status;
3175
3176 fcu_osc = state->reg[MT2063_REG_FIFFC];
3177
3178 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3179 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3180 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3181 if (status < 0)
3182 return status;
3183
3184 /* Adjust each of the values in the ClearTune filter cross-over table */
3185 for (i = 0; i < 31; i++)
3186 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
3187
3188 status = MT2063_SoftwareShutdown(state, 1);
3189 if (status < 0)
3190 return status;
3191 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
3192 if (status < 0)
3193 return status;
3194
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003195 return 0;
3196}
3197
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003198static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3199{
3200 int rc = 0;
3201
3202 //get tuner lock status
3203
3204 return rc;
3205}
3206
3207static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003208 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003209{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003210 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003211
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003212 switch (param) {
3213 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003214 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003215 break;
3216 case DVBFE_TUNER_TUNERSTEP:
3217 break;
3218 case DVBFE_TUNER_IFFREQ:
3219 break;
3220 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003221 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003222 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003223 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab31e67fa2011-07-21 10:30:11 -03003224 tunstate->refclock = mt2063_lockStatus(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003225 break;
3226 default:
3227 break;
3228 }
3229
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003230 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003231}
3232
3233static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003234 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003235{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003236 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003237 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003238
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003239 switch (param) {
3240 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003241 //set frequency
3242
3243 status =
Mauro Carvalho Chehabfad11db2011-07-21 10:35:30 -03003244 mt2063_setTune(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003245 tunstate->frequency, tunstate->bandwidth,
3246 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003247
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003248 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003249 break;
3250 case DVBFE_TUNER_TUNERSTEP:
3251 break;
3252 case DVBFE_TUNER_IFFREQ:
3253 break;
3254 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003255 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003256 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003257 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003258 case DVBFE_TUNER_REFCLOCK:
3259
3260 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003261 default:
3262 break;
3263 }
3264
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003265 return (int)status;
3266}
3267
3268static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003269{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003270 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003271
3272 fe->tuner_priv = NULL;
3273 kfree(state);
3274
3275 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003276}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003277
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003278static struct dvb_tuner_ops mt2063_ops = {
3279 .info = {
3280 .name = "MT2063 Silicon Tuner",
3281 .frequency_min = 45000000,
3282 .frequency_max = 850000000,
3283 .frequency_step = 0,
3284 },
3285
3286 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003287 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003288 .get_status = mt2063_get_status,
3289 .get_state = mt2063_get_state,
3290 .set_state = mt2063_set_state,
3291 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003292};
3293
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003294struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3295 struct mt2063_config *config,
3296 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003297{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003298 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003299
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003300 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003301 if (state == NULL)
3302 goto error;
3303
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003304 state->config = config;
3305 state->i2c = i2c;
3306 state->frontend = fe;
3307 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003308 fe->tuner_priv = state;
3309 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003310
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003311 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003312 return fe;
3313
3314error:
3315 kfree(state);
3316 return NULL;
3317}
Mauro Carvalho Chehab3d497002011-07-21 11:00:59 -03003318EXPORT_SYMBOL_GPL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003319
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003320MODULE_PARM_DESC(verbose, "Set Verbosity level");
3321
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003322MODULE_AUTHOR("Henry");
3323MODULE_DESCRIPTION("MT2063 Silicon tuner");
3324MODULE_LICENSE("GPL");