blob: 86620073c17479d77ac27c985dd5a7c5d48963b1 [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 Chehab6d3d7482011-07-20 22:21:26 -030011/* Internal structures and types */
12
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030013/* FIXME: Those two error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030014/* Error: Upconverter PLL is not locked */
15#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030016/* Error: Downconverter PLL is not locked */
17#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030018
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030019/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030020#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030021
22/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
23#define MT2063_SPUR_CNT_MASK (0x001f0000)
24#define MT2063_SPUR_SHIFT (16)
25
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
27#define MT2063_UPC_RANGE (0x04000000)
28
29/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
30#define MT2063_DNC_RANGE (0x08000000)
31
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030032/*
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030033 * Data Types
34 */
35
36/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030037 * Constant defining the version of the following structure
38 * and therefore the API for this code.
39 *
40 * When compiling the tuner driver, the preprocessor will
41 * check against this version number to make sure that
42 * it matches the version that the tuner driver knows about.
43 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030044
45/* DECT Frequency Avoidance */
46#define MT2063_DECT_AVOID_US_FREQS 0x00000001
47
48#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
49
50#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
51
52#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
53
54enum MT2063_DECT_Avoid_Type {
55 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
56 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
57 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
58 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
59};
60
61#define MT2063_MAX_ZONES 48
62
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030063struct MT2063_ExclZone_t {
64 u32 min_;
65 u32 max_;
66 struct MT2063_ExclZone_t *next_;
67};
68
69/*
70 * Structure of data needed for Spur Avoidance
71 */
72struct MT2063_AvoidSpursData_t {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030073 u32 f_ref;
74 u32 f_in;
75 u32 f_LO1;
76 u32 f_if1_Center;
77 u32 f_if1_Request;
78 u32 f_if1_bw;
79 u32 f_LO2;
80 u32 f_out;
81 u32 f_out_bw;
82 u32 f_LO1_Step;
83 u32 f_LO2_Step;
84 u32 f_LO1_FracN_Avoid;
85 u32 f_LO2_FracN_Avoid;
86 u32 f_zif_bw;
87 u32 f_min_LO_Separation;
88 u32 maxH1;
89 u32 maxH2;
90 enum MT2063_DECT_Avoid_Type avoidDECT;
91 u32 bSpurPresent;
92 u32 bSpurAvoided;
93 u32 nSpursFound;
94 u32 nZones;
95 struct MT2063_ExclZone_t *freeZones;
96 struct MT2063_ExclZone_t *usedZones;
97 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
98};
99
100/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300101 * Parameter for function MT2063_SetPowerMask that specifies the power down
102 * of various sections of the MT2063.
103 */
104enum MT2063_Mask_Bits {
105 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
106 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
107 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
108 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
109 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
110 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
111 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
112 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
113 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
114 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
115 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
116 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
117 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
118 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
119 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
120};
121
122/*
123 * Parameter for function MT2063_GetParam & MT2063_SetParam that
124 * specifies the tuning algorithm parameter to be read/written.
125 */
126enum MT2063_Param {
127 /* tuner address set by MT2063_Open() */
128 MT2063_IC_ADDR,
129
130 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
131 MT2063_MAX_OPEN,
132
133 /* current number of open MT2063 tuners set by MT2063_Open() */
134 MT2063_NUM_OPEN,
135
136 /* crystal frequency (default: 16000000 Hz) */
137 MT2063_SRO_FREQ,
138
139 /* min tuning step size (default: 50000 Hz) */
140 MT2063_STEPSIZE,
141
142 /* input center frequency set by MT2063_Tune() */
143 MT2063_INPUT_FREQ,
144
145 /* LO1 Frequency set by MT2063_Tune() */
146 MT2063_LO1_FREQ,
147
148 /* LO1 minimum step size (default: 250000 Hz) */
149 MT2063_LO1_STEPSIZE,
150
151 /* LO1 FracN keep-out region (default: 999999 Hz) */
152 MT2063_LO1_FRACN_AVOID_PARAM,
153
154 /* Current 1st IF in use set by MT2063_Tune() */
155 MT2063_IF1_ACTUAL,
156
157 /* Requested 1st IF set by MT2063_Tune() */
158 MT2063_IF1_REQUEST,
159
160 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
161 MT2063_IF1_CENTER,
162
163 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
164 MT2063_IF1_BW,
165
166 /* zero-IF bandwidth (default: 2000000 Hz) */
167 MT2063_ZIF_BW,
168
169 /* LO2 Frequency set by MT2063_Tune() */
170 MT2063_LO2_FREQ,
171
172 /* LO2 minimum step size (default: 50000 Hz) */
173 MT2063_LO2_STEPSIZE,
174
175 /* LO2 FracN keep-out region (default: 374999 Hz) */
176 MT2063_LO2_FRACN_AVOID,
177
178 /* output center frequency set by MT2063_Tune() */
179 MT2063_OUTPUT_FREQ,
180
181 /* output bandwidth set by MT2063_Tune() */
182 MT2063_OUTPUT_BW,
183
184 /* min inter-tuner LO separation (default: 1000000 Hz) */
185 MT2063_LO_SEPARATION,
186
187 /* ID of avoid-spurs algorithm in use compile-time constant */
188 MT2063_AS_ALG,
189
190 /* max # of intra-tuner harmonics (default: 15) */
191 MT2063_MAX_HARM1,
192
193 /* max # of inter-tuner harmonics (default: 7) */
194 MT2063_MAX_HARM2,
195
196 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
197 MT2063_EXCL_ZONES,
198
199 /* # of spurs found/avoided set by MT2063_Tune() */
200 MT2063_NUM_SPURS,
201
202 /* >0 spurs avoided set by MT2063_Tune() */
203 MT2063_SPUR_AVOIDED,
204
205 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
206 MT2063_SPUR_PRESENT,
207
208 /* Receiver Mode for some parameters. 1 is DVB-T */
209 MT2063_RCVR_MODE,
210
211 /* directly set LNA attenuation, parameter is value to set */
212 MT2063_ACLNA,
213
214 /* maximum LNA attenuation, parameter is value to set */
215 MT2063_ACLNA_MAX,
216
217 /* directly set ATN attenuation. Paremeter is value to set. */
218 MT2063_ACRF,
219
220 /* maxium ATN attenuation. Paremeter is value to set. */
221 MT2063_ACRF_MAX,
222
223 /* directly set FIF attenuation. Paremeter is value to set. */
224 MT2063_ACFIF,
225
226 /* maxium FIF attenuation. Paremeter is value to set. */
227 MT2063_ACFIF_MAX,
228
229 /* LNA Rin */
230 MT2063_LNA_RIN,
231
232 /* Power Detector LNA level target */
233 MT2063_LNA_TGT,
234
235 /* Power Detector 1 level */
236 MT2063_PD1,
237
238 /* Power Detector 1 level target */
239 MT2063_PD1_TGT,
240
241 /* Power Detector 2 level */
242 MT2063_PD2,
243
244 /* Power Detector 2 level target */
245 MT2063_PD2_TGT,
246
247 /* Selects, which DNC is activ */
248 MT2063_DNC_OUTPUT_ENABLE,
249
250 /* VGA gain code */
251 MT2063_VGAGC,
252
253 /* VGA bias current */
254 MT2063_VGAOI,
255
256 /* TAGC, determins the speed of the AGC */
257 MT2063_TAGC,
258
259 /* AMP gain code */
260 MT2063_AMPGC,
261
262 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
263 MT2063_AVOID_DECT,
264
265 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
266 MT2063_CTFILT_SW,
267
268 MT2063_EOP /* last entry in enumerated list */
269};
270
271/*
272 * Parameter for selecting tuner mode
273 */
274enum MT2063_RCVR_MODES {
275 MT2063_CABLE_QAM = 0, /* Digital cable */
276 MT2063_CABLE_ANALOG, /* Analog cable */
277 MT2063_OFFAIR_COFDM, /* Digital offair */
278 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
279 MT2063_OFFAIR_ANALOG, /* Analog offair */
280 MT2063_OFFAIR_8VSB, /* Analog offair */
281 MT2063_NUM_RCVR_MODES
282};
283
284/*
285 * Possible values for MT2063_DNC_OUTPUT
286 */
287enum MT2063_DNC_Output_Enable {
288 MT2063_DNC_NONE = 0,
289 MT2063_DNC_1,
290 MT2063_DNC_2,
291 MT2063_DNC_BOTH
292};
293
294/*
295** Two-wire serial bus subaddresses of the tuner registers.
296** Also known as the tuner's register addresses.
297*/
298enum MT2063_Register_Offsets {
299 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
300 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
301 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
302 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
303 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
304 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
305 MT2063_REG_RSVD_06, /* 0x06: Reserved */
306 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
307 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
308 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
309 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
310 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
311 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
312 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
313 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
314 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
315 MT2063_REG_RSVD_10, /* 0x10: Reserved */
316 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
317 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
318 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
319 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
320 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
321 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
322 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
323 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
324 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
325 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
326 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
327 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
328 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
329 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
330 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
331 MT2063_REG_RSVD_20, /* 0x20: Reserved */
332 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
333 MT2063_REG_RSVD_22, /* 0x22: Reserved */
334 MT2063_REG_RSVD_23, /* 0x23: Reserved */
335 MT2063_REG_RSVD_24, /* 0x24: Reserved */
336 MT2063_REG_RSVD_25, /* 0x25: Reserved */
337 MT2063_REG_RSVD_26, /* 0x26: Reserved */
338 MT2063_REG_RSVD_27, /* 0x27: Reserved */
339 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
340 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
341 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
342 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
343 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
344 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
345 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
346 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
347 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
348 MT2063_REG_RSVD_31, /* 0x31: Reserved */
349 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
350 MT2063_REG_RSVD_33, /* 0x33: Reserved */
351 MT2063_REG_RSVD_34, /* 0x34: Reserved */
352 MT2063_REG_RSVD_35, /* 0x35: Reserved */
353 MT2063_REG_RSVD_36, /* 0x36: Reserved */
354 MT2063_REG_RSVD_37, /* 0x37: Reserved */
355 MT2063_REG_RSVD_38, /* 0x38: Reserved */
356 MT2063_REG_RSVD_39, /* 0x39: Reserved */
357 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
358 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
359 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
360 MT2063_REG_END_REGS
361};
362
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300363enum MTTune_atv_standard {
364 MTTUNEA_UNKNOWN = 0,
365 MTTUNEA_PAL_B,
366 MTTUNEA_PAL_G,
367 MTTUNEA_PAL_I,
368 MTTUNEA_PAL_L,
369 MTTUNEA_PAL_MN,
370 MTTUNEA_PAL_DK,
371 MTTUNEA_DIGITAL,
372 MTTUNEA_FMRADIO,
373 MTTUNEA_DVBC,
374 MTTUNEA_DVBT
375};
376
377
378struct mt2063_state {
379 struct i2c_adapter *i2c;
380
381 const struct mt2063_config *config;
382 struct dvb_tuner_ops ops;
383 struct dvb_frontend *frontend;
384 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300385
386 enum MTTune_atv_standard tv_type;
387 u32 frequency;
388 u32 srate;
389 u32 bandwidth;
390 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300391
392 u32 tuner_id;
393 struct MT2063_AvoidSpursData_t AS_Data;
394 u32 f_IF1_actual;
395 u32 rcvr_mode;
396 u32 ctfilt_sw;
397 u32 CTFiltMax[31];
398 u32 num_regs;
399 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300400};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300401
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300402/* Prototypes */
403static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
404 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300405static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
406static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
407static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
408static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300409 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300410static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown);
411static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits);
412
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300413
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300414/*****************/
415/* From drivers/media/common/tuners/mt2063_cfg.h */
416
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300417unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300418 u32 bw_in,
419 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300420{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300421 struct dvb_frontend_ops *frontend_ops = NULL;
422 struct dvb_tuner_ops *tuner_ops = NULL;
423 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300424 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300425 int err = 0;
426
427 t_state.frequency = f_in;
428 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300429 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300430 if (&fe->ops)
431 frontend_ops = &fe->ops;
432 if (&frontend_ops->tuner_ops)
433 tuner_ops = &frontend_ops->tuner_ops;
434 if (tuner_ops->set_state) {
435 if ((err =
436 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
437 &t_state)) < 0) {
438 printk("%s: Invalid parameter\n", __func__);
439 return err;
440 }
441 }
442
443 return err;
444}
445
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300446unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300447{
448 struct dvb_frontend_ops *frontend_ops = &fe->ops;
449 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
450 struct tuner_state t_state;
451 int err = 0;
452
453 if (&fe->ops)
454 frontend_ops = &fe->ops;
455 if (&frontend_ops->tuner_ops)
456 tuner_ops = &frontend_ops->tuner_ops;
457 if (tuner_ops->get_state) {
458 if ((err =
459 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
460 &t_state)) < 0) {
461 printk("%s: Invalid parameter\n", __func__);
462 return err;
463 }
464 }
465 return err;
466}
467
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300468
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300469unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300470{
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300471 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300472 struct dvb_frontend_ops *frontend_ops = &fe->ops;
473 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300474 int err = 0;
475
476 if (&fe->ops)
477 frontend_ops = &fe->ops;
478 if (&frontend_ops->tuner_ops)
479 tuner_ops = &frontend_ops->tuner_ops;
480 if (tuner_ops->set_state) {
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300481 err = MT2063_SoftwareShutdown(state, 1);
482 if (err < 0) {
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300483 printk("%s: Invalid parameter\n", __func__);
484 return err;
485 }
486 }
487
488 return err;
489}
490
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300491unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300492{
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300493 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300494 struct dvb_frontend_ops *frontend_ops = &fe->ops;
495 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300496 int err = 0;
497
498 if (&fe->ops)
499 frontend_ops = &fe->ops;
500 if (&frontend_ops->tuner_ops)
501 tuner_ops = &frontend_ops->tuner_ops;
502 if (tuner_ops->set_state) {
Mauro Carvalho Chehab8c64f932011-07-21 03:29:06 -0300503 err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
504 if (err < 0) {
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300505 printk("%s: Invalid parameter\n", __func__);
506 return err;
507 }
508 }
509
510 return err;
511}
512
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300513/*
514 * mt2063_write - Write data into the I2C bus
515 */
516static u32 mt2063_write(struct mt2063_state *state,
517 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300518{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300519 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300520 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300521 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300522 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300523 .addr = state->config->tuner_address,
524 .flags = 0,
525 .buf = buf,
526 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300527 };
528
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300529 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300530 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300531
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300532 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300533 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300534 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300535
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300536 if (ret < 0)
537 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300538
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300539 return ret;
540}
541
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300542/*
543 * mt2063_read - Read data from the I2C bus
544 */
545static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300546 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300547{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300548 u32 status = 0; /* Status to be returned */
549 struct dvb_frontend *fe = state->frontend;
550 u32 i = 0;
551
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300552 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300553
554 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300555 int ret;
556 u8 b0[] = { subAddress + i };
557 struct i2c_msg msg[] = {
558 {
559 .addr = state->config->tuner_address,
560 .flags = I2C_M_RD,
561 .buf = b0,
562 .len = 1
563 }, {
564 .addr = state->config->tuner_address,
565 .flags = I2C_M_RD,
566 .buf = pData + 1,
567 .len = 1
568 }
569 };
570
571 ret = i2c_transfer(state->i2c, msg, 2);
572 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300573 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300574 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300575 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300576 return (status);
577}
578
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300579/*
580 * FIXME: Is this really needed?
581 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300582static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300583{
584 /*
585 ** ToDo: Add code here to implement a OS blocking
586 ** for a period of "nMinDelayTime" milliseconds.
587 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300588 msleep(10);
589
590 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300591}
592
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300593/*
594 * Microtune spur avoidance
595 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300596
597/* Implement ceiling, floor functions. */
598#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300599#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300600
601struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300602 s32 min_;
603 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300604};
605
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300606/*
607** Reset all exclusion zones.
608** Add zones to protect the PLL FracN regions near zero
609**
610** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
611** frequencies into MT_ResetExclZones().
612*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300613static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300614{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300615 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300616
617 pAS_Info->nZones = 0; /* this clears the used list */
618 pAS_Info->usedZones = NULL; /* reset ptr */
619 pAS_Info->freeZones = NULL; /* reset ptr */
620
621 center =
622 pAS_Info->f_ref *
623 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
624 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
625 while (center <
626 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
627 pAS_Info->f_LO1_FracN_Avoid) {
628 /* Exclude LO1 FracN */
629 MT2063_AddExclZone(pAS_Info,
630 center - pAS_Info->f_LO1_FracN_Avoid,
631 center - 1);
632 MT2063_AddExclZone(pAS_Info, center + 1,
633 center + pAS_Info->f_LO1_FracN_Avoid);
634 center += pAS_Info->f_ref;
635 }
636
637 center =
638 pAS_Info->f_ref *
639 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
640 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
641 while (center <
642 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
643 pAS_Info->f_LO2_FracN_Avoid) {
644 /* Exclude LO2 FracN */
645 MT2063_AddExclZone(pAS_Info,
646 center - pAS_Info->f_LO2_FracN_Avoid,
647 center - 1);
648 MT2063_AddExclZone(pAS_Info, center + 1,
649 center + pAS_Info->f_LO2_FracN_Avoid);
650 center += pAS_Info->f_ref;
651 }
652
653 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
654 /* Exclude LO1 values that conflict with DECT channels */
655 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
656 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
657 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
658 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
659 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
660 }
661
662 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
663 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
664 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
665 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
666 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
667 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
668 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
669 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
670 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
671 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
672 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
673 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300674}
675
676static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
677 *pAS_Info,
678 struct MT2063_ExclZone_t *pPrevNode)
679{
680 struct MT2063_ExclZone_t *pNode;
681 /* Check for a node in the free list */
682 if (pAS_Info->freeZones != NULL) {
683 /* Use one from the free list */
684 pNode = pAS_Info->freeZones;
685 pAS_Info->freeZones = pNode->next_;
686 } else {
687 /* Grab a node from the array */
688 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
689 }
690
691 if (pPrevNode != NULL) {
692 pNode->next_ = pPrevNode->next_;
693 pPrevNode->next_ = pNode;
694 } else { /* insert at the beginning of the list */
695
696 pNode->next_ = pAS_Info->usedZones;
697 pAS_Info->usedZones = pNode;
698 }
699
700 pAS_Info->nZones++;
701 return pNode;
702}
703
704static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
705 *pAS_Info,
706 struct MT2063_ExclZone_t *pPrevNode,
707 struct MT2063_ExclZone_t
708 *pNodeToRemove)
709{
710 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
711
712 /* Make previous node point to the subsequent node */
713 if (pPrevNode != NULL)
714 pPrevNode->next_ = pNext;
715
716 /* Add pNodeToRemove to the beginning of the freeZones */
717 pNodeToRemove->next_ = pAS_Info->freeZones;
718 pAS_Info->freeZones = pNodeToRemove;
719
720 /* Decrement node count */
721 pAS_Info->nZones--;
722
723 return pNext;
724}
725
726/*****************************************************************************
727**
728** Name: MT_AddExclZone
729**
730** Description: Add (and merge) an exclusion zone into the list.
731** If the range (f_min, f_max) is totally outside the
732** 1st IF BW, ignore the entry.
733** If the range (f_min, f_max) is negative, ignore the entry.
734**
735** Revision History:
736**
737** SCR Date Author Description
738** -------------------------------------------------------------------------
739** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
740** (f_min, f_max) < 0, ignore the entry.
741**
742*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300743static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300744 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300745{
746 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
747 struct MT2063_ExclZone_t *pPrev = NULL;
748 struct MT2063_ExclZone_t *pNext = NULL;
749
750 /* Check to see if this overlaps the 1st IF filter */
751 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
752 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
753 && (f_min < f_max)) {
754 /*
755 ** 1 2 3 4 5 6
756 **
757 ** New entry: |---| |--| |--| |-| |---| |--|
758 ** or or or or or
759 ** Existing: |--| |--| |--| |---| |-| |--|
760 */
761
762 /* Check for our place in the list */
763 while ((pNode != NULL) && (pNode->max_ < f_min)) {
764 pPrev = pNode;
765 pNode = pNode->next_;
766 }
767
768 if ((pNode != NULL) && (pNode->min_ < f_max)) {
769 /* Combine me with pNode */
770 if (f_min < pNode->min_)
771 pNode->min_ = f_min;
772 if (f_max > pNode->max_)
773 pNode->max_ = f_max;
774 } else {
775 pNode = InsertNode(pAS_Info, pPrev);
776 pNode->min_ = f_min;
777 pNode->max_ = f_max;
778 }
779
780 /* Look for merging possibilities */
781 pNext = pNode->next_;
782 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
783 if (pNext->max_ > pNode->max_)
784 pNode->max_ = pNext->max_;
785 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
786 }
787 }
788}
789
790/*****************************************************************************
791**
792** Name: MT_ChooseFirstIF
793**
794** Description: Choose the best available 1st IF
795** If f_Desired is not excluded, choose that first.
796** Otherwise, return the value closest to f_Center that is
797** not excluded
798**
799** Revision History:
800**
801** SCR Date Author Description
802** -------------------------------------------------------------------------
803** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
804** tuner DLL.
805** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
806** Added logic to force f_Center within 1/2 f_Step.
807**
808*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300809static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300810{
811 /*
812 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
813 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
814 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
815 ** However, the sum must be.
816 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300817 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300818 pAS_Info->f_LO1_Step *
819 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
820 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
821 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300822 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300823 (pAS_Info->f_LO1_Step >
824 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
825 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300826 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300827
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300828 s32 i;
829 s32 j = 0;
830 u32 bDesiredExcluded = 0;
831 u32 bZeroExcluded = 0;
832 s32 tmpMin, tmpMax;
833 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300834 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
835 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
836
837 if (pAS_Info->nZones == 0)
838 return f_Desired;
839
840 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
841 if (pAS_Info->f_if1_Center > f_Desired)
842 f_Center =
843 f_Desired +
844 f_Step *
845 ((pAS_Info->f_if1_Center - f_Desired +
846 f_Step / 2) / f_Step);
847 else
848 f_Center =
849 f_Desired -
850 f_Step *
851 ((f_Desired - pAS_Info->f_if1_Center +
852 f_Step / 2) / f_Step);
853
854 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300855 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300856 // return 0;
857
858 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
859 while (pNode != NULL) {
860 /* floor function */
861 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300862 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300863
864 /* ceil function */
865 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300866 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300867
868 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
869 bDesiredExcluded = 1;
870
871 if ((tmpMin < 0) && (tmpMax > 0))
872 bZeroExcluded = 1;
873
874 /* See if this zone overlaps the previous */
875 if ((j > 0) && (tmpMin < zones[j - 1].max_))
876 zones[j - 1].max_ = tmpMax;
877 else {
878 /* Add new zone */
879 //assert(j<MT2063_MAX_ZONES);
880 //if (j>=MT2063_MAX_ZONES)
881 //break;
882
883 zones[j].min_ = tmpMin;
884 zones[j].max_ = tmpMax;
885 j++;
886 }
887 pNode = pNode->next_;
888 }
889
890 /*
891 ** If the desired is okay, return with it
892 */
893 if (bDesiredExcluded == 0)
894 return f_Desired;
895
896 /*
897 ** If the desired is excluded and the center is okay, return with it
898 */
899 if (bZeroExcluded == 0)
900 return f_Center;
901
902 /* Find the value closest to 0 (f_Center) */
903 bestDiff = zones[0].min_;
904 for (i = 0; i < j; i++) {
905 if (abs(zones[i].min_) < abs(bestDiff))
906 bestDiff = zones[i].min_;
907 if (abs(zones[i].max_) < abs(bestDiff))
908 bestDiff = zones[i].max_;
909 }
910
911 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300912 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300913
914 return f_Center + (bestDiff * f_Step);
915}
916
917/****************************************************************************
918**
919** Name: gcd
920**
921** Description: Uses Euclid's algorithm
922**
923** Parameters: u, v - unsigned values whose GCD is desired.
924**
925** Global: None
926**
927** Returns: greatest common divisor of u and v, if either value
928** is 0, the other value is returned as the result.
929**
930** Dependencies: None.
931**
932** Revision History:
933**
934** SCR Date Author Description
935** -------------------------------------------------------------------------
936** N/A 06-01-2004 JWS Original
937** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
938** unsigned numbers.
939**
940****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300941static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300942{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300943 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300944
945 while (v != 0) {
946 r = u % v;
947 u = v;
948 v = r;
949 }
950
951 return u;
952}
953
954/****************************************************************************
955**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300956** Name: IsSpurInBand
957**
958** Description: Checks to see if a spur will be present within the IF's
959** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
960**
961** ma mb mc md
962** <--+-+-+-------------------+-------------------+-+-+-->
963** | ^ 0 ^ |
964** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
965** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
966**
967** Note that some equations are doubled to prevent round-off
968** problems when calculating fIFBW/2
969**
970** Parameters: pAS_Info - Avoid Spurs information block
971** fm - If spur, amount f_IF1 has to move negative
972** fp - If spur, amount f_IF1 has to move positive
973**
974** Global: None
975**
976** Returns: 1 if an LO spur would be present, otherwise 0.
977**
978** Dependencies: None.
979**
980** Revision History:
981**
982** SCR Date Author Description
983** -------------------------------------------------------------------------
984** N/A 11-28-2002 DAD Implemented algorithm from applied patent
985**
986****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300987static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
988 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300989{
990 /*
991 ** Calculate LO frequency settings.
992 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300993 u32 n, n0;
994 const u32 f_LO1 = pAS_Info->f_LO1;
995 const u32 f_LO2 = pAS_Info->f_LO2;
996 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
997 const u32 c = d - pAS_Info->f_out_bw;
998 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -0300999 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001000 s32 f_nsLO1, f_nsLO2;
1001 s32 f_Spur;
1002 u32 ma, mb, mc, md, me, mf;
1003 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001004 *fm = 0;
1005
1006 /*
1007 ** For each edge (d, c & f), calculate a scale, based on the gcd
1008 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1009 ** gcd-based scale factor or f_Scale.
1010 */
1011 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -03001012 gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001013 hgds = gd_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -03001014 gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001015 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabfd1126c2011-07-21 03:30:57 -03001016 gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001017 hgfs = gf_Scale / 2;
1018
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001019 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001020
1021 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1022 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1023 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1024 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1025
1026 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1027 if (md >= pAS_Info->maxH1)
1028 break;
1029
1030 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1031 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1032
1033 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1034 if (md == ma)
1035 continue;
1036
1037 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1038 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1039 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001040 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1041 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001042 f_Spur =
1043 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1044 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1045
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001046 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1047 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001048 return 1;
1049 }
1050
1051 /* Location of Zero-IF-spur to be checked */
1052 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1053 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1054 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1055 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1056 if (me != mf) {
1057 f_nsLO1 = n * (f_LO1 / gf_Scale);
1058 f_nsLO2 = me * (f_LO2 / gf_Scale);
1059 f_Spur =
1060 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1061 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1062
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001063 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1064 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001065 return 1;
1066 }
1067
1068 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1069 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1070 if (ma != mb) {
1071 f_nsLO1 = n * (f_LO1 / gc_Scale);
1072 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1073 f_Spur =
1074 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1075 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1076
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001077 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1078 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001079 return 1;
1080 }
1081 }
1082
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001083 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001084 return 0;
1085}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001086
1087/*****************************************************************************
1088**
1089** Name: MT_AvoidSpurs
1090**
1091** Description: Main entry point to avoid spurs.
1092** Checks for existing spurs in present LO1, LO2 freqs
1093** and if present, chooses spur-free LO1, LO2 combination
1094** that tunes the same input/output frequencies.
1095**
1096** Revision History:
1097**
1098** SCR Date Author Description
1099** -------------------------------------------------------------------------
1100** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1101**
1102*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001103static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001104{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001105 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001106 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001107 pAS_Info->bSpurAvoided = 0;
1108 pAS_Info->nSpursFound = 0;
1109
1110 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001111 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001112
1113 /*
1114 ** Avoid LO Generated Spurs
1115 **
1116 ** Make sure that have no LO-related spurs within the IF output
1117 ** bandwidth.
1118 **
1119 ** If there is an LO spur in this band, start at the current IF1 frequency
1120 ** and work out until we find a spur-free frequency or run up against the
1121 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1122 ** will be unchanged if a spur-free setting is not found.
1123 */
1124 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1125 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001126 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1127 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1128 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1129 u32 delta_IF1;
1130 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001131
1132 /*
1133 ** Spur was found, attempt to find a spur-free 1st IF
1134 */
1135 do {
1136 pAS_Info->nSpursFound++;
1137
1138 /* Raise f_IF1_upper, if needed */
1139 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1140
1141 /* Choose next IF1 that is closest to f_IF1_CENTER */
1142 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1143
1144 if (new_IF1 > zfIF1) {
1145 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1146 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1147 } else {
1148 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1149 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1150 }
1151 zfIF1 = new_IF1;
1152
1153 if (zfIF1 > pAS_Info->f_if1_Center)
1154 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1155 else
1156 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1157 }
1158 /*
1159 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1160 ** and there is a spur in the band (again)
1161 */
1162 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1163 pAS_Info->f_if1_bw)
1164 && (pAS_Info->bSpurPresent =
1165 IsSpurInBand(pAS_Info, &fm, &fp)));
1166
1167 /*
1168 ** Use the LO-spur free values found. If the search went all the way to
1169 ** the 1st IF band edge and always found spurs, just leave the original
1170 ** choice. It's as "good" as any other.
1171 */
1172 if (pAS_Info->bSpurPresent == 1) {
1173 status |= MT2063_SPUR_PRESENT_ERR;
1174 pAS_Info->f_LO1 = zfLO1;
1175 pAS_Info->f_LO2 = zfLO2;
1176 } else
1177 pAS_Info->bSpurAvoided = 1;
1178 }
1179
1180 status |=
1181 ((pAS_Info->
1182 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1183
1184 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001185}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001186
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001187//end of mt2063_spuravoid.c
1188//=================================================================
1189//#################################################################
1190//=================================================================
1191
1192/*
1193** The expected version of MT_AvoidSpursData_t
1194** If the version is different, an updated file is needed from Microtune
1195*/
1196/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001197
1198typedef enum {
1199 MT2063_SET_ATTEN,
1200 MT2063_INCR_ATTEN,
1201 MT2063_DECR_ATTEN
1202} MT2063_ATTEN_CNTL_MODE;
1203
1204//#define TUNER_MT2063_OPTIMIZATION
1205/*
1206** Constants used by the tuning algorithm
1207*/
1208#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1209#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1210#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1211#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1212#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1213#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1214#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1215#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1216#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1217#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1218#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1219#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1220#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1221#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1222#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1223#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1224#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1225#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1226
1227/*
1228** Define the supported Part/Rev codes for the MT2063
1229*/
1230#define MT2063_B0 (0x9B)
1231#define MT2063_B1 (0x9C)
1232#define MT2063_B2 (0x9D)
1233#define MT2063_B3 (0x9E)
1234
1235/*
1236** The number of Tuner Registers
1237*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001238static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001239
1240#define USE_GLOBAL_TUNER 0
1241
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001242static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001243static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001244
1245/*
1246** Constants for setting receiver modes.
1247** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1248** (DNC1GC & DNC2GC are the values, which are used, when the specific
1249** DNC Output is selected, the other is always off)
1250**
1251** If PAL-L or L' is received, set:
1252** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1253**
1254** --------------+----------------------------------------------
1255** Mode 0 : | MT2063_CABLE_QAM
1256** Mode 1 : | MT2063_CABLE_ANALOG
1257** Mode 2 : | MT2063_OFFAIR_COFDM
1258** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1259** Mode 4 : | MT2063_OFFAIR_ANALOG
1260** Mode 5 : | MT2063_OFFAIR_8VSB
1261** --------------+----+----+----+----+-----+-----+--------------
1262** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1263** --------------+----+----+----+----+-----+-----+
1264**
1265**
1266*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001267static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1268static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1269static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1270static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1271static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1272static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1273static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1274static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1275static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1276static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1277static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1278static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1279static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1280static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001281
1282/*
1283** Local Function Prototypes - not available for external access.
1284*/
1285
1286/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001287static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1288 u32 f_LO_Step, u32 f_Ref);
1289static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1290 u32 f_LO_Step, u32 f_Ref);
1291static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1292 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001293
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001294/****************************************************************************
1295**
1296** Name: MT2063_GetLocked
1297**
1298** Description: Checks to see if LO1 and LO2 are locked.
1299**
1300** Parameters: h - Open handle to the tuner (from MT2063_Open).
1301**
1302** Returns: status:
1303** MT_OK - No errors
1304** MT_UPC_UNLOCK - Upconverter PLL unlocked
1305** MT_DNC_UNLOCK - Downconverter PLL unlocked
1306** MT_COMM_ERR - Serial bus communications error
1307** MT_INV_HANDLE - Invalid tuner handle
1308**
1309** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1310** MT_Sleep - Delay execution for x milliseconds
1311**
1312** Revision History:
1313**
1314** SCR Date Author Description
1315** -------------------------------------------------------------------------
1316** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1317**
1318****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001319static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001320{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001321 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1322 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1323 const u32 nMaxLoops = nMaxWait / nPollRate;
1324 const u8 LO1LK = 0x80;
1325 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001326 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001327 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001328
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001329 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001330 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001331 LO2LK = 0x40;
1332
1333 do {
1334 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001335 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001336 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001337 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001338
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001339 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001340 return (status);
1341
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001342 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001343 (LO1LK | LO2LK)) {
1344 return (status);
1345 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001346 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001347 }
1348 while (++nDelays < nMaxLoops);
1349
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001350 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001351 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001352 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001353 status |= MT2063_DNC_UNLOCK;
1354
1355 return (status);
1356}
1357
1358/****************************************************************************
1359**
1360** Name: MT2063_GetParam
1361**
1362** Description: Gets a tuning algorithm parameter.
1363**
1364** This function provides access to the internals of the
1365** tuning algorithm - mostly for testing purposes.
1366**
1367** Parameters: h - Tuner handle (returned by MT2063_Open)
1368** param - Tuning algorithm parameter
1369** (see enum MT2063_Param)
1370** pValue - ptr to returned value
1371**
1372** param Description
1373** ---------------------- --------------------------------
1374** MT2063_IC_ADDR Serial Bus address of this tuner
1375** MT2063_MAX_OPEN Max # of MT2063's allowed open
1376** MT2063_NUM_OPEN # of MT2063's open
1377** MT2063_SRO_FREQ crystal frequency
1378** MT2063_STEPSIZE minimum tuning step size
1379** MT2063_INPUT_FREQ input center frequency
1380** MT2063_LO1_FREQ LO1 Frequency
1381** MT2063_LO1_STEPSIZE LO1 minimum step size
1382** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1383** MT2063_IF1_ACTUAL Current 1st IF in use
1384** MT2063_IF1_REQUEST Requested 1st IF
1385** MT2063_IF1_CENTER Center of 1st IF SAW filter
1386** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1387** MT2063_ZIF_BW zero-IF bandwidth
1388** MT2063_LO2_FREQ LO2 Frequency
1389** MT2063_LO2_STEPSIZE LO2 minimum step size
1390** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1391** MT2063_OUTPUT_FREQ output center frequency
1392** MT2063_OUTPUT_BW output bandwidth
1393** MT2063_LO_SEPARATION min inter-tuner LO separation
1394** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1395** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1396** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1397** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1398** MT2063_NUM_SPURS # of spurs found/avoided
1399** MT2063_SPUR_AVOIDED >0 spurs avoided
1400** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1401** MT2063_RCVR_MODE Predefined modes.
1402** MT2063_ACLNA LNA attenuator gain code
1403** MT2063_ACRF RF attenuator gain code
1404** MT2063_ACFIF FIF attenuator gain code
1405** MT2063_ACLNA_MAX LNA attenuator limit
1406** MT2063_ACRF_MAX RF attenuator limit
1407** MT2063_ACFIF_MAX FIF attenuator limit
1408** MT2063_PD1 Actual value of PD1
1409** MT2063_PD2 Actual value of PD2
1410** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1411** MT2063_VGAGC VGA gain code
1412** MT2063_VGAOI VGA output current
1413** MT2063_TAGC TAGC setting
1414** MT2063_AMPGC AMP gain code
1415** MT2063_AVOID_DECT Avoid DECT Frequencies
1416** MT2063_CTFILT_SW Cleartune filter selection
1417**
1418** Usage: status |= MT2063_GetParam(hMT2063,
1419** MT2063_IF1_ACTUAL,
1420** &f_IF1_Actual);
1421**
1422** Returns: status:
1423** MT_OK - No errors
1424** MT_INV_HANDLE - Invalid tuner handle
1425** MT_ARG_NULL - Null pointer argument passed
1426** MT_ARG_RANGE - Invalid parameter requested
1427**
1428** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1429**
1430** See Also: MT2063_SetParam, MT2063_Open
1431**
1432** Revision History:
1433**
1434** SCR Date Author Description
1435** -------------------------------------------------------------------------
1436** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1437** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1438** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1439** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1440** in GetParam.
1441** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1442** Split SetParam up to ACLNA / ACLNA_MAX
1443** removed ACLNA_INRC/DECR (+RF & FIF)
1444** removed GCUAUTO / BYPATNDN/UP
1445** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1446** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1447** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1448**
1449****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001450static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001451{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001452 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001453 u32 Div;
1454 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001455
1456 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001457 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001458
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001459 switch (param) {
1460 /* Serial Bus address of this tuner */
1461 case MT2063_IC_ADDR:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001462 *pValue = state->config->tuner_address;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001463 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001464
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001465 /* Max # of MT2063's allowed to be open */
1466 case MT2063_MAX_OPEN:
1467 *pValue = nMT2063MaxTuners;
1468 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001469
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001470 /* # of MT2063's open */
1471 case MT2063_NUM_OPEN:
1472 *pValue = nMT2063OpenTuners;
1473 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001474
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001475 /* crystal frequency */
1476 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001477 *pValue = state->AS_Data.f_ref;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001478 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001479
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001480 /* minimum tuning step size */
1481 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001482 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001483 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001484
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001485 /* input center frequency */
1486 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001487 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001488 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001489
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001490 /* LO1 Frequency */
1491 case MT2063_LO1_FREQ:
1492 {
1493 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1494 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001495 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001496 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001497 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001498 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001499 Div = state->reg[MT2063_REG_LO1C_1];
1500 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1501 state->AS_Data.f_LO1 =
1502 (state->AS_Data.f_ref * Div) +
1503 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001504 f_ref, Num, 64);
1505 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001506 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001507 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001508
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001509 /* LO1 minimum step size */
1510 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001511 *pValue = state->AS_Data.f_LO1_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001512 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001513
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001514 /* LO1 FracN keep-out region */
1515 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001516 *pValue = state->AS_Data.f_LO1_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001517 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001518
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001519 /* Current 1st IF in use */
1520 case MT2063_IF1_ACTUAL:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001521 *pValue = state->f_IF1_actual;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001522 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001523
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001524 /* Requested 1st IF */
1525 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001526 *pValue = state->AS_Data.f_if1_Request;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001527 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001528
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001529 /* Center of 1st IF SAW filter */
1530 case MT2063_IF1_CENTER:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001531 *pValue = state->AS_Data.f_if1_Center;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001532 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001533
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001534 /* Bandwidth of 1st IF SAW filter */
1535 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001536 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001537 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001538
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001539 /* zero-IF bandwidth */
1540 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001541 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001542 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001543
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001544 /* LO2 Frequency */
1545 case MT2063_LO2_FREQ:
1546 {
1547 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1548 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001549 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001550 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001551 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001552 reg[MT2063_REG_LO2C_1], 3);
1553 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001554 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001555 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001556 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001557 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001558 (state->
1559 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001560 reg
1561 [MT2063_REG_LO2C_3]
1562 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001563 state->AS_Data.f_LO2 =
1564 (state->AS_Data.f_ref * Div) +
1565 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001566 f_ref, Num, 8191);
1567 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001568 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001569 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001570
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001571 /* LO2 minimum step size */
1572 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001573 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001574 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001575
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001576 /* LO2 FracN keep-out region */
1577 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001578 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001579 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001580
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001581 /* output center frequency */
1582 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001583 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001584 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001585
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001586 /* output bandwidth */
1587 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001588 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001589 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001590
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001591 /* min inter-tuner LO separation */
1592 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001593 *pValue = state->AS_Data.f_min_LO_Separation;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001594 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001595
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001596 /* max # of intra-tuner harmonics */
1597 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001598 *pValue = state->AS_Data.maxH1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001599 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001600
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001601 /* max # of inter-tuner harmonics */
1602 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001603 *pValue = state->AS_Data.maxH2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001604 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001605
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001606 /* # of 1st IF exclusion zones */
1607 case MT2063_EXCL_ZONES:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001608 *pValue = state->AS_Data.nZones;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001609 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001610
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001611 /* # of spurs found/avoided */
1612 case MT2063_NUM_SPURS:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001613 *pValue = state->AS_Data.nSpursFound;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001614 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001615
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001616 /* >0 spurs avoided */
1617 case MT2063_SPUR_AVOIDED:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001618 *pValue = state->AS_Data.bSpurAvoided;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001619 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001620
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001621 /* >0 spurs in output (mathematically) */
1622 case MT2063_SPUR_PRESENT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001623 *pValue = state->AS_Data.bSpurPresent;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001624 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001625
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001626 /* Predefined receiver setup combination */
1627 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001628 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001629 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001630
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001631 case MT2063_PD1:
1632 case MT2063_PD2: {
1633 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001634 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001635 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1636 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001637
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001638 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001639
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001640 /* Initiate ADC output to reg 0x0A */
1641 if (reg != orig)
1642 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001643 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001644 MT2063_REG_BYP_CTRL,
1645 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001646
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001647 if (status < 0)
1648 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001649
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001650 for (i = 0; i < 8; i++) {
1651 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001652 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001653 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001654 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001655 reg
1656 [MT2063_REG_ADC_OUT],
1657 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001658
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001659 if (status >= 0)
1660 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001661 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001662 reg[MT2063_REG_ADC_OUT];
1663 else {
1664 if (i)
1665 *pValue /= i;
1666 return (status);
1667 }
1668 }
1669 *pValue /= 8; /* divide by number of reads */
1670 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001671
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001672 /* Restore value of Register BYP_CTRL */
1673 if (reg != orig)
1674 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001675 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001676 MT2063_REG_BYP_CTRL,
1677 &orig, 1);
1678 }
1679 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001680
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001681 /* Get LNA attenuator code */
1682 case MT2063_ACLNA:
1683 {
1684 u8 val;
1685 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001686 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001687 &val);
1688 *pValue = val & 0x1f;
1689 }
1690 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001691
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001692 /* Get RF attenuator code */
1693 case MT2063_ACRF:
1694 {
1695 u8 val;
1696 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001697 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001698 &val);
1699 *pValue = val & 0x1f;
1700 }
1701 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001702
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001703 /* Get FIF attenuator code */
1704 case MT2063_ACFIF:
1705 {
1706 u8 val;
1707 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001708 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001709 &val);
1710 *pValue = val & 0x1f;
1711 }
1712 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001713
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001714 /* Get LNA attenuator limit */
1715 case MT2063_ACLNA_MAX:
1716 {
1717 u8 val;
1718 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001719 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001720 &val);
1721 *pValue = val & 0x1f;
1722 }
1723 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001724
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001725 /* Get RF attenuator limit */
1726 case MT2063_ACRF_MAX:
1727 {
1728 u8 val;
1729 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001730 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001731 &val);
1732 *pValue = val & 0x1f;
1733 }
1734 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001735
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001736 /* Get FIF attenuator limit */
1737 case MT2063_ACFIF_MAX:
1738 {
1739 u8 val;
1740 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001741 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001742 &val);
1743 *pValue = val & 0x1f;
1744 }
1745 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001746
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001747 /* Get current used DNC output */
1748 case MT2063_DNC_OUTPUT_ENABLE:
1749 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001750 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1751 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001752 *pValue =
1753 (u32) MT2063_DNC_NONE;
1754 else
1755 *pValue =
1756 (u32) MT2063_DNC_2;
1757 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001758
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001759 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001760 *pValue =
1761 (u32) MT2063_DNC_1;
1762 else
1763 *pValue =
1764 (u32) MT2063_DNC_BOTH;
1765 }
1766 }
1767 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001768
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001769 /* Get VGA Gain Code */
1770 case MT2063_VGAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001771 *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001772 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001773
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001774 /* Get VGA bias current */
1775 case MT2063_VGAOI:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001776 *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001777 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001778
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001779 /* Get TAGC setting */
1780 case MT2063_TAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001781 *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001782 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001783
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001784 /* Get AMP Gain Code */
1785 case MT2063_AMPGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001786 *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001787 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001788
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001789 /* Avoid DECT Frequencies */
1790 case MT2063_AVOID_DECT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001791 *pValue = state->AS_Data.avoidDECT;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001792 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001793
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001794 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
1795 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001796 *pValue = state->ctfilt_sw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001797 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001798
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001799 case MT2063_EOP:
1800 default:
1801 status |= -ERANGE;
1802 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001803 return (status);
1804}
1805
1806/****************************************************************************
1807**
1808** Name: MT2063_GetReg
1809**
1810** Description: Gets an MT2063 register.
1811**
1812** Parameters: h - Tuner handle (returned by MT2063_Open)
1813** reg - MT2063 register/subaddress location
1814** *val - MT2063 register/subaddress value
1815**
1816** Returns: status:
1817** MT_OK - No errors
1818** MT_COMM_ERR - Serial bus communications error
1819** MT_INV_HANDLE - Invalid tuner handle
1820** MT_ARG_NULL - Null pointer argument passed
1821** MT_ARG_RANGE - Argument out of range
1822**
1823** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1824**
1825** Use this function if you need to read a register from
1826** the MT2063.
1827**
1828** Revision History:
1829**
1830** SCR Date Author Description
1831** -------------------------------------------------------------------------
1832** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1833**
1834****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001835static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001836{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001837 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001838
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001839 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001840 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001841
1842 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001843 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001844
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001845 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001846
1847 return (status);
1848}
1849
1850/******************************************************************************
1851**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001852** Name: MT2063_SetReceiverMode
1853**
1854** Description: Set the MT2063 receiver mode
1855**
1856** --------------+----------------------------------------------
1857** Mode 0 : | MT2063_CABLE_QAM
1858** Mode 1 : | MT2063_CABLE_ANALOG
1859** Mode 2 : | MT2063_OFFAIR_COFDM
1860** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1861** Mode 4 : | MT2063_OFFAIR_ANALOG
1862** Mode 5 : | MT2063_OFFAIR_8VSB
1863** --------------+----+----+----+----+-----+--------------------
1864** (DNC1GC & DNC2GC are the values, which are used, when the specific
1865** DNC Output is selected, the other is always off)
1866**
1867** |<---------- Mode -------------->|
1868** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1869** ------------+-----+-----+-----+-----+-----+-----+
1870** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1871** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1872** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1873** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1874** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1875** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1876** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1877** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1878** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1879** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1880** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1881** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1882** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1883** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1884** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1885**
1886**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001887** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001888** Mode - desired reciever mode
1889**
1890** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1891**
1892** Returns: status:
1893** MT_OK - No errors
1894** MT_COMM_ERR - Serial bus communications error
1895**
1896** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1897** Assumes that the tuner cache is valid.
1898**
1899** Revision History:
1900**
1901** SCR Date Author Description
1902** -------------------------------------------------------------------------
1903** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1904** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1905** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1906** modulation
1907** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1908** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1909** the same settings as with MT Launcher
1910** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1911** Add SetParam DNC_OUTPUT_ENABLE
1912** Removed VGAGC from receiver mode,
1913** default now 1
1914** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1915** Add SetParam AMPGC, removed from rcvr-mode
1916** Corrected names of GCU values
1917** reorganized receiver modes, removed,
1918** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1919** Actualized Receiver-Mode values
1920** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1921** N/A 11-27-2007 PINZ Improved buffered writing
1922** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1923** correct wakeup of the LNA after shutdown
1924** Set AFCsd = 1 as default
1925** Changed CAP1sel default
1926** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1927** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1928** Split SetParam up to ACLNA / ACLNA_MAX
1929** removed ACLNA_INRC/DECR (+RF & FIF)
1930** removed GCUAUTO / BYPATNDN/UP
1931**
1932******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001933static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001934 enum MT2063_RCVR_MODES Mode)
1935{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001936 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001937 u8 val;
1938 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001939
1940 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001941 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001942
1943 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001944 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001945 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001946 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001947 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001948 ? 0x40 :
1949 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001950 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1951 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001952 }
1953 }
1954
1955 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001956 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001957 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001958 }
1959
1960 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001961 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001962 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001963 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001964 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001965 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001966 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001967 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001968 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001969 /* trigger FIFF calibration, needed after changing FIFFQ */
1970 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001971 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001972 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001973 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001974 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001975 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001976 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001977 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001978 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001979 }
1980 }
1981
1982 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001983 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
1984 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001985
1986 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001987 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001988 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001989 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001990 }
1991
1992 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001993 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001994 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995 }
1996
1997 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001998 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001999 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002000 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002001 }
2002
2003 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002004 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002005 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002006 }
2007
2008 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002009 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002010 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002011 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002012 }
2013
2014 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002015 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002016 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002017 }
2018
2019 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002020 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002021 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002022 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002023 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002024 ? 0x80 :
2025 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002026 if (state->reg[MT2063_REG_LNA_TGT] != val) {
2027 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002028 }
2029 }
2030
2031 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002032 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002033 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002034 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002035 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002036 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002037 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2038 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002039 }
2040 }
2041
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002042 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002043 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002044
2045 return (status);
2046}
2047
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002048/****************************************************************************
2049**
2050** Name: MT2063_SetParam
2051**
2052** Description: Sets a tuning algorithm parameter.
2053**
2054** This function provides access to the internals of the
2055** tuning algorithm. You can override many of the tuning
2056** algorithm defaults using this function.
2057**
2058** Parameters: h - Tuner handle (returned by MT2063_Open)
2059** param - Tuning algorithm parameter
2060** (see enum MT2063_Param)
2061** nValue - value to be set
2062**
2063** param Description
2064** ---------------------- --------------------------------
2065** MT2063_SRO_FREQ crystal frequency
2066** MT2063_STEPSIZE minimum tuning step size
2067** MT2063_LO1_FREQ LO1 frequency
2068** MT2063_LO1_STEPSIZE LO1 minimum step size
2069** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2070** MT2063_IF1_REQUEST Requested 1st IF
2071** MT2063_ZIF_BW zero-IF bandwidth
2072** MT2063_LO2_FREQ LO2 frequency
2073** MT2063_LO2_STEPSIZE LO2 minimum step size
2074** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2075** MT2063_OUTPUT_FREQ output center frequency
2076** MT2063_OUTPUT_BW output bandwidth
2077** MT2063_LO_SEPARATION min inter-tuner LO separation
2078** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2079** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2080** MT2063_RCVR_MODE Predefined modes
2081** MT2063_LNA_RIN Set LNA Rin (*)
2082** MT2063_LNA_TGT Set target power level at LNA (*)
2083** MT2063_PD1_TGT Set target power level at PD1 (*)
2084** MT2063_PD2_TGT Set target power level at PD2 (*)
2085** MT2063_ACLNA_MAX LNA attenuator limit (*)
2086** MT2063_ACRF_MAX RF attenuator limit (*)
2087** MT2063_ACFIF_MAX FIF attenuator limit (*)
2088** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2089** MT2063_VGAGC VGA gain code
2090** MT2063_VGAOI VGA output current
2091** MT2063_TAGC TAGC setting
2092** MT2063_AMPGC AMP gain code
2093** MT2063_AVOID_DECT Avoid DECT Frequencies
2094** MT2063_CTFILT_SW Cleartune filter selection
2095**
2096** (*) This parameter is set by MT2063_RCVR_MODE, do not call
2097** additionally.
2098**
2099** Usage: status |= MT2063_SetParam(hMT2063,
2100** MT2063_STEPSIZE,
2101** 50000);
2102**
2103** Returns: status:
2104** MT_OK - No errors
2105** MT_INV_HANDLE - Invalid tuner handle
2106** MT_ARG_NULL - Null pointer argument passed
2107** MT_ARG_RANGE - Invalid parameter requested
2108** or set value out of range
2109** or non-writable parameter
2110**
2111** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2112**
2113** See Also: MT2063_GetParam, MT2063_Open
2114**
2115** Revision History:
2116**
2117** SCR Date Author Description
2118** -------------------------------------------------------------------------
2119** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2120** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2121** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2122** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2123** Split SetParam up to ACLNA / ACLNA_MAX
2124** removed ACLNA_INRC/DECR (+RF & FIF)
2125** removed GCUAUTO / BYPATNDN/UP
2126** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2127** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2128** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2129**
2130****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002131static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002132 enum MT2063_Param param,
2133 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002134{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002135 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002136 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002137
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002138 switch (param) {
2139 /* crystal frequency */
2140 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002141 state->AS_Data.f_ref = nValue;
2142 state->AS_Data.f_LO1_FracN_Avoid = 0;
2143 state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
2144 state->AS_Data.f_LO1_Step = nValue / 64;
2145 state->AS_Data.f_if1_Center =
2146 (state->AS_Data.f_ref / 8) *
2147 (state->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002148 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002149
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002150 /* minimum tuning step size */
2151 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002152 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002153 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002154
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002155 /* LO1 frequency */
2156 case MT2063_LO1_FREQ:
2157 {
2158 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2159 /* Capture the Divider and Numerator portions of other LO */
2160 u8 tempLO2CQ[3];
2161 u8 tempLO2C[3];
2162 u8 tmpOneShot;
2163 u32 Div, FracN;
2164 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002165
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002166 /* Buffer the queue for restoration later and get actual LO2 values. */
2167 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002168 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002169 MT2063_REG_LO2CQ_1,
2170 &(tempLO2CQ[0]), 3);
2171 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002172 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002173 MT2063_REG_LO2C_1,
2174 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002175
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002176 /* clear the one-shot bits */
2177 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
2178 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002179
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002180 /* only write the queue values if they are different from the actual. */
2181 if ((tempLO2CQ[0] != tempLO2C[0]) ||
2182 (tempLO2CQ[1] != tempLO2C[1]) ||
2183 (tempLO2CQ[2] != tempLO2C[2])) {
2184 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002185 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002186 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002187 MT2063_REG_LO2CQ_1,
2188 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002189
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002190 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002191 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002192 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002193 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002194 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002195 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002196 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002197 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002198 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002199 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002200 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002201
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002202 /* Calculate the Divider and Numberator components of LO1 */
2203 status =
2204 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002205 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002206 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002207 state->AS_Data.f_ref);
2208 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002209 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002210 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002211 (u8) (FracN);
2212 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002213 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002214 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002215 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002216 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002217
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002218 /* set the one-shot bit to load the pair of LO values */
2219 tmpOneShot = tempLO2CQ[2] | 0xE0;
2220 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002221 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002222 MT2063_REG_LO2CQ_3,
2223 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002224
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002225 /* only restore the queue values if they were different from the actual. */
2226 if (restore) {
2227 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002228 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002229 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002230 MT2063_REG_LO2CQ_1,
2231 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002232
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002233 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002234 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002235 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002236 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002237 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002238 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002239 tempLO2CQ[2];
2240 }
2241
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002242 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002243 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002244 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002245 }
2246 break;
2247
2248 /* LO1 minimum step size */
2249 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002250 state->AS_Data.f_LO1_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002251 break;
2252
2253 /* LO1 FracN keep-out region */
2254 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002255 state->AS_Data.f_LO1_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002256 break;
2257
2258 /* Requested 1st IF */
2259 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002260 state->AS_Data.f_if1_Request = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002261 break;
2262
2263 /* zero-IF bandwidth */
2264 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002265 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002266 break;
2267
2268 /* LO2 frequency */
2269 case MT2063_LO2_FREQ:
2270 {
2271 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2272 /* Capture the Divider and Numerator portions of other LO */
2273 u8 tempLO1CQ[2];
2274 u8 tempLO1C[2];
2275 u32 Div2;
2276 u32 FracN2;
2277 u8 tmpOneShot;
2278 u8 restore = 0;
2279
2280 /* Buffer the queue for restoration later and get actual LO2 values. */
2281 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002282 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002283 MT2063_REG_LO1CQ_1,
2284 &(tempLO1CQ[0]), 2);
2285 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002286 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002287 MT2063_REG_LO1C_1,
2288 &(tempLO1C[0]), 2);
2289
2290 /* only write the queue values if they are different from the actual. */
2291 if ((tempLO1CQ[0] != tempLO1C[0])
2292 || (tempLO1CQ[1] != tempLO1C[1])) {
2293 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002294 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002295 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002296 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002297 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002298
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002299 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002300 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002301 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002302 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002303 tempLO1C[1];
2304 restore = 1;
2305 }
2306
2307 /* Calculate the Divider and Numberator components of LO2 */
2308 status =
2309 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002310 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002311 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002312 state->AS_Data.f_ref);
2313 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002314 (u8) ((Div2 << 1) |
2315 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002316 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002317 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002318 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002319 (u8) ((FracN2 & 0x0F));
2320 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002321 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002322 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002323 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002324 reg[MT2063_REG_LO1CQ_1], 3);
2325
2326 /* set the one-shot bit to load the LO values */
2327 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002328 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002329 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002330 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002331 MT2063_REG_LO2CQ_3,
2332 &tmpOneShot, 1);
2333
2334 /* only restore LO1 queue value if they were different from the actual. */
2335 if (restore) {
2336 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002337 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002338 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002339 MT2063_REG_LO1CQ_1,
2340 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002341
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002342 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002343 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002344 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002345 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002346 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002347 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002348
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002349 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002350 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002351 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002352 }
2353 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002354
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002355 /* LO2 minimum step size */
2356 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002357 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002358 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002359
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002360 /* LO2 FracN keep-out region */
2361 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002362 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002363 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002364
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002365 /* output center frequency */
2366 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002367 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002368 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002369
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002370 /* output bandwidth */
2371 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002372 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002373 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002374
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002375 /* min inter-tuner LO separation */
2376 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002377 state->AS_Data.f_min_LO_Separation = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002378 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002379
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002380 /* max # of intra-tuner harmonics */
2381 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002382 state->AS_Data.maxH1 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002383 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002384
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002385 /* max # of inter-tuner harmonics */
2386 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002387 state->AS_Data.maxH2 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002388 break;
2389
2390 case MT2063_RCVR_MODE:
2391 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002392 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002393 (enum MT2063_RCVR_MODES)
2394 nValue);
2395 break;
2396
2397 /* Set LNA Rin -- nValue is desired value */
2398 case MT2063_LNA_RIN:
2399 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002400 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002401 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2402 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002403 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002404 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002405 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002406 val);
2407 }
2408 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002409
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002410 /* Set target power level at LNA -- nValue is desired value */
2411 case MT2063_LNA_TGT:
2412 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002413 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002414 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2415 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002416 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002417 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002418 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002419 val);
2420 }
2421 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002422
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002423 /* Set target power level at PD1 -- nValue is desired value */
2424 case MT2063_PD1_TGT:
2425 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002426 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002427 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2428 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002429 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002430 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002431 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002432 val);
2433 }
2434 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002435
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002436 /* Set target power level at PD2 -- nValue is desired value */
2437 case MT2063_PD2_TGT:
2438 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002439 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002440 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2441 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002442 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002443 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002444 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002445 val);
2446 }
2447 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002448
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002449 /* Set LNA atten limit -- nValue is desired value */
2450 case MT2063_ACLNA_MAX:
2451 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002452 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002453 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2454 &
2455 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002456 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002457 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002458 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002459 val);
2460 }
2461 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002462
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002463 /* Set RF atten limit -- nValue is desired value */
2464 case MT2063_ACRF_MAX:
2465 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002466 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002467 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2468 &
2469 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002470 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002471 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002472 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002473 }
2474 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002475
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002476 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2477 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002478 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002479 && nValue > 5)
2480 nValue = 5;
2481 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002482 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002483 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2484 &
2485 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002486 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002487 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002488 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002489 val);
2490 }
2491 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002492
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002493 case MT2063_DNC_OUTPUT_ENABLE:
2494 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002495 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002496 case MT2063_DNC_NONE:
2497 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002498 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2499 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002500 val)
2501 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002502 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002503 MT2063_REG_DNC_GAIN,
2504 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002505
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002506 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2507 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002508 val)
2509 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002510 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002511 MT2063_REG_VGA_GAIN,
2512 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002513
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002514 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2515 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002516 val)
2517 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002518 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002519 MT2063_REG_RSVD_20,
2520 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002521
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002522 break;
2523 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002524 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002525 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002526 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2527 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002528 val)
2529 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002530 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002531 MT2063_REG_DNC_GAIN,
2532 val);
2533
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002534 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2535 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002536 val)
2537 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002538 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002539 MT2063_REG_VGA_GAIN,
2540 val);
2541
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002542 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2543 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002544 val)
2545 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002546 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002547 MT2063_REG_RSVD_20,
2548 val);
2549
2550 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002551 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002552 case MT2063_DNC_2:
2553 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002554 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2555 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002556 val)
2557 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002558 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002559 MT2063_REG_DNC_GAIN,
2560 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002561
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002562 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2563 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002564 val)
2565 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002566 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002567 MT2063_REG_VGA_GAIN,
2568 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002569
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002570 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2571 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002572 val)
2573 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002574 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002575 MT2063_REG_RSVD_20,
2576 val);
2577
2578 break;
2579 }
2580 case MT2063_DNC_BOTH:
2581 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002582 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2583 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002584 val)
2585 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002586 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002587 MT2063_REG_DNC_GAIN,
2588 val);
2589
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002590 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2591 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002592 val)
2593 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002594 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002595 MT2063_REG_VGA_GAIN,
2596 val);
2597
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002598 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2599 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002600 val)
2601 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002602 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002603 MT2063_REG_RSVD_20,
2604 val);
2605
2606 break;
2607 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002608 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002609 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002610 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002611 break;
2612
2613 case MT2063_VGAGC:
2614 /* Set VGA gain code */
2615 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002616 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002617 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
2618 ((nValue & 0x03) << 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002619 if (state->reg[MT2063_REG_VGA_GAIN] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002620 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002621 MT2063_SetReg(state, MT2063_REG_VGA_GAIN,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002622 val);
2623 }
2624 break;
2625
2626 case MT2063_VGAOI:
2627 /* Set VGA bias current */
2628 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002629 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002630 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
2631 (nValue & 0x07);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002632 if (state->reg[MT2063_REG_RSVD_31] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002633 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002634 MT2063_SetReg(state, MT2063_REG_RSVD_31,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002635 val);
2636 }
2637 break;
2638
2639 case MT2063_TAGC:
2640 /* Set TAGC */
2641 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002642 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002643 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
2644 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002645 if (state->reg[MT2063_REG_RSVD_1E] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002646 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002647 MT2063_SetReg(state, MT2063_REG_RSVD_1E,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002648 val);
2649 }
2650 break;
2651
2652 case MT2063_AMPGC:
2653 /* Set Amp gain code */
2654 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002655 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002656 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
2657 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002658 if (state->reg[MT2063_REG_TEMP_SEL] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002659 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002660 MT2063_SetReg(state, MT2063_REG_TEMP_SEL,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002661 val);
2662 }
2663 break;
2664
2665 /* Avoid DECT Frequencies */
2666 case MT2063_AVOID_DECT:
2667 {
2668 enum MT2063_DECT_Avoid_Type newAvoidSetting =
2669 (enum MT2063_DECT_Avoid_Type)nValue;
2670 if ((newAvoidSetting >=
2671 MT2063_NO_DECT_AVOIDANCE)
2672 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002673 state->AS_Data.avoidDECT =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002674 newAvoidSetting;
2675 }
2676 }
2677 break;
2678
2679 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2680 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002681 state->ctfilt_sw = (nValue & 0x01);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002682 break;
2683
2684 /* These parameters are read-only */
2685 case MT2063_IC_ADDR:
2686 case MT2063_MAX_OPEN:
2687 case MT2063_NUM_OPEN:
2688 case MT2063_INPUT_FREQ:
2689 case MT2063_IF1_ACTUAL:
2690 case MT2063_IF1_CENTER:
2691 case MT2063_IF1_BW:
2692 case MT2063_AS_ALG:
2693 case MT2063_EXCL_ZONES:
2694 case MT2063_SPUR_AVOIDED:
2695 case MT2063_NUM_SPURS:
2696 case MT2063_SPUR_PRESENT:
2697 case MT2063_ACLNA:
2698 case MT2063_ACRF:
2699 case MT2063_ACFIF:
2700 case MT2063_EOP:
2701 default:
2702 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002703 }
2704 return (status);
2705}
2706
2707/****************************************************************************
2708**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002709** Name: MT2063_ClearPowerMaskBits
2710**
2711** Description: Clears the power-down mask bits for various sections of
2712** the MT2063
2713**
2714** Parameters: h - Tuner handle (returned by MT2063_Open)
2715** Bits - Mask bits to be cleared.
2716**
2717** See definition of MT2063_Mask_Bits type for description
2718** of each of the power bits.
2719**
2720** Returns: status:
2721** MT_OK - No errors
2722** MT_INV_HANDLE - Invalid tuner handle
2723** MT_COMM_ERR - Serial bus communications error
2724**
2725** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2726**
2727** Revision History:
2728**
2729** SCR Date Author Description
2730** -------------------------------------------------------------------------
2731** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2732**
2733****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002734static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002735{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002736 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002737
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002738 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
2739 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002740 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002741 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002742 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002743 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002744 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002745 }
2746 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002747 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002748 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002749 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002750 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002751 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002752 }
2753
2754 return (status);
2755}
2756
2757/****************************************************************************
2758**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002759** Name: MT2063_SoftwareShutdown
2760**
2761** Description: Enables or disables software shutdown function. When
2762** Shutdown==1, any section whose power mask is set will be
2763** shutdown.
2764**
2765** Parameters: h - Tuner handle (returned by MT2063_Open)
2766** Shutdown - 1 = shutdown the masked sections, otherwise
2767** power all sections on
2768**
2769** Returns: status:
2770** MT_OK - No errors
2771** MT_INV_HANDLE - Invalid tuner handle
2772** MT_COMM_ERR - Serial bus communications error
2773**
2774** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2775**
2776** Revision History:
2777**
2778** SCR Date Author Description
2779** -------------------------------------------------------------------------
2780** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2781** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
2782** correct wakeup of the LNA
2783**
2784****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002785static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002786{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002787 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002788
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002789 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002790 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002791 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002792 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002793
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002794 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002795 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002796 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002797 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002798
2799 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002800 state->reg[MT2063_REG_BYP_CTRL] =
2801 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002802 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002803 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002804 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002805 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002806 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002807 state->reg[MT2063_REG_BYP_CTRL] =
2808 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002809 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002810 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002811 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002812 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002813 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002814 }
2815
2816 return (status);
2817}
2818
2819/****************************************************************************
2820**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002821** Name: MT2063_SetReg
2822**
2823** Description: Sets an MT2063 register.
2824**
2825** Parameters: h - Tuner handle (returned by MT2063_Open)
2826** reg - MT2063 register/subaddress location
2827** val - MT2063 register/subaddress value
2828**
2829** Returns: status:
2830** MT_OK - No errors
2831** MT_COMM_ERR - Serial bus communications error
2832** MT_INV_HANDLE - Invalid tuner handle
2833** MT_ARG_RANGE - Argument out of range
2834**
2835** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2836**
2837** Use this function if you need to override a default
2838** register value
2839**
2840** Revision History:
2841**
2842** SCR Date Author Description
2843** -------------------------------------------------------------------------
2844** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2845**
2846****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002847static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002848{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002849 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002850
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002851 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002852 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002853
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002854 status = mt2063_write(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002855 1);
2856 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002857 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002858
2859 return (status);
2860}
2861
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002862static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002863{
2864 return f_ref * (f_LO / f_ref)
2865 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
2866}
2867
2868/****************************************************************************
2869**
2870** Name: fLO_FractionalTerm
2871**
2872** Description: Calculates the portion contributed by FracN / denom.
2873**
2874** This function preserves maximum precision without
2875** risk of overflow. It accurately calculates
2876** f_ref * num / denom to within 1 HZ with fixed math.
2877**
2878** Parameters: num - Fractional portion of the multiplier
2879** denom - denominator portion of the ratio
2880** This routine successfully handles denom values
2881** up to and including 2^18.
2882** f_Ref - SRO frequency. This calculation handles
2883** f_ref as two separate 14-bit fields.
2884** Therefore, a maximum value of 2^28-1
2885** may safely be used for f_ref. This is
2886** the genesis of the magic number "14" and the
2887** magic mask value of 0x03FFF.
2888**
2889** Returns: f_ref * num / denom
2890**
2891** Revision History:
2892**
2893** SCR Date Author Description
2894** -------------------------------------------------------------------------
2895** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2896**
2897****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002898static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
2899 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002900{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002901 u32 t1 = (f_ref >> 14) * num;
2902 u32 term1 = t1 / denom;
2903 u32 loss = t1 % denom;
2904 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002905 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
2906 return ((term1 << 14) + term2);
2907}
2908
2909/****************************************************************************
2910**
2911** Name: CalcLO1Mult
2912**
2913** Description: Calculates Integer divider value and the numerator
2914** value for a FracN PLL.
2915**
2916** This function assumes that the f_LO and f_Ref are
2917** evenly divisible by f_LO_Step.
2918**
2919** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2920** FracN - OUTPUT: Fractional portion of the multiplier
2921** f_LO - desired LO frequency.
2922** f_LO_Step - Minimum step size for the LO (in Hz).
2923** f_Ref - SRO frequency.
2924** f_Avoid - Range of PLL frequencies to avoid near
2925** integer multiples of f_Ref (in Hz).
2926**
2927** Returns: Recalculated LO frequency.
2928**
2929** Revision History:
2930**
2931** SCR Date Author Description
2932** -------------------------------------------------------------------------
2933** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2934**
2935****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002936static u32 MT2063_CalcLO1Mult(u32 * Div,
2937 u32 * FracN,
2938 u32 f_LO,
2939 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002940{
2941 /* Calculate the whole number portion of the divider */
2942 *Div = f_LO / f_Ref;
2943
2944 /* Calculate the numerator value (round to nearest f_LO_Step) */
2945 *FracN =
2946 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2947 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2948
2949 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
2950}
2951
2952/****************************************************************************
2953**
2954** Name: CalcLO2Mult
2955**
2956** Description: Calculates Integer divider value and the numerator
2957** value for a FracN PLL.
2958**
2959** This function assumes that the f_LO and f_Ref are
2960** evenly divisible by f_LO_Step.
2961**
2962** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2963** FracN - OUTPUT: Fractional portion of the multiplier
2964** f_LO - desired LO frequency.
2965** f_LO_Step - Minimum step size for the LO (in Hz).
2966** f_Ref - SRO frequency.
2967** f_Avoid - Range of PLL frequencies to avoid near
2968** integer multiples of f_Ref (in Hz).
2969**
2970** Returns: Recalculated LO frequency.
2971**
2972** Revision History:
2973**
2974** SCR Date Author Description
2975** -------------------------------------------------------------------------
2976** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2977**
2978****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002979static u32 MT2063_CalcLO2Mult(u32 * Div,
2980 u32 * FracN,
2981 u32 f_LO,
2982 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002983{
2984 /* Calculate the whole number portion of the divider */
2985 *Div = f_LO / f_Ref;
2986
2987 /* Calculate the numerator value (round to nearest f_LO_Step) */
2988 *FracN =
2989 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2990 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2991
2992 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
2993 8191);
2994}
2995
2996/****************************************************************************
2997**
2998** Name: FindClearTuneFilter
2999**
3000** Description: Calculate the corrrect ClearTune filter to be used for
3001** a given input frequency.
3002**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003003** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003004** f_in - RF input center frequency (in Hz).
3005**
3006** Returns: ClearTune filter number (0-31)
3007**
3008** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3009**
3010** Revision History:
3011**
3012** SCR Date Author Description
3013** -------------------------------------------------------------------------
3014** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3015** cross-over frequency values.
3016**
3017****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003018static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003019{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003020 u32 RFBand;
3021 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003022
3023 /*
3024 ** Find RF Band setting
3025 */
3026 RFBand = 31; /* def when f_in > all */
3027 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003028 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003029 RFBand = idx;
3030 break;
3031 }
3032 }
3033 return (RFBand);
3034}
3035
3036/****************************************************************************
3037**
3038** Name: MT2063_Tune
3039**
3040** Description: Change the tuner's tuned frequency to RFin.
3041**
3042** Parameters: h - Open handle to the tuner (from MT2063_Open).
3043** f_in - RF input center frequency (in Hz).
3044**
3045** Returns: status:
3046** MT_OK - No errors
3047** MT_INV_HANDLE - Invalid tuner handle
3048** MT_UPC_UNLOCK - Upconverter PLL unlocked
3049** MT_DNC_UNLOCK - Downconverter PLL unlocked
3050** MT_COMM_ERR - Serial bus communications error
3051** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3052** MT_SPUR_PRESENT - LO spur possible in output
3053** MT_FIN_RANGE - Input freq out of range
3054** MT_FOUT_RANGE - Output freq out of range
3055** MT_UPC_RANGE - Upconverter freq out of range
3056** MT_DNC_RANGE - Downconverter freq out of range
3057**
3058** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
3059**
3060** MT_ReadSub - Read data from the two-wire serial bus
3061** MT_WriteSub - Write data to the two-wire serial bus
3062** MT_Sleep - Delay execution for x milliseconds
3063** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
3064**
3065** Revision History:
3066**
3067** SCR Date Author Description
3068** -------------------------------------------------------------------------
3069** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3070** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
3071** cross-over frequency values.
3072** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3073** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3074** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3075**
3076****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003077static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003078{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003079
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003080 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003081 u32 LO1; /* 1st LO register value */
3082 u32 Num1; /* Numerator for LO1 reg. value */
3083 u32 f_IF1; /* 1st IF requested */
3084 u32 LO2; /* 2nd LO register value */
3085 u32 Num2; /* Numerator for LO2 reg. value */
3086 u32 ofLO1, ofLO2; /* last time's LO frequencies */
3087 u32 ofin, ofout; /* last time's I/O frequencies */
3088 u8 fiffc = 0x80; /* FIFF center freq from tuner */
3089 u32 fiffof; /* Offset from FIFF center freq */
3090 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
3091 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
3092 u8 val;
3093 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003094
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003095 /* Check the input and output frequency ranges */
3096 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003097 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003098
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003099 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
3100 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003101 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003102
3103 /*
3104 ** Save original LO1 and LO2 register values
3105 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003106 ofLO1 = state->AS_Data.f_LO1;
3107 ofLO2 = state->AS_Data.f_LO2;
3108 ofin = state->AS_Data.f_in;
3109 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003110
3111 /*
3112 ** Find and set RF Band setting
3113 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003114 if (state->ctfilt_sw == 1) {
3115 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
3116 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003117 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003118 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003119 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003120 val = state->reg[MT2063_REG_CTUNE_OV];
3121 RFBand = FindClearTuneFilter(state, f_in);
3122 state->reg[MT2063_REG_CTUNE_OV] =
3123 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003124 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003125 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003126 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003127 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003128 }
3129 }
3130
3131 /*
3132 ** Read the FIFF Center Frequency from the tuner
3133 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003134 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003135 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003136 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003137 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003138 &state->reg[MT2063_REG_FIFFC], 1);
3139 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003140 }
3141 /*
3142 ** Assign in the requested values
3143 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003144 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003145 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003146 state->AS_Data.f_if1_Request =
3147 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
3148 state->AS_Data.f_LO1_Step,
3149 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003150
3151 /*
3152 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
3153 ** desired LO1 frequency
3154 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003155 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003156
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003157 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003158
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003159 state->AS_Data.f_LO1 =
3160 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
3161 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003162
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003163 state->AS_Data.f_LO2 =
3164 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3165 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003166
3167 /*
3168 ** Check for any LO spurs in the output bandwidth and adjust
3169 ** the LO settings to avoid them if needed
3170 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003171 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003172 /*
3173 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
3174 ** Recalculate the LO frequencies and the values to be placed
3175 ** in the tuning registers.
3176 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003177 state->AS_Data.f_LO1 =
3178 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
3179 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
3180 state->AS_Data.f_LO2 =
3181 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3182 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
3183 state->AS_Data.f_LO2 =
3184 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
3185 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003186
3187 /*
3188 ** Check the upconverter and downconverter frequency ranges
3189 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003190 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
3191 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003192 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003193 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
3194 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003195 status |= MT2063_DNC_RANGE;
3196 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003197 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003198 LO2LK = 0x40;
3199
3200 /*
3201 ** If we have the same LO frequencies and we're already locked,
3202 ** then skip re-programming the LO registers.
3203 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003204 if ((ofLO1 != state->AS_Data.f_LO1)
3205 || (ofLO2 != state->AS_Data.f_LO2)
3206 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003207 (LO1LK | LO2LK))) {
3208 /*
3209 ** Calculate the FIFFOF register value
3210 **
3211 ** IF1_Actual
3212 ** FIFFOF = ------------ - 8 * FIFFC - 4992
3213 ** f_ref/64
3214 */
3215 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003216 (state->AS_Data.f_LO1 -
3217 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003218 4992;
3219 if (fiffof > 0xFF)
3220 fiffof = 0xFF;
3221
3222 /*
3223 ** Place all of the calculated values into the local tuner
3224 ** register fields.
3225 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003226 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003227 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
3228 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
3229 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003230 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003231 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
3232 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003233
3234 /*
3235 ** Now write out the computed register values
3236 ** IMPORTANT: There is a required order for writing
3237 ** (0x05 must follow all the others).
3238 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003239 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 -03003240 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003241 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003242 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003243 }
3244 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003245 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003246 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003247 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003248 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003249 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003250 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003251 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003252 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003253 reg[MT2063_REG_FIFF_OFFSET],
3254 1);
3255 }
3256 }
3257
3258 /*
3259 ** Check for LO's locking
3260 */
3261
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003262 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003263 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003264 }
3265 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003266 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003267 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003268 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003269 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003270 }
3271 }
3272
3273 return (status);
3274}
3275
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003276static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003277 enum MTTune_atv_standard tv_type)
3278{
3279
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003280 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003281
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003282 s32 pict_car = 0;
3283 s32 pict2chanb_vsb = 0;
3284 s32 pict2chanb_snd = 0;
3285 s32 pict2snd1 = 0;
3286 s32 pict2snd2 = 0;
3287 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003288
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003289 s32 if_mid = 0;
3290 s32 rcvr_mode = 0;
3291 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003292
3293 switch (tv_type) {
3294 case MTTUNEA_PAL_B:{
3295 pict_car = 38900000;
3296 ch_bw = 8000000;
3297 pict2chanb_vsb = -1250000;
3298 pict2snd1 = 5500000;
3299 pict2snd2 = 5742000;
3300 rcvr_mode = 1;
3301 break;
3302 }
3303 case MTTUNEA_PAL_G:{
3304 pict_car = 38900000;
3305 ch_bw = 7000000;
3306 pict2chanb_vsb = -1250000;
3307 pict2snd1 = 5500000;
3308 pict2snd2 = 0;
3309 rcvr_mode = 1;
3310 break;
3311 }
3312 case MTTUNEA_PAL_I:{
3313 pict_car = 38900000;
3314 ch_bw = 8000000;
3315 pict2chanb_vsb = -1250000;
3316 pict2snd1 = 6000000;
3317 pict2snd2 = 0;
3318 rcvr_mode = 1;
3319 break;
3320 }
3321 case MTTUNEA_PAL_L:{
3322 pict_car = 38900000;
3323 ch_bw = 8000000;
3324 pict2chanb_vsb = -1250000;
3325 pict2snd1 = 6500000;
3326 pict2snd2 = 0;
3327 rcvr_mode = 1;
3328 break;
3329 }
3330 case MTTUNEA_PAL_MN:{
3331 pict_car = 38900000;
3332 ch_bw = 6000000;
3333 pict2chanb_vsb = -1250000;
3334 pict2snd1 = 4500000;
3335 pict2snd2 = 0;
3336 rcvr_mode = 1;
3337 break;
3338 }
3339 case MTTUNEA_PAL_DK:{
3340 pict_car = 38900000;
3341 ch_bw = 8000000;
3342 pict2chanb_vsb = -1250000;
3343 pict2snd1 = 6500000;
3344 pict2snd2 = 0;
3345 rcvr_mode = 1;
3346 break;
3347 }
3348 case MTTUNEA_DIGITAL:{
3349 pict_car = 36125000;
3350 ch_bw = 8000000;
3351 pict2chanb_vsb = -(ch_bw / 2);
3352 pict2snd1 = 0;
3353 pict2snd2 = 0;
3354 rcvr_mode = 2;
3355 break;
3356 }
3357 case MTTUNEA_FMRADIO:{
3358 pict_car = 38900000;
3359 ch_bw = 8000000;
3360 pict2chanb_vsb = -(ch_bw / 2);
3361 pict2snd1 = 0;
3362 pict2snd2 = 0;
3363 rcvr_mode = 4;
3364 //f_in -= 2900000;
3365 break;
3366 }
3367 case MTTUNEA_DVBC:{
3368 pict_car = 36125000;
3369 ch_bw = 8000000;
3370 pict2chanb_vsb = -(ch_bw / 2);
3371 pict2snd1 = 0;
3372 pict2snd2 = 0;
3373 rcvr_mode = MT2063_CABLE_QAM;
3374 break;
3375 }
3376 case MTTUNEA_DVBT:{
3377 pict_car = 36125000;
3378 ch_bw = bw_in; //8000000
3379 pict2chanb_vsb = -(ch_bw / 2);
3380 pict2snd1 = 0;
3381 pict2snd2 = 0;
3382 rcvr_mode = MT2063_OFFAIR_COFDM;
3383 break;
3384 }
3385 case MTTUNEA_UNKNOWN:
3386 break;
3387 default:
3388 break;
3389 }
3390
3391 pict2chanb_snd = pict2chanb_vsb - ch_bw;
3392 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
3393
3394 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
3395 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
3396 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
3397 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3398
3399 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
3400 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
3401 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3402
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003403 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003404}
3405
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003406static const u8 MT2063B0_defaults[] = {
3407 /* Reg, Value */
3408 0x19, 0x05,
3409 0x1B, 0x1D,
3410 0x1C, 0x1F,
3411 0x1D, 0x0F,
3412 0x1E, 0x3F,
3413 0x1F, 0x0F,
3414 0x20, 0x3F,
3415 0x22, 0x21,
3416 0x23, 0x3F,
3417 0x24, 0x20,
3418 0x25, 0x3F,
3419 0x27, 0xEE,
3420 0x2C, 0x27, /* bit at 0x20 is cleared below */
3421 0x30, 0x03,
3422 0x2C, 0x07, /* bit at 0x20 is cleared here */
3423 0x2D, 0x87,
3424 0x2E, 0xAA,
3425 0x28, 0xE1, /* Set the FIFCrst bit here */
3426 0x28, 0xE0, /* Clear the FIFCrst bit here */
3427 0x00
3428};
3429
3430/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3431static const u8 MT2063B1_defaults[] = {
3432 /* Reg, Value */
3433 0x05, 0xF0,
3434 0x11, 0x10, /* New Enable AFCsd */
3435 0x19, 0x05,
3436 0x1A, 0x6C,
3437 0x1B, 0x24,
3438 0x1C, 0x28,
3439 0x1D, 0x8F,
3440 0x1E, 0x14,
3441 0x1F, 0x8F,
3442 0x20, 0x57,
3443 0x22, 0x21, /* New - ver 1.03 */
3444 0x23, 0x3C, /* New - ver 1.10 */
3445 0x24, 0x20, /* New - ver 1.03 */
3446 0x2C, 0x24, /* bit at 0x20 is cleared below */
3447 0x2D, 0x87, /* FIFFQ=0 */
3448 0x2F, 0xF3,
3449 0x30, 0x0C, /* New - ver 1.11 */
3450 0x31, 0x1B, /* New - ver 1.11 */
3451 0x2C, 0x04, /* bit at 0x20 is cleared here */
3452 0x28, 0xE1, /* Set the FIFCrst bit here */
3453 0x28, 0xE0, /* Clear the FIFCrst bit here */
3454 0x00
3455};
3456
3457/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3458static const u8 MT2063B3_defaults[] = {
3459 /* Reg, Value */
3460 0x05, 0xF0,
3461 0x19, 0x3D,
3462 0x2C, 0x24, /* bit at 0x20 is cleared below */
3463 0x2C, 0x04, /* bit at 0x20 is cleared here */
3464 0x28, 0xE1, /* Set the FIFCrst bit here */
3465 0x28, 0xE0, /* Clear the FIFCrst bit here */
3466 0x00
3467};
3468
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003469static int mt2063_init(struct dvb_frontend *fe)
3470{
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003471 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003472 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003473 u8 all_resets = 0xF0; /* reset/load bits */
3474 const u8 *def = NULL;
3475 u32 FCRUN;
3476 s32 maxReads;
3477 u32 fcu_osc;
3478 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003479
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003480 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003481
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003482 /* Read the Part/Rev code from the tuner */
3483 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
3484 if (status < 0)
3485 return status;
3486
3487 /* Check the part/rev code */
3488 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
3489 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
3490 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
3491 return -ENODEV; /* Wrong tuner Part/Rev code */
3492
3493 /* Check the 2nd byte of the Part/Rev code from the tuner */
3494 status = mt2063_read(state, MT2063_REG_RSVD_3B,
3495 &state->reg[MT2063_REG_RSVD_3B], 1);
3496
3497 /* b7 != 0 ==> NOT MT2063 */
3498 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
3499 return -ENODEV; /* Wrong tuner Part/Rev code */
3500
3501 /* Reset the tuner */
3502 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
3503 if (status < 0)
3504 return status;
3505
3506 /* change all of the default values that vary from the HW reset values */
3507 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
3508 switch (state->reg[MT2063_REG_PART_REV]) {
3509 case MT2063_B3:
3510 def = MT2063B3_defaults;
3511 break;
3512
3513 case MT2063_B1:
3514 def = MT2063B1_defaults;
3515 break;
3516
3517 case MT2063_B0:
3518 def = MT2063B0_defaults;
3519 break;
3520
3521 default:
3522 return -ENODEV;
3523 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003524 }
3525
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003526 while (status >= 0 && *def) {
3527 u8 reg = *def++;
3528 u8 val = *def++;
3529 status = mt2063_write(state, reg, &val, 1);
3530 }
3531 if (status < 0)
3532 return status;
3533
3534 /* Wait for FIFF location to complete. */
3535 FCRUN = 1;
3536 maxReads = 10;
3537 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3538 msleep(2);
3539 status = mt2063_read(state,
3540 MT2063_REG_XO_STATUS,
3541 &state->
3542 reg[MT2063_REG_XO_STATUS], 1);
3543 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
3544 }
3545
3546 if (FCRUN != 0 || status < 0)
3547 return -ENODEV;
3548
3549 status = mt2063_read(state,
3550 MT2063_REG_FIFFC,
3551 &state->reg[MT2063_REG_FIFFC], 1);
3552 if (status < 0)
3553 return status;
3554
3555 /* Read back all the registers from the tuner */
3556 status = mt2063_read(state,
3557 MT2063_REG_PART_REV,
3558 state->reg, MT2063_REG_END_REGS);
3559 if (status < 0)
3560 return status;
3561
3562 /* Initialize the tuner state. */
3563 state->tuner_id = state->reg[MT2063_REG_PART_REV];
3564 state->AS_Data.f_ref = MT2063_REF_FREQ;
3565 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
3566 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
3567 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
3568 state->AS_Data.f_out = 43750000UL;
3569 state->AS_Data.f_out_bw = 6750000UL;
3570 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3571 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
3572 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3573 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3574 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3575 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3576 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
3577 state->AS_Data.f_LO1 = 2181000000UL;
3578 state->AS_Data.f_LO2 = 1486249786UL;
3579 state->f_IF1_actual = state->AS_Data.f_if1_Center;
3580 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
3581 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3582 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3583 state->num_regs = MT2063_REG_END_REGS;
3584 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3585 state->ctfilt_sw = 0;
3586
3587 state->CTFiltMax[0] = 69230000;
3588 state->CTFiltMax[1] = 105770000;
3589 state->CTFiltMax[2] = 140350000;
3590 state->CTFiltMax[3] = 177110000;
3591 state->CTFiltMax[4] = 212860000;
3592 state->CTFiltMax[5] = 241130000;
3593 state->CTFiltMax[6] = 274370000;
3594 state->CTFiltMax[7] = 309820000;
3595 state->CTFiltMax[8] = 342450000;
3596 state->CTFiltMax[9] = 378870000;
3597 state->CTFiltMax[10] = 416210000;
3598 state->CTFiltMax[11] = 456500000;
3599 state->CTFiltMax[12] = 495790000;
3600 state->CTFiltMax[13] = 534530000;
3601 state->CTFiltMax[14] = 572610000;
3602 state->CTFiltMax[15] = 598970000;
3603 state->CTFiltMax[16] = 635910000;
3604 state->CTFiltMax[17] = 672130000;
3605 state->CTFiltMax[18] = 714840000;
3606 state->CTFiltMax[19] = 739660000;
3607 state->CTFiltMax[20] = 770410000;
3608 state->CTFiltMax[21] = 814660000;
3609 state->CTFiltMax[22] = 846950000;
3610 state->CTFiltMax[23] = 867820000;
3611 state->CTFiltMax[24] = 915980000;
3612 state->CTFiltMax[25] = 947450000;
3613 state->CTFiltMax[26] = 983110000;
3614 state->CTFiltMax[27] = 1021630000;
3615 state->CTFiltMax[28] = 1061870000;
3616 state->CTFiltMax[29] = 1098330000;
3617 state->CTFiltMax[30] = 1138990000;
3618
3619 /*
3620 ** Fetch the FCU osc value and use it and the fRef value to
3621 ** scale all of the Band Max values
3622 */
3623
3624 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3625 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3626 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3627 if (status < 0)
3628 return status;
3629
3630 /* Read the ClearTune filter calibration value */
3631 status = mt2063_read(state, MT2063_REG_FIFFC,
3632 &state->reg[MT2063_REG_FIFFC], 1);
3633 if (status < 0)
3634 return status;
3635
3636 fcu_osc = state->reg[MT2063_REG_FIFFC];
3637
3638 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3639 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3640 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3641 if (status < 0)
3642 return status;
3643
3644 /* Adjust each of the values in the ClearTune filter cross-over table */
3645 for (i = 0; i < 31; i++)
3646 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
3647
3648 status = MT2063_SoftwareShutdown(state, 1);
3649 if (status < 0)
3650 return status;
3651 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
3652 if (status < 0)
3653 return status;
3654
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003655 return 0;
3656}
3657
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003658static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3659{
3660 int rc = 0;
3661
3662 //get tuner lock status
3663
3664 return rc;
3665}
3666
3667static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003668 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003669{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003670 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003671
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003672 switch (param) {
3673 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003674 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003675 break;
3676 case DVBFE_TUNER_TUNERSTEP:
3677 break;
3678 case DVBFE_TUNER_IFFREQ:
3679 break;
3680 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003681 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003682 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003683 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003684 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003685 break;
3686 default:
3687 break;
3688 }
3689
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003690 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003691}
3692
3693static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003694 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003695{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003696 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003697 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003698
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003699 switch (param) {
3700 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003701 //set frequency
3702
3703 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003704 MT_Tune_atv(state,
3705 tunstate->frequency, tunstate->bandwidth,
3706 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003707
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003708 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003709 break;
3710 case DVBFE_TUNER_TUNERSTEP:
3711 break;
3712 case DVBFE_TUNER_IFFREQ:
3713 break;
3714 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003715 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003716 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003717 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003718 case DVBFE_TUNER_REFCLOCK:
3719
3720 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003721 default:
3722 break;
3723 }
3724
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003725 return (int)status;
3726}
3727
3728static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003729{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003730 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003731
3732 fe->tuner_priv = NULL;
3733 kfree(state);
3734
3735 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003736}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003737
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003738static struct dvb_tuner_ops mt2063_ops = {
3739 .info = {
3740 .name = "MT2063 Silicon Tuner",
3741 .frequency_min = 45000000,
3742 .frequency_max = 850000000,
3743 .frequency_step = 0,
3744 },
3745
3746 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003747 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003748 .get_status = mt2063_get_status,
3749 .get_state = mt2063_get_state,
3750 .set_state = mt2063_set_state,
3751 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003752};
3753
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003754struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3755 struct mt2063_config *config,
3756 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003757{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003758 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003759
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003760 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003761 if (state == NULL)
3762 goto error;
3763
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003764 state->config = config;
3765 state->i2c = i2c;
3766 state->frontend = fe;
3767 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003768 fe->tuner_priv = state;
3769 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003770
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003771 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003772 return fe;
3773
3774error:
3775 kfree(state);
3776 return NULL;
3777}
3778
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003779EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003780MODULE_PARM_DESC(verbose, "Set Verbosity level");
3781
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003782MODULE_AUTHOR("Henry");
3783MODULE_DESCRIPTION("MT2063 Silicon tuner");
3784MODULE_LICENSE("GPL");