blob: 6c73bfd31c47da0590e23899cfc8920a50122ea2 [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**
956** Name: umax
957**
958** Description: Implements a simple maximum function for unsigned numbers.
959** Implemented as a function rather than a macro to avoid
960** multiple evaluation of the calling parameters.
961**
962** Parameters: a, b - Values to be compared
963**
964** Global: None
965**
966** Returns: larger of the input values.
967**
968** Dependencies: None.
969**
970** Revision History:
971**
972** SCR Date Author Description
973** -------------------------------------------------------------------------
974** N/A 06-02-2004 JWS Original
975**
976****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300977static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300978{
979 return (a >= b) ? a : b;
980}
981
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300982/****************************************************************************
983**
984** Name: IsSpurInBand
985**
986** Description: Checks to see if a spur will be present within the IF's
987** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
988**
989** ma mb mc md
990** <--+-+-+-------------------+-------------------+-+-+-->
991** | ^ 0 ^ |
992** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
993** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
994**
995** Note that some equations are doubled to prevent round-off
996** problems when calculating fIFBW/2
997**
998** Parameters: pAS_Info - Avoid Spurs information block
999** fm - If spur, amount f_IF1 has to move negative
1000** fp - If spur, amount f_IF1 has to move positive
1001**
1002** Global: None
1003**
1004** Returns: 1 if an LO spur would be present, otherwise 0.
1005**
1006** Dependencies: None.
1007**
1008** Revision History:
1009**
1010** SCR Date Author Description
1011** -------------------------------------------------------------------------
1012** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1013**
1014****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001015static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1016 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001017{
1018 /*
1019 ** Calculate LO frequency settings.
1020 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001021 u32 n, n0;
1022 const u32 f_LO1 = pAS_Info->f_LO1;
1023 const u32 f_LO2 = pAS_Info->f_LO2;
1024 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1025 const u32 c = d - pAS_Info->f_out_bw;
1026 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -03001027 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001028 s32 f_nsLO1, f_nsLO2;
1029 s32 f_Spur;
1030 u32 ma, mb, mc, md, me, mf;
1031 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001032 *fm = 0;
1033
1034 /*
1035 ** For each edge (d, c & f), calculate a scale, based on the gcd
1036 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1037 ** gcd-based scale factor or f_Scale.
1038 */
1039 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001040 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001041 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001042 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001043 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001044 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001045 hgfs = gf_Scale / 2;
1046
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001047 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001048
1049 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1050 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1051 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1052 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1053
1054 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1055 if (md >= pAS_Info->maxH1)
1056 break;
1057
1058 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1059 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1060
1061 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1062 if (md == ma)
1063 continue;
1064
1065 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1066 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1067 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001068 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1069 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001070 f_Spur =
1071 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1072 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1073
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001074 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1075 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001076 return 1;
1077 }
1078
1079 /* Location of Zero-IF-spur to be checked */
1080 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1081 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1082 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1083 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1084 if (me != mf) {
1085 f_nsLO1 = n * (f_LO1 / gf_Scale);
1086 f_nsLO2 = me * (f_LO2 / gf_Scale);
1087 f_Spur =
1088 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1089 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1090
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001091 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1092 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001093 return 1;
1094 }
1095
1096 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1097 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1098 if (ma != mb) {
1099 f_nsLO1 = n * (f_LO1 / gc_Scale);
1100 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1101 f_Spur =
1102 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1103 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1104
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001105 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1106 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001107 return 1;
1108 }
1109 }
1110
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001111 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001112 return 0;
1113}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001114
1115/*****************************************************************************
1116**
1117** Name: MT_AvoidSpurs
1118**
1119** Description: Main entry point to avoid spurs.
1120** Checks for existing spurs in present LO1, LO2 freqs
1121** and if present, chooses spur-free LO1, LO2 combination
1122** that tunes the same input/output frequencies.
1123**
1124** Revision History:
1125**
1126** SCR Date Author Description
1127** -------------------------------------------------------------------------
1128** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1129**
1130*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001131static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001132{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001133 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001134 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001135 pAS_Info->bSpurAvoided = 0;
1136 pAS_Info->nSpursFound = 0;
1137
1138 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001139 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001140
1141 /*
1142 ** Avoid LO Generated Spurs
1143 **
1144 ** Make sure that have no LO-related spurs within the IF output
1145 ** bandwidth.
1146 **
1147 ** If there is an LO spur in this band, start at the current IF1 frequency
1148 ** and work out until we find a spur-free frequency or run up against the
1149 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1150 ** will be unchanged if a spur-free setting is not found.
1151 */
1152 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1153 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001154 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1155 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1156 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1157 u32 delta_IF1;
1158 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001159
1160 /*
1161 ** Spur was found, attempt to find a spur-free 1st IF
1162 */
1163 do {
1164 pAS_Info->nSpursFound++;
1165
1166 /* Raise f_IF1_upper, if needed */
1167 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1168
1169 /* Choose next IF1 that is closest to f_IF1_CENTER */
1170 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1171
1172 if (new_IF1 > zfIF1) {
1173 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1174 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1175 } else {
1176 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1177 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1178 }
1179 zfIF1 = new_IF1;
1180
1181 if (zfIF1 > pAS_Info->f_if1_Center)
1182 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1183 else
1184 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1185 }
1186 /*
1187 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1188 ** and there is a spur in the band (again)
1189 */
1190 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1191 pAS_Info->f_if1_bw)
1192 && (pAS_Info->bSpurPresent =
1193 IsSpurInBand(pAS_Info, &fm, &fp)));
1194
1195 /*
1196 ** Use the LO-spur free values found. If the search went all the way to
1197 ** the 1st IF band edge and always found spurs, just leave the original
1198 ** choice. It's as "good" as any other.
1199 */
1200 if (pAS_Info->bSpurPresent == 1) {
1201 status |= MT2063_SPUR_PRESENT_ERR;
1202 pAS_Info->f_LO1 = zfLO1;
1203 pAS_Info->f_LO2 = zfLO2;
1204 } else
1205 pAS_Info->bSpurAvoided = 1;
1206 }
1207
1208 status |=
1209 ((pAS_Info->
1210 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1211
1212 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001213}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001214
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001215//end of mt2063_spuravoid.c
1216//=================================================================
1217//#################################################################
1218//=================================================================
1219
1220/*
1221** The expected version of MT_AvoidSpursData_t
1222** If the version is different, an updated file is needed from Microtune
1223*/
1224/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001225
1226typedef enum {
1227 MT2063_SET_ATTEN,
1228 MT2063_INCR_ATTEN,
1229 MT2063_DECR_ATTEN
1230} MT2063_ATTEN_CNTL_MODE;
1231
1232//#define TUNER_MT2063_OPTIMIZATION
1233/*
1234** Constants used by the tuning algorithm
1235*/
1236#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1237#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1238#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1239#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1240#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1241#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1242#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1243#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1244#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1245#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1246#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1247#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1248#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1249#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1250#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1251#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1252#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1253#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1254
1255/*
1256** Define the supported Part/Rev codes for the MT2063
1257*/
1258#define MT2063_B0 (0x9B)
1259#define MT2063_B1 (0x9C)
1260#define MT2063_B2 (0x9D)
1261#define MT2063_B3 (0x9E)
1262
1263/*
1264** The number of Tuner Registers
1265*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001266static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001267
1268#define USE_GLOBAL_TUNER 0
1269
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001270static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001271static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001272
1273/*
1274** Constants for setting receiver modes.
1275** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1276** (DNC1GC & DNC2GC are the values, which are used, when the specific
1277** DNC Output is selected, the other is always off)
1278**
1279** If PAL-L or L' is received, set:
1280** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1281**
1282** --------------+----------------------------------------------
1283** Mode 0 : | MT2063_CABLE_QAM
1284** Mode 1 : | MT2063_CABLE_ANALOG
1285** Mode 2 : | MT2063_OFFAIR_COFDM
1286** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1287** Mode 4 : | MT2063_OFFAIR_ANALOG
1288** Mode 5 : | MT2063_OFFAIR_8VSB
1289** --------------+----+----+----+----+-----+-----+--------------
1290** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1291** --------------+----+----+----+----+-----+-----+
1292**
1293**
1294*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001295static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1296static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1297static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1298static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1299static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1300static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1301static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1302static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1303static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1304static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1305static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1306static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1307static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1308static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001309
1310/*
1311** Local Function Prototypes - not available for external access.
1312*/
1313
1314/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001315static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1316 u32 f_LO_Step, u32 f_Ref);
1317static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1318 u32 f_LO_Step, u32 f_Ref);
1319static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1320 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001321
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001322/****************************************************************************
1323**
1324** Name: MT2063_GetLocked
1325**
1326** Description: Checks to see if LO1 and LO2 are locked.
1327**
1328** Parameters: h - Open handle to the tuner (from MT2063_Open).
1329**
1330** Returns: status:
1331** MT_OK - No errors
1332** MT_UPC_UNLOCK - Upconverter PLL unlocked
1333** MT_DNC_UNLOCK - Downconverter PLL unlocked
1334** MT_COMM_ERR - Serial bus communications error
1335** MT_INV_HANDLE - Invalid tuner handle
1336**
1337** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1338** MT_Sleep - Delay execution for x milliseconds
1339**
1340** Revision History:
1341**
1342** SCR Date Author Description
1343** -------------------------------------------------------------------------
1344** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1345**
1346****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001347static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001348{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001349 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1350 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1351 const u32 nMaxLoops = nMaxWait / nPollRate;
1352 const u8 LO1LK = 0x80;
1353 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001354 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001355 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001356
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001357 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001358 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001359 LO2LK = 0x40;
1360
1361 do {
1362 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001363 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001364 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001365 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001366
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001367 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001368 return (status);
1369
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001370 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001371 (LO1LK | LO2LK)) {
1372 return (status);
1373 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001374 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001375 }
1376 while (++nDelays < nMaxLoops);
1377
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001378 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001379 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001380 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001381 status |= MT2063_DNC_UNLOCK;
1382
1383 return (status);
1384}
1385
1386/****************************************************************************
1387**
1388** Name: MT2063_GetParam
1389**
1390** Description: Gets a tuning algorithm parameter.
1391**
1392** This function provides access to the internals of the
1393** tuning algorithm - mostly for testing purposes.
1394**
1395** Parameters: h - Tuner handle (returned by MT2063_Open)
1396** param - Tuning algorithm parameter
1397** (see enum MT2063_Param)
1398** pValue - ptr to returned value
1399**
1400** param Description
1401** ---------------------- --------------------------------
1402** MT2063_IC_ADDR Serial Bus address of this tuner
1403** MT2063_MAX_OPEN Max # of MT2063's allowed open
1404** MT2063_NUM_OPEN # of MT2063's open
1405** MT2063_SRO_FREQ crystal frequency
1406** MT2063_STEPSIZE minimum tuning step size
1407** MT2063_INPUT_FREQ input center frequency
1408** MT2063_LO1_FREQ LO1 Frequency
1409** MT2063_LO1_STEPSIZE LO1 minimum step size
1410** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1411** MT2063_IF1_ACTUAL Current 1st IF in use
1412** MT2063_IF1_REQUEST Requested 1st IF
1413** MT2063_IF1_CENTER Center of 1st IF SAW filter
1414** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1415** MT2063_ZIF_BW zero-IF bandwidth
1416** MT2063_LO2_FREQ LO2 Frequency
1417** MT2063_LO2_STEPSIZE LO2 minimum step size
1418** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1419** MT2063_OUTPUT_FREQ output center frequency
1420** MT2063_OUTPUT_BW output bandwidth
1421** MT2063_LO_SEPARATION min inter-tuner LO separation
1422** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1423** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1424** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1425** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1426** MT2063_NUM_SPURS # of spurs found/avoided
1427** MT2063_SPUR_AVOIDED >0 spurs avoided
1428** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1429** MT2063_RCVR_MODE Predefined modes.
1430** MT2063_ACLNA LNA attenuator gain code
1431** MT2063_ACRF RF attenuator gain code
1432** MT2063_ACFIF FIF attenuator gain code
1433** MT2063_ACLNA_MAX LNA attenuator limit
1434** MT2063_ACRF_MAX RF attenuator limit
1435** MT2063_ACFIF_MAX FIF attenuator limit
1436** MT2063_PD1 Actual value of PD1
1437** MT2063_PD2 Actual value of PD2
1438** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1439** MT2063_VGAGC VGA gain code
1440** MT2063_VGAOI VGA output current
1441** MT2063_TAGC TAGC setting
1442** MT2063_AMPGC AMP gain code
1443** MT2063_AVOID_DECT Avoid DECT Frequencies
1444** MT2063_CTFILT_SW Cleartune filter selection
1445**
1446** Usage: status |= MT2063_GetParam(hMT2063,
1447** MT2063_IF1_ACTUAL,
1448** &f_IF1_Actual);
1449**
1450** Returns: status:
1451** MT_OK - No errors
1452** MT_INV_HANDLE - Invalid tuner handle
1453** MT_ARG_NULL - Null pointer argument passed
1454** MT_ARG_RANGE - Invalid parameter requested
1455**
1456** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1457**
1458** See Also: MT2063_SetParam, MT2063_Open
1459**
1460** Revision History:
1461**
1462** SCR Date Author Description
1463** -------------------------------------------------------------------------
1464** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1465** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1466** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1467** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1468** in GetParam.
1469** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1470** Split SetParam up to ACLNA / ACLNA_MAX
1471** removed ACLNA_INRC/DECR (+RF & FIF)
1472** removed GCUAUTO / BYPATNDN/UP
1473** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1474** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1475** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1476**
1477****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001478static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001479{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001480 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001481 u32 Div;
1482 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001483
1484 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001485 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001486
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001487 switch (param) {
1488 /* Serial Bus address of this tuner */
1489 case MT2063_IC_ADDR:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001490 *pValue = state->config->tuner_address;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001491 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001492
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001493 /* Max # of MT2063's allowed to be open */
1494 case MT2063_MAX_OPEN:
1495 *pValue = nMT2063MaxTuners;
1496 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001497
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001498 /* # of MT2063's open */
1499 case MT2063_NUM_OPEN:
1500 *pValue = nMT2063OpenTuners;
1501 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001502
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001503 /* crystal frequency */
1504 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001505 *pValue = state->AS_Data.f_ref;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001506 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001507
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001508 /* minimum tuning step size */
1509 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001510 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001511 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001512
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001513 /* input center frequency */
1514 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001515 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001516 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001517
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001518 /* LO1 Frequency */
1519 case MT2063_LO1_FREQ:
1520 {
1521 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1522 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001523 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001524 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001525 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001526 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001527 Div = state->reg[MT2063_REG_LO1C_1];
1528 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1529 state->AS_Data.f_LO1 =
1530 (state->AS_Data.f_ref * Div) +
1531 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001532 f_ref, Num, 64);
1533 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001534 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001535 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001536
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001537 /* LO1 minimum step size */
1538 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001539 *pValue = state->AS_Data.f_LO1_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001540 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001541
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001542 /* LO1 FracN keep-out region */
1543 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001544 *pValue = state->AS_Data.f_LO1_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001545 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001546
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001547 /* Current 1st IF in use */
1548 case MT2063_IF1_ACTUAL:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001549 *pValue = state->f_IF1_actual;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001550 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001551
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001552 /* Requested 1st IF */
1553 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001554 *pValue = state->AS_Data.f_if1_Request;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001555 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001556
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001557 /* Center of 1st IF SAW filter */
1558 case MT2063_IF1_CENTER:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001559 *pValue = state->AS_Data.f_if1_Center;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001560 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001561
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001562 /* Bandwidth of 1st IF SAW filter */
1563 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001564 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001565 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001566
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001567 /* zero-IF bandwidth */
1568 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001569 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001570 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001571
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001572 /* LO2 Frequency */
1573 case MT2063_LO2_FREQ:
1574 {
1575 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1576 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001577 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001578 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001579 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001580 reg[MT2063_REG_LO2C_1], 3);
1581 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001582 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001583 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001584 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001585 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001586 (state->
1587 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001588 reg
1589 [MT2063_REG_LO2C_3]
1590 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001591 state->AS_Data.f_LO2 =
1592 (state->AS_Data.f_ref * Div) +
1593 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001594 f_ref, Num, 8191);
1595 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001596 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001597 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001598
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001599 /* LO2 minimum step size */
1600 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001601 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001602 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001603
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001604 /* LO2 FracN keep-out region */
1605 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001606 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001607 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001608
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001609 /* output center frequency */
1610 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001611 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001612 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001613
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001614 /* output bandwidth */
1615 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001616 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001617 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001618
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001619 /* min inter-tuner LO separation */
1620 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001621 *pValue = state->AS_Data.f_min_LO_Separation;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001622 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001623
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001624 /* max # of intra-tuner harmonics */
1625 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001626 *pValue = state->AS_Data.maxH1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001627 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001628
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001629 /* max # of inter-tuner harmonics */
1630 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001631 *pValue = state->AS_Data.maxH2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001632 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001633
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001634 /* # of 1st IF exclusion zones */
1635 case MT2063_EXCL_ZONES:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001636 *pValue = state->AS_Data.nZones;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001637 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001638
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001639 /* # of spurs found/avoided */
1640 case MT2063_NUM_SPURS:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001641 *pValue = state->AS_Data.nSpursFound;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001642 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001643
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001644 /* >0 spurs avoided */
1645 case MT2063_SPUR_AVOIDED:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001646 *pValue = state->AS_Data.bSpurAvoided;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001647 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001648
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001649 /* >0 spurs in output (mathematically) */
1650 case MT2063_SPUR_PRESENT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001651 *pValue = state->AS_Data.bSpurPresent;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001652 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001653
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001654 /* Predefined receiver setup combination */
1655 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001656 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001657 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001658
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001659 case MT2063_PD1:
1660 case MT2063_PD2: {
1661 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001662 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001663 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1664 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001665
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001666 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001667
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001668 /* Initiate ADC output to reg 0x0A */
1669 if (reg != orig)
1670 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001671 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001672 MT2063_REG_BYP_CTRL,
1673 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001674
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001675 if (status < 0)
1676 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001677
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001678 for (i = 0; i < 8; i++) {
1679 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001680 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001681 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001682 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001683 reg
1684 [MT2063_REG_ADC_OUT],
1685 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001686
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001687 if (status >= 0)
1688 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001689 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001690 reg[MT2063_REG_ADC_OUT];
1691 else {
1692 if (i)
1693 *pValue /= i;
1694 return (status);
1695 }
1696 }
1697 *pValue /= 8; /* divide by number of reads */
1698 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001699
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001700 /* Restore value of Register BYP_CTRL */
1701 if (reg != orig)
1702 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001703 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001704 MT2063_REG_BYP_CTRL,
1705 &orig, 1);
1706 }
1707 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001708
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001709 /* Get LNA attenuator code */
1710 case MT2063_ACLNA:
1711 {
1712 u8 val;
1713 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001714 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001715 &val);
1716 *pValue = val & 0x1f;
1717 }
1718 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001719
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001720 /* Get RF attenuator code */
1721 case MT2063_ACRF:
1722 {
1723 u8 val;
1724 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001725 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001726 &val);
1727 *pValue = val & 0x1f;
1728 }
1729 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001730
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001731 /* Get FIF attenuator code */
1732 case MT2063_ACFIF:
1733 {
1734 u8 val;
1735 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001736 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001737 &val);
1738 *pValue = val & 0x1f;
1739 }
1740 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001741
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001742 /* Get LNA attenuator limit */
1743 case MT2063_ACLNA_MAX:
1744 {
1745 u8 val;
1746 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001747 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001748 &val);
1749 *pValue = val & 0x1f;
1750 }
1751 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001752
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001753 /* Get RF attenuator limit */
1754 case MT2063_ACRF_MAX:
1755 {
1756 u8 val;
1757 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001758 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001759 &val);
1760 *pValue = val & 0x1f;
1761 }
1762 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001763
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001764 /* Get FIF attenuator limit */
1765 case MT2063_ACFIF_MAX:
1766 {
1767 u8 val;
1768 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001769 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001770 &val);
1771 *pValue = val & 0x1f;
1772 }
1773 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001774
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001775 /* Get current used DNC output */
1776 case MT2063_DNC_OUTPUT_ENABLE:
1777 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001778 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1779 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001780 *pValue =
1781 (u32) MT2063_DNC_NONE;
1782 else
1783 *pValue =
1784 (u32) MT2063_DNC_2;
1785 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001786
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001787 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001788 *pValue =
1789 (u32) MT2063_DNC_1;
1790 else
1791 *pValue =
1792 (u32) MT2063_DNC_BOTH;
1793 }
1794 }
1795 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001796
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001797 /* Get VGA Gain Code */
1798 case MT2063_VGAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001799 *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001800 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001801
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001802 /* Get VGA bias current */
1803 case MT2063_VGAOI:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001804 *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001805 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001806
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001807 /* Get TAGC setting */
1808 case MT2063_TAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001809 *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001810 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001811
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001812 /* Get AMP Gain Code */
1813 case MT2063_AMPGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001814 *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001815 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001816
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001817 /* Avoid DECT Frequencies */
1818 case MT2063_AVOID_DECT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001819 *pValue = state->AS_Data.avoidDECT;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001820 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001821
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001822 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
1823 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001824 *pValue = state->ctfilt_sw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001825 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001826
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001827 case MT2063_EOP:
1828 default:
1829 status |= -ERANGE;
1830 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001831 return (status);
1832}
1833
1834/****************************************************************************
1835**
1836** Name: MT2063_GetReg
1837**
1838** Description: Gets an MT2063 register.
1839**
1840** Parameters: h - Tuner handle (returned by MT2063_Open)
1841** reg - MT2063 register/subaddress location
1842** *val - MT2063 register/subaddress value
1843**
1844** Returns: status:
1845** MT_OK - No errors
1846** MT_COMM_ERR - Serial bus communications error
1847** MT_INV_HANDLE - Invalid tuner handle
1848** MT_ARG_NULL - Null pointer argument passed
1849** MT_ARG_RANGE - Argument out of range
1850**
1851** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1852**
1853** Use this function if you need to read a register from
1854** the MT2063.
1855**
1856** Revision History:
1857**
1858** SCR Date Author Description
1859** -------------------------------------------------------------------------
1860** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1861**
1862****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001863static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001864{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001865 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001866
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001867 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001868 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001869
1870 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001871 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001872
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001873 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001874
1875 return (status);
1876}
1877
1878/******************************************************************************
1879**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001880** Name: MT2063_SetReceiverMode
1881**
1882** Description: Set the MT2063 receiver mode
1883**
1884** --------------+----------------------------------------------
1885** Mode 0 : | MT2063_CABLE_QAM
1886** Mode 1 : | MT2063_CABLE_ANALOG
1887** Mode 2 : | MT2063_OFFAIR_COFDM
1888** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1889** Mode 4 : | MT2063_OFFAIR_ANALOG
1890** Mode 5 : | MT2063_OFFAIR_8VSB
1891** --------------+----+----+----+----+-----+--------------------
1892** (DNC1GC & DNC2GC are the values, which are used, when the specific
1893** DNC Output is selected, the other is always off)
1894**
1895** |<---------- Mode -------------->|
1896** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1897** ------------+-----+-----+-----+-----+-----+-----+
1898** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1899** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1900** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1901** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1902** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1903** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1904** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1905** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1906** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1907** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1908** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1909** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1910** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1911** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1912** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1913**
1914**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001915** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001916** Mode - desired reciever mode
1917**
1918** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1919**
1920** Returns: status:
1921** MT_OK - No errors
1922** MT_COMM_ERR - Serial bus communications error
1923**
1924** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1925** Assumes that the tuner cache is valid.
1926**
1927** Revision History:
1928**
1929** SCR Date Author Description
1930** -------------------------------------------------------------------------
1931** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1932** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1933** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1934** modulation
1935** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1936** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1937** the same settings as with MT Launcher
1938** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1939** Add SetParam DNC_OUTPUT_ENABLE
1940** Removed VGAGC from receiver mode,
1941** default now 1
1942** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1943** Add SetParam AMPGC, removed from rcvr-mode
1944** Corrected names of GCU values
1945** reorganized receiver modes, removed,
1946** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1947** Actualized Receiver-Mode values
1948** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1949** N/A 11-27-2007 PINZ Improved buffered writing
1950** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1951** correct wakeup of the LNA after shutdown
1952** Set AFCsd = 1 as default
1953** Changed CAP1sel default
1954** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1955** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1956** Split SetParam up to ACLNA / ACLNA_MAX
1957** removed ACLNA_INRC/DECR (+RF & FIF)
1958** removed GCUAUTO / BYPATNDN/UP
1959**
1960******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001961static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001962 enum MT2063_RCVR_MODES Mode)
1963{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001964 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001965 u8 val;
1966 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001967
1968 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001969 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001970
1971 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001972 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001973 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001974 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001975 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001976 ? 0x40 :
1977 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001978 if (state->reg[MT2063_REG_PD1_TGT] != val) {
1979 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001980 }
1981 }
1982
1983 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001984 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001985 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001986 }
1987
1988 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001989 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001990 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001991 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001992 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001993 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001994 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001996 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001997 /* trigger FIFF calibration, needed after changing FIFFQ */
1998 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001999 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002000 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002001 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002002 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002003 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002004 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002005 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002006 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002007 }
2008 }
2009
2010 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002011 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
2012 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002013
2014 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002015 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002016 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002017 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002018 }
2019
2020 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002021 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002022 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002023 }
2024
2025 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002026 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002027 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002028 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002029 }
2030
2031 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002032 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002033 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002034 }
2035
2036 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002037 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002038 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002039 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002040 }
2041
2042 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002043 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002044 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002045 }
2046
2047 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002048 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002049 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002050 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002051 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002052 ? 0x80 :
2053 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002054 if (state->reg[MT2063_REG_LNA_TGT] != val) {
2055 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002056 }
2057 }
2058
2059 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002060 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002061 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002062 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002063 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002064 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002065 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2066 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002067 }
2068 }
2069
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002070 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002071 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002072
2073 return (status);
2074}
2075
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002076/****************************************************************************
2077**
2078** Name: MT2063_SetParam
2079**
2080** Description: Sets a tuning algorithm parameter.
2081**
2082** This function provides access to the internals of the
2083** tuning algorithm. You can override many of the tuning
2084** algorithm defaults using this function.
2085**
2086** Parameters: h - Tuner handle (returned by MT2063_Open)
2087** param - Tuning algorithm parameter
2088** (see enum MT2063_Param)
2089** nValue - value to be set
2090**
2091** param Description
2092** ---------------------- --------------------------------
2093** MT2063_SRO_FREQ crystal frequency
2094** MT2063_STEPSIZE minimum tuning step size
2095** MT2063_LO1_FREQ LO1 frequency
2096** MT2063_LO1_STEPSIZE LO1 minimum step size
2097** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2098** MT2063_IF1_REQUEST Requested 1st IF
2099** MT2063_ZIF_BW zero-IF bandwidth
2100** MT2063_LO2_FREQ LO2 frequency
2101** MT2063_LO2_STEPSIZE LO2 minimum step size
2102** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2103** MT2063_OUTPUT_FREQ output center frequency
2104** MT2063_OUTPUT_BW output bandwidth
2105** MT2063_LO_SEPARATION min inter-tuner LO separation
2106** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2107** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2108** MT2063_RCVR_MODE Predefined modes
2109** MT2063_LNA_RIN Set LNA Rin (*)
2110** MT2063_LNA_TGT Set target power level at LNA (*)
2111** MT2063_PD1_TGT Set target power level at PD1 (*)
2112** MT2063_PD2_TGT Set target power level at PD2 (*)
2113** MT2063_ACLNA_MAX LNA attenuator limit (*)
2114** MT2063_ACRF_MAX RF attenuator limit (*)
2115** MT2063_ACFIF_MAX FIF attenuator limit (*)
2116** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2117** MT2063_VGAGC VGA gain code
2118** MT2063_VGAOI VGA output current
2119** MT2063_TAGC TAGC setting
2120** MT2063_AMPGC AMP gain code
2121** MT2063_AVOID_DECT Avoid DECT Frequencies
2122** MT2063_CTFILT_SW Cleartune filter selection
2123**
2124** (*) This parameter is set by MT2063_RCVR_MODE, do not call
2125** additionally.
2126**
2127** Usage: status |= MT2063_SetParam(hMT2063,
2128** MT2063_STEPSIZE,
2129** 50000);
2130**
2131** Returns: status:
2132** MT_OK - No errors
2133** MT_INV_HANDLE - Invalid tuner handle
2134** MT_ARG_NULL - Null pointer argument passed
2135** MT_ARG_RANGE - Invalid parameter requested
2136** or set value out of range
2137** or non-writable parameter
2138**
2139** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2140**
2141** See Also: MT2063_GetParam, MT2063_Open
2142**
2143** Revision History:
2144**
2145** SCR Date Author Description
2146** -------------------------------------------------------------------------
2147** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2148** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2149** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2150** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2151** Split SetParam up to ACLNA / ACLNA_MAX
2152** removed ACLNA_INRC/DECR (+RF & FIF)
2153** removed GCUAUTO / BYPATNDN/UP
2154** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2155** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2156** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2157**
2158****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002159static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002160 enum MT2063_Param param,
2161 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002162{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002163 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002164 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002165
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002166 switch (param) {
2167 /* crystal frequency */
2168 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002169 state->AS_Data.f_ref = nValue;
2170 state->AS_Data.f_LO1_FracN_Avoid = 0;
2171 state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
2172 state->AS_Data.f_LO1_Step = nValue / 64;
2173 state->AS_Data.f_if1_Center =
2174 (state->AS_Data.f_ref / 8) *
2175 (state->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002176 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002177
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002178 /* minimum tuning step size */
2179 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002180 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002181 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002182
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002183 /* LO1 frequency */
2184 case MT2063_LO1_FREQ:
2185 {
2186 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2187 /* Capture the Divider and Numerator portions of other LO */
2188 u8 tempLO2CQ[3];
2189 u8 tempLO2C[3];
2190 u8 tmpOneShot;
2191 u32 Div, FracN;
2192 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002193
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002194 /* Buffer the queue for restoration later and get actual LO2 values. */
2195 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002196 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002197 MT2063_REG_LO2CQ_1,
2198 &(tempLO2CQ[0]), 3);
2199 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002200 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002201 MT2063_REG_LO2C_1,
2202 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002203
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002204 /* clear the one-shot bits */
2205 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
2206 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002207
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002208 /* only write the queue values if they are different from the actual. */
2209 if ((tempLO2CQ[0] != tempLO2C[0]) ||
2210 (tempLO2CQ[1] != tempLO2C[1]) ||
2211 (tempLO2CQ[2] != tempLO2C[2])) {
2212 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002213 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002214 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002215 MT2063_REG_LO2CQ_1,
2216 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002217
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002218 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002219 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002220 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002221 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002222 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002223 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002224 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002225 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002226 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002227 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002228 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002229
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002230 /* Calculate the Divider and Numberator components of LO1 */
2231 status =
2232 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002233 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002234 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002235 state->AS_Data.f_ref);
2236 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002237 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002238 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002239 (u8) (FracN);
2240 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002241 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002242 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002243 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002244 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002245
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002246 /* set the one-shot bit to load the pair of LO values */
2247 tmpOneShot = tempLO2CQ[2] | 0xE0;
2248 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002249 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002250 MT2063_REG_LO2CQ_3,
2251 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002252
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002253 /* only restore the queue values if they were different from the actual. */
2254 if (restore) {
2255 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002256 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002257 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002258 MT2063_REG_LO2CQ_1,
2259 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002260
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002261 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002262 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002263 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002264 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002265 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002266 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002267 tempLO2CQ[2];
2268 }
2269
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002270 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002271 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002272 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002273 }
2274 break;
2275
2276 /* LO1 minimum step size */
2277 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002278 state->AS_Data.f_LO1_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002279 break;
2280
2281 /* LO1 FracN keep-out region */
2282 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002283 state->AS_Data.f_LO1_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002284 break;
2285
2286 /* Requested 1st IF */
2287 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002288 state->AS_Data.f_if1_Request = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002289 break;
2290
2291 /* zero-IF bandwidth */
2292 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002293 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002294 break;
2295
2296 /* LO2 frequency */
2297 case MT2063_LO2_FREQ:
2298 {
2299 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2300 /* Capture the Divider and Numerator portions of other LO */
2301 u8 tempLO1CQ[2];
2302 u8 tempLO1C[2];
2303 u32 Div2;
2304 u32 FracN2;
2305 u8 tmpOneShot;
2306 u8 restore = 0;
2307
2308 /* Buffer the queue for restoration later and get actual LO2 values. */
2309 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002310 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002311 MT2063_REG_LO1CQ_1,
2312 &(tempLO1CQ[0]), 2);
2313 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002314 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002315 MT2063_REG_LO1C_1,
2316 &(tempLO1C[0]), 2);
2317
2318 /* only write the queue values if they are different from the actual. */
2319 if ((tempLO1CQ[0] != tempLO1C[0])
2320 || (tempLO1CQ[1] != tempLO1C[1])) {
2321 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002322 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002323 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002324 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002325 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002326
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002327 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002328 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002329 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002330 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002331 tempLO1C[1];
2332 restore = 1;
2333 }
2334
2335 /* Calculate the Divider and Numberator components of LO2 */
2336 status =
2337 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002338 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002339 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002340 state->AS_Data.f_ref);
2341 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002342 (u8) ((Div2 << 1) |
2343 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002344 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002345 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002346 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002347 (u8) ((FracN2 & 0x0F));
2348 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002349 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002350 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002351 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002352 reg[MT2063_REG_LO1CQ_1], 3);
2353
2354 /* set the one-shot bit to load the LO values */
2355 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002356 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002357 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002358 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002359 MT2063_REG_LO2CQ_3,
2360 &tmpOneShot, 1);
2361
2362 /* only restore LO1 queue value if they were different from the actual. */
2363 if (restore) {
2364 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002365 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002366 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002367 MT2063_REG_LO1CQ_1,
2368 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002369
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002370 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002371 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002372 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002373 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002374 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002375 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002376
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002377 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002378 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002379 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002380 }
2381 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002382
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002383 /* LO2 minimum step size */
2384 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002385 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002386 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002387
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002388 /* LO2 FracN keep-out region */
2389 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002390 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002391 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002392
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002393 /* output center frequency */
2394 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002395 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002396 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002397
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002398 /* output bandwidth */
2399 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002400 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002401 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002402
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002403 /* min inter-tuner LO separation */
2404 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002405 state->AS_Data.f_min_LO_Separation = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002406 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002407
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002408 /* max # of intra-tuner harmonics */
2409 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002410 state->AS_Data.maxH1 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002411 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002412
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002413 /* max # of inter-tuner harmonics */
2414 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002415 state->AS_Data.maxH2 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002416 break;
2417
2418 case MT2063_RCVR_MODE:
2419 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002420 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002421 (enum MT2063_RCVR_MODES)
2422 nValue);
2423 break;
2424
2425 /* Set LNA Rin -- nValue is desired value */
2426 case MT2063_LNA_RIN:
2427 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002428 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002429 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2430 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002431 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002432 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002433 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002434 val);
2435 }
2436 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002437
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002438 /* Set target power level at LNA -- nValue is desired value */
2439 case MT2063_LNA_TGT:
2440 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002441 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002442 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2443 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002444 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002445 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002446 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002447 val);
2448 }
2449 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002450
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002451 /* Set target power level at PD1 -- nValue is desired value */
2452 case MT2063_PD1_TGT:
2453 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002454 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002455 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2456 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002457 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002458 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002459 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002460 val);
2461 }
2462 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002463
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002464 /* Set target power level at PD2 -- nValue is desired value */
2465 case MT2063_PD2_TGT:
2466 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002467 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002468 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2469 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002470 if (state->reg[MT2063_REG_PD2_TGT] != 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_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002473 val);
2474 }
2475 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002476
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002477 /* Set LNA atten limit -- nValue is desired value */
2478 case MT2063_ACLNA_MAX:
2479 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002480 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002481 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2482 &
2483 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002484 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002485 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002486 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002487 val);
2488 }
2489 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002490
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002491 /* Set RF atten limit -- nValue is desired value */
2492 case MT2063_ACRF_MAX:
2493 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002494 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002495 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2496 &
2497 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002498 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002499 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002500 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002501 }
2502 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002503
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002504 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2505 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002506 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002507 && nValue > 5)
2508 nValue = 5;
2509 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002510 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002511 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2512 &
2513 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002514 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002515 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002516 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002517 val);
2518 }
2519 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002520
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002521 case MT2063_DNC_OUTPUT_ENABLE:
2522 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002523 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002524 case MT2063_DNC_NONE:
2525 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002526 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
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);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002533
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);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002541
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);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002549
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002550 break;
2551 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002552 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002553 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002554 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
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);
2561
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002562 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
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);
2569
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002570 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
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;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002579 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002580 case MT2063_DNC_2:
2581 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002582 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
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);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002589
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);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002597
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 }
2608 case MT2063_DNC_BOTH:
2609 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002610 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2611 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002612 val)
2613 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002614 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002615 MT2063_REG_DNC_GAIN,
2616 val);
2617
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002618 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2619 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002620 val)
2621 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002622 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002623 MT2063_REG_VGA_GAIN,
2624 val);
2625
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002626 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2627 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002628 val)
2629 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002630 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002631 MT2063_REG_RSVD_20,
2632 val);
2633
2634 break;
2635 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002636 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002637 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002638 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002639 break;
2640
2641 case MT2063_VGAGC:
2642 /* Set VGA gain code */
2643 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002644 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002645 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
2646 ((nValue & 0x03) << 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002647 if (state->reg[MT2063_REG_VGA_GAIN] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002648 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002649 MT2063_SetReg(state, MT2063_REG_VGA_GAIN,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002650 val);
2651 }
2652 break;
2653
2654 case MT2063_VGAOI:
2655 /* Set VGA bias current */
2656 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002657 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002658 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
2659 (nValue & 0x07);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002660 if (state->reg[MT2063_REG_RSVD_31] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002661 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002662 MT2063_SetReg(state, MT2063_REG_RSVD_31,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002663 val);
2664 }
2665 break;
2666
2667 case MT2063_TAGC:
2668 /* Set TAGC */
2669 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002670 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002671 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
2672 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002673 if (state->reg[MT2063_REG_RSVD_1E] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002674 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002675 MT2063_SetReg(state, MT2063_REG_RSVD_1E,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002676 val);
2677 }
2678 break;
2679
2680 case MT2063_AMPGC:
2681 /* Set Amp gain code */
2682 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002683 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002684 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
2685 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002686 if (state->reg[MT2063_REG_TEMP_SEL] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002687 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002688 MT2063_SetReg(state, MT2063_REG_TEMP_SEL,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002689 val);
2690 }
2691 break;
2692
2693 /* Avoid DECT Frequencies */
2694 case MT2063_AVOID_DECT:
2695 {
2696 enum MT2063_DECT_Avoid_Type newAvoidSetting =
2697 (enum MT2063_DECT_Avoid_Type)nValue;
2698 if ((newAvoidSetting >=
2699 MT2063_NO_DECT_AVOIDANCE)
2700 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002701 state->AS_Data.avoidDECT =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002702 newAvoidSetting;
2703 }
2704 }
2705 break;
2706
2707 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2708 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002709 state->ctfilt_sw = (nValue & 0x01);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002710 break;
2711
2712 /* These parameters are read-only */
2713 case MT2063_IC_ADDR:
2714 case MT2063_MAX_OPEN:
2715 case MT2063_NUM_OPEN:
2716 case MT2063_INPUT_FREQ:
2717 case MT2063_IF1_ACTUAL:
2718 case MT2063_IF1_CENTER:
2719 case MT2063_IF1_BW:
2720 case MT2063_AS_ALG:
2721 case MT2063_EXCL_ZONES:
2722 case MT2063_SPUR_AVOIDED:
2723 case MT2063_NUM_SPURS:
2724 case MT2063_SPUR_PRESENT:
2725 case MT2063_ACLNA:
2726 case MT2063_ACRF:
2727 case MT2063_ACFIF:
2728 case MT2063_EOP:
2729 default:
2730 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002731 }
2732 return (status);
2733}
2734
2735/****************************************************************************
2736**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002737** Name: MT2063_ClearPowerMaskBits
2738**
2739** Description: Clears the power-down mask bits for various sections of
2740** the MT2063
2741**
2742** Parameters: h - Tuner handle (returned by MT2063_Open)
2743** Bits - Mask bits to be cleared.
2744**
2745** See definition of MT2063_Mask_Bits type for description
2746** of each of the power bits.
2747**
2748** Returns: status:
2749** MT_OK - No errors
2750** MT_INV_HANDLE - Invalid tuner handle
2751** MT_COMM_ERR - Serial bus communications error
2752**
2753** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2754**
2755** Revision History:
2756**
2757** SCR Date Author Description
2758** -------------------------------------------------------------------------
2759** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2760**
2761****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002762static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002763{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002764 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002765
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002766 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
2767 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002768 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002769 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002770 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002771 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002772 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002773 }
2774 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002775 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002776 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002777 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002778 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002779 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002780 }
2781
2782 return (status);
2783}
2784
2785/****************************************************************************
2786**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002787** Name: MT2063_SoftwareShutdown
2788**
2789** Description: Enables or disables software shutdown function. When
2790** Shutdown==1, any section whose power mask is set will be
2791** shutdown.
2792**
2793** Parameters: h - Tuner handle (returned by MT2063_Open)
2794** Shutdown - 1 = shutdown the masked sections, otherwise
2795** power all sections on
2796**
2797** Returns: status:
2798** MT_OK - No errors
2799** MT_INV_HANDLE - Invalid tuner handle
2800** MT_COMM_ERR - Serial bus communications error
2801**
2802** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2803**
2804** Revision History:
2805**
2806** SCR Date Author Description
2807** -------------------------------------------------------------------------
2808** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2809** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
2810** correct wakeup of the LNA
2811**
2812****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002813static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002814{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002815 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002816
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002817 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002818 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002819 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002820 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002821
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002822 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002823 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002824 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002825 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002826
2827 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002828 state->reg[MT2063_REG_BYP_CTRL] =
2829 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002830 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002831 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002832 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002833 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002834 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002835 state->reg[MT2063_REG_BYP_CTRL] =
2836 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002837 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002838 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002839 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002840 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002841 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002842 }
2843
2844 return (status);
2845}
2846
2847/****************************************************************************
2848**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002849** Name: MT2063_SetReg
2850**
2851** Description: Sets an MT2063 register.
2852**
2853** Parameters: h - Tuner handle (returned by MT2063_Open)
2854** reg - MT2063 register/subaddress location
2855** val - MT2063 register/subaddress value
2856**
2857** Returns: status:
2858** MT_OK - No errors
2859** MT_COMM_ERR - Serial bus communications error
2860** MT_INV_HANDLE - Invalid tuner handle
2861** MT_ARG_RANGE - Argument out of range
2862**
2863** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2864**
2865** Use this function if you need to override a default
2866** register value
2867**
2868** Revision History:
2869**
2870** SCR Date Author Description
2871** -------------------------------------------------------------------------
2872** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2873**
2874****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002875static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002876{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002877 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002878
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002879 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002880 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002881
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002882 status = mt2063_write(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002883 1);
2884 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002885 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002886
2887 return (status);
2888}
2889
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002890static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002891{
2892 return f_ref * (f_LO / f_ref)
2893 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
2894}
2895
2896/****************************************************************************
2897**
2898** Name: fLO_FractionalTerm
2899**
2900** Description: Calculates the portion contributed by FracN / denom.
2901**
2902** This function preserves maximum precision without
2903** risk of overflow. It accurately calculates
2904** f_ref * num / denom to within 1 HZ with fixed math.
2905**
2906** Parameters: num - Fractional portion of the multiplier
2907** denom - denominator portion of the ratio
2908** This routine successfully handles denom values
2909** up to and including 2^18.
2910** f_Ref - SRO frequency. This calculation handles
2911** f_ref as two separate 14-bit fields.
2912** Therefore, a maximum value of 2^28-1
2913** may safely be used for f_ref. This is
2914** the genesis of the magic number "14" and the
2915** magic mask value of 0x03FFF.
2916**
2917** Returns: f_ref * num / denom
2918**
2919** Revision History:
2920**
2921** SCR Date Author Description
2922** -------------------------------------------------------------------------
2923** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2924**
2925****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002926static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
2927 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002928{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002929 u32 t1 = (f_ref >> 14) * num;
2930 u32 term1 = t1 / denom;
2931 u32 loss = t1 % denom;
2932 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002933 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
2934 return ((term1 << 14) + term2);
2935}
2936
2937/****************************************************************************
2938**
2939** Name: CalcLO1Mult
2940**
2941** Description: Calculates Integer divider value and the numerator
2942** value for a FracN PLL.
2943**
2944** This function assumes that the f_LO and f_Ref are
2945** evenly divisible by f_LO_Step.
2946**
2947** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2948** FracN - OUTPUT: Fractional portion of the multiplier
2949** f_LO - desired LO frequency.
2950** f_LO_Step - Minimum step size for the LO (in Hz).
2951** f_Ref - SRO frequency.
2952** f_Avoid - Range of PLL frequencies to avoid near
2953** integer multiples of f_Ref (in Hz).
2954**
2955** Returns: Recalculated LO frequency.
2956**
2957** Revision History:
2958**
2959** SCR Date Author Description
2960** -------------------------------------------------------------------------
2961** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2962**
2963****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002964static u32 MT2063_CalcLO1Mult(u32 * Div,
2965 u32 * FracN,
2966 u32 f_LO,
2967 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002968{
2969 /* Calculate the whole number portion of the divider */
2970 *Div = f_LO / f_Ref;
2971
2972 /* Calculate the numerator value (round to nearest f_LO_Step) */
2973 *FracN =
2974 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
2975 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
2976
2977 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
2978}
2979
2980/****************************************************************************
2981**
2982** Name: CalcLO2Mult
2983**
2984** Description: Calculates Integer divider value and the numerator
2985** value for a FracN PLL.
2986**
2987** This function assumes that the f_LO and f_Ref are
2988** evenly divisible by f_LO_Step.
2989**
2990** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2991** FracN - OUTPUT: Fractional portion of the multiplier
2992** f_LO - desired LO frequency.
2993** f_LO_Step - Minimum step size for the LO (in Hz).
2994** f_Ref - SRO frequency.
2995** f_Avoid - Range of PLL frequencies to avoid near
2996** integer multiples of f_Ref (in Hz).
2997**
2998** Returns: Recalculated LO frequency.
2999**
3000** Revision History:
3001**
3002** SCR Date Author Description
3003** -------------------------------------------------------------------------
3004** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3005**
3006****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003007static u32 MT2063_CalcLO2Mult(u32 * Div,
3008 u32 * FracN,
3009 u32 f_LO,
3010 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003011{
3012 /* Calculate the whole number portion of the divider */
3013 *Div = f_LO / f_Ref;
3014
3015 /* Calculate the numerator value (round to nearest f_LO_Step) */
3016 *FracN =
3017 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3018 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3019
3020 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
3021 8191);
3022}
3023
3024/****************************************************************************
3025**
3026** Name: FindClearTuneFilter
3027**
3028** Description: Calculate the corrrect ClearTune filter to be used for
3029** a given input frequency.
3030**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003031** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003032** f_in - RF input center frequency (in Hz).
3033**
3034** Returns: ClearTune filter number (0-31)
3035**
3036** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3037**
3038** Revision History:
3039**
3040** SCR Date Author Description
3041** -------------------------------------------------------------------------
3042** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3043** cross-over frequency values.
3044**
3045****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003046static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003047{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003048 u32 RFBand;
3049 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003050
3051 /*
3052 ** Find RF Band setting
3053 */
3054 RFBand = 31; /* def when f_in > all */
3055 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003056 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003057 RFBand = idx;
3058 break;
3059 }
3060 }
3061 return (RFBand);
3062}
3063
3064/****************************************************************************
3065**
3066** Name: MT2063_Tune
3067**
3068** Description: Change the tuner's tuned frequency to RFin.
3069**
3070** Parameters: h - Open handle to the tuner (from MT2063_Open).
3071** f_in - RF input center frequency (in Hz).
3072**
3073** Returns: status:
3074** MT_OK - No errors
3075** MT_INV_HANDLE - Invalid tuner handle
3076** MT_UPC_UNLOCK - Upconverter PLL unlocked
3077** MT_DNC_UNLOCK - Downconverter PLL unlocked
3078** MT_COMM_ERR - Serial bus communications error
3079** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3080** MT_SPUR_PRESENT - LO spur possible in output
3081** MT_FIN_RANGE - Input freq out of range
3082** MT_FOUT_RANGE - Output freq out of range
3083** MT_UPC_RANGE - Upconverter freq out of range
3084** MT_DNC_RANGE - Downconverter freq out of range
3085**
3086** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
3087**
3088** MT_ReadSub - Read data from the two-wire serial bus
3089** MT_WriteSub - Write data to the two-wire serial bus
3090** MT_Sleep - Delay execution for x milliseconds
3091** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
3092**
3093** Revision History:
3094**
3095** SCR Date Author Description
3096** -------------------------------------------------------------------------
3097** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3098** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
3099** cross-over frequency values.
3100** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3101** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3102** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3103**
3104****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003105static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003106{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003107
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003108 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003109 u32 LO1; /* 1st LO register value */
3110 u32 Num1; /* Numerator for LO1 reg. value */
3111 u32 f_IF1; /* 1st IF requested */
3112 u32 LO2; /* 2nd LO register value */
3113 u32 Num2; /* Numerator for LO2 reg. value */
3114 u32 ofLO1, ofLO2; /* last time's LO frequencies */
3115 u32 ofin, ofout; /* last time's I/O frequencies */
3116 u8 fiffc = 0x80; /* FIFF center freq from tuner */
3117 u32 fiffof; /* Offset from FIFF center freq */
3118 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
3119 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
3120 u8 val;
3121 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003122
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003123 /* Check the input and output frequency ranges */
3124 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003125 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003126
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003127 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
3128 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003129 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003130
3131 /*
3132 ** Save original LO1 and LO2 register values
3133 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003134 ofLO1 = state->AS_Data.f_LO1;
3135 ofLO2 = state->AS_Data.f_LO2;
3136 ofin = state->AS_Data.f_in;
3137 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003138
3139 /*
3140 ** Find and set RF Band setting
3141 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003142 if (state->ctfilt_sw == 1) {
3143 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
3144 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003145 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003146 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003147 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003148 val = state->reg[MT2063_REG_CTUNE_OV];
3149 RFBand = FindClearTuneFilter(state, f_in);
3150 state->reg[MT2063_REG_CTUNE_OV] =
3151 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003152 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003153 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003154 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003155 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003156 }
3157 }
3158
3159 /*
3160 ** Read the FIFF Center Frequency from the tuner
3161 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003162 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003163 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003164 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003165 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003166 &state->reg[MT2063_REG_FIFFC], 1);
3167 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003168 }
3169 /*
3170 ** Assign in the requested values
3171 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003172 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003173 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003174 state->AS_Data.f_if1_Request =
3175 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
3176 state->AS_Data.f_LO1_Step,
3177 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003178
3179 /*
3180 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
3181 ** desired LO1 frequency
3182 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003183 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003184
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003185 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003186
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003187 state->AS_Data.f_LO1 =
3188 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
3189 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003190
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003191 state->AS_Data.f_LO2 =
3192 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3193 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003194
3195 /*
3196 ** Check for any LO spurs in the output bandwidth and adjust
3197 ** the LO settings to avoid them if needed
3198 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003199 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003200 /*
3201 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
3202 ** Recalculate the LO frequencies and the values to be placed
3203 ** in the tuning registers.
3204 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003205 state->AS_Data.f_LO1 =
3206 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
3207 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
3208 state->AS_Data.f_LO2 =
3209 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3210 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
3211 state->AS_Data.f_LO2 =
3212 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
3213 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003214
3215 /*
3216 ** Check the upconverter and downconverter frequency ranges
3217 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003218 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
3219 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003220 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003221 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
3222 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003223 status |= MT2063_DNC_RANGE;
3224 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003225 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003226 LO2LK = 0x40;
3227
3228 /*
3229 ** If we have the same LO frequencies and we're already locked,
3230 ** then skip re-programming the LO registers.
3231 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003232 if ((ofLO1 != state->AS_Data.f_LO1)
3233 || (ofLO2 != state->AS_Data.f_LO2)
3234 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003235 (LO1LK | LO2LK))) {
3236 /*
3237 ** Calculate the FIFFOF register value
3238 **
3239 ** IF1_Actual
3240 ** FIFFOF = ------------ - 8 * FIFFC - 4992
3241 ** f_ref/64
3242 */
3243 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003244 (state->AS_Data.f_LO1 -
3245 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003246 4992;
3247 if (fiffof > 0xFF)
3248 fiffof = 0xFF;
3249
3250 /*
3251 ** Place all of the calculated values into the local tuner
3252 ** register fields.
3253 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003254 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003255 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
3256 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
3257 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003258 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003259 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
3260 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003261
3262 /*
3263 ** Now write out the computed register values
3264 ** IMPORTANT: There is a required order for writing
3265 ** (0x05 must follow all the others).
3266 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003267 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 -03003268 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003269 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003270 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003271 }
3272 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003273 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003274 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003275 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003276 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003277 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003278 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003279 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003280 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003281 reg[MT2063_REG_FIFF_OFFSET],
3282 1);
3283 }
3284 }
3285
3286 /*
3287 ** Check for LO's locking
3288 */
3289
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003290 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003291 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003292 }
3293 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003294 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003295 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003296 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003297 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003298 }
3299 }
3300
3301 return (status);
3302}
3303
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003304static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003305 enum MTTune_atv_standard tv_type)
3306{
3307
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003308 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003309
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003310 s32 pict_car = 0;
3311 s32 pict2chanb_vsb = 0;
3312 s32 pict2chanb_snd = 0;
3313 s32 pict2snd1 = 0;
3314 s32 pict2snd2 = 0;
3315 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003316
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003317 s32 if_mid = 0;
3318 s32 rcvr_mode = 0;
3319 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003320
3321 switch (tv_type) {
3322 case MTTUNEA_PAL_B:{
3323 pict_car = 38900000;
3324 ch_bw = 8000000;
3325 pict2chanb_vsb = -1250000;
3326 pict2snd1 = 5500000;
3327 pict2snd2 = 5742000;
3328 rcvr_mode = 1;
3329 break;
3330 }
3331 case MTTUNEA_PAL_G:{
3332 pict_car = 38900000;
3333 ch_bw = 7000000;
3334 pict2chanb_vsb = -1250000;
3335 pict2snd1 = 5500000;
3336 pict2snd2 = 0;
3337 rcvr_mode = 1;
3338 break;
3339 }
3340 case MTTUNEA_PAL_I:{
3341 pict_car = 38900000;
3342 ch_bw = 8000000;
3343 pict2chanb_vsb = -1250000;
3344 pict2snd1 = 6000000;
3345 pict2snd2 = 0;
3346 rcvr_mode = 1;
3347 break;
3348 }
3349 case MTTUNEA_PAL_L:{
3350 pict_car = 38900000;
3351 ch_bw = 8000000;
3352 pict2chanb_vsb = -1250000;
3353 pict2snd1 = 6500000;
3354 pict2snd2 = 0;
3355 rcvr_mode = 1;
3356 break;
3357 }
3358 case MTTUNEA_PAL_MN:{
3359 pict_car = 38900000;
3360 ch_bw = 6000000;
3361 pict2chanb_vsb = -1250000;
3362 pict2snd1 = 4500000;
3363 pict2snd2 = 0;
3364 rcvr_mode = 1;
3365 break;
3366 }
3367 case MTTUNEA_PAL_DK:{
3368 pict_car = 38900000;
3369 ch_bw = 8000000;
3370 pict2chanb_vsb = -1250000;
3371 pict2snd1 = 6500000;
3372 pict2snd2 = 0;
3373 rcvr_mode = 1;
3374 break;
3375 }
3376 case MTTUNEA_DIGITAL:{
3377 pict_car = 36125000;
3378 ch_bw = 8000000;
3379 pict2chanb_vsb = -(ch_bw / 2);
3380 pict2snd1 = 0;
3381 pict2snd2 = 0;
3382 rcvr_mode = 2;
3383 break;
3384 }
3385 case MTTUNEA_FMRADIO:{
3386 pict_car = 38900000;
3387 ch_bw = 8000000;
3388 pict2chanb_vsb = -(ch_bw / 2);
3389 pict2snd1 = 0;
3390 pict2snd2 = 0;
3391 rcvr_mode = 4;
3392 //f_in -= 2900000;
3393 break;
3394 }
3395 case MTTUNEA_DVBC:{
3396 pict_car = 36125000;
3397 ch_bw = 8000000;
3398 pict2chanb_vsb = -(ch_bw / 2);
3399 pict2snd1 = 0;
3400 pict2snd2 = 0;
3401 rcvr_mode = MT2063_CABLE_QAM;
3402 break;
3403 }
3404 case MTTUNEA_DVBT:{
3405 pict_car = 36125000;
3406 ch_bw = bw_in; //8000000
3407 pict2chanb_vsb = -(ch_bw / 2);
3408 pict2snd1 = 0;
3409 pict2snd2 = 0;
3410 rcvr_mode = MT2063_OFFAIR_COFDM;
3411 break;
3412 }
3413 case MTTUNEA_UNKNOWN:
3414 break;
3415 default:
3416 break;
3417 }
3418
3419 pict2chanb_snd = pict2chanb_vsb - ch_bw;
3420 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
3421
3422 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
3423 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
3424 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
3425 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3426
3427 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
3428 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
3429 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3430
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003431 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003432}
3433
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003434static const u8 MT2063B0_defaults[] = {
3435 /* Reg, Value */
3436 0x19, 0x05,
3437 0x1B, 0x1D,
3438 0x1C, 0x1F,
3439 0x1D, 0x0F,
3440 0x1E, 0x3F,
3441 0x1F, 0x0F,
3442 0x20, 0x3F,
3443 0x22, 0x21,
3444 0x23, 0x3F,
3445 0x24, 0x20,
3446 0x25, 0x3F,
3447 0x27, 0xEE,
3448 0x2C, 0x27, /* bit at 0x20 is cleared below */
3449 0x30, 0x03,
3450 0x2C, 0x07, /* bit at 0x20 is cleared here */
3451 0x2D, 0x87,
3452 0x2E, 0xAA,
3453 0x28, 0xE1, /* Set the FIFCrst bit here */
3454 0x28, 0xE0, /* Clear the FIFCrst bit here */
3455 0x00
3456};
3457
3458/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3459static const u8 MT2063B1_defaults[] = {
3460 /* Reg, Value */
3461 0x05, 0xF0,
3462 0x11, 0x10, /* New Enable AFCsd */
3463 0x19, 0x05,
3464 0x1A, 0x6C,
3465 0x1B, 0x24,
3466 0x1C, 0x28,
3467 0x1D, 0x8F,
3468 0x1E, 0x14,
3469 0x1F, 0x8F,
3470 0x20, 0x57,
3471 0x22, 0x21, /* New - ver 1.03 */
3472 0x23, 0x3C, /* New - ver 1.10 */
3473 0x24, 0x20, /* New - ver 1.03 */
3474 0x2C, 0x24, /* bit at 0x20 is cleared below */
3475 0x2D, 0x87, /* FIFFQ=0 */
3476 0x2F, 0xF3,
3477 0x30, 0x0C, /* New - ver 1.11 */
3478 0x31, 0x1B, /* New - ver 1.11 */
3479 0x2C, 0x04, /* bit at 0x20 is cleared here */
3480 0x28, 0xE1, /* Set the FIFCrst bit here */
3481 0x28, 0xE0, /* Clear the FIFCrst bit here */
3482 0x00
3483};
3484
3485/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3486static const u8 MT2063B3_defaults[] = {
3487 /* Reg, Value */
3488 0x05, 0xF0,
3489 0x19, 0x3D,
3490 0x2C, 0x24, /* bit at 0x20 is cleared below */
3491 0x2C, 0x04, /* bit at 0x20 is cleared here */
3492 0x28, 0xE1, /* Set the FIFCrst bit here */
3493 0x28, 0xE0, /* Clear the FIFCrst bit here */
3494 0x00
3495};
3496
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003497static int mt2063_init(struct dvb_frontend *fe)
3498{
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003499 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003500 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003501 u8 all_resets = 0xF0; /* reset/load bits */
3502 const u8 *def = NULL;
3503 u32 FCRUN;
3504 s32 maxReads;
3505 u32 fcu_osc;
3506 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003507
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003508 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003509
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003510 /* Read the Part/Rev code from the tuner */
3511 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
3512 if (status < 0)
3513 return status;
3514
3515 /* Check the part/rev code */
3516 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
3517 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
3518 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
3519 return -ENODEV; /* Wrong tuner Part/Rev code */
3520
3521 /* Check the 2nd byte of the Part/Rev code from the tuner */
3522 status = mt2063_read(state, MT2063_REG_RSVD_3B,
3523 &state->reg[MT2063_REG_RSVD_3B], 1);
3524
3525 /* b7 != 0 ==> NOT MT2063 */
3526 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
3527 return -ENODEV; /* Wrong tuner Part/Rev code */
3528
3529 /* Reset the tuner */
3530 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
3531 if (status < 0)
3532 return status;
3533
3534 /* change all of the default values that vary from the HW reset values */
3535 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
3536 switch (state->reg[MT2063_REG_PART_REV]) {
3537 case MT2063_B3:
3538 def = MT2063B3_defaults;
3539 break;
3540
3541 case MT2063_B1:
3542 def = MT2063B1_defaults;
3543 break;
3544
3545 case MT2063_B0:
3546 def = MT2063B0_defaults;
3547 break;
3548
3549 default:
3550 return -ENODEV;
3551 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003552 }
3553
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003554 while (status >= 0 && *def) {
3555 u8 reg = *def++;
3556 u8 val = *def++;
3557 status = mt2063_write(state, reg, &val, 1);
3558 }
3559 if (status < 0)
3560 return status;
3561
3562 /* Wait for FIFF location to complete. */
3563 FCRUN = 1;
3564 maxReads = 10;
3565 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3566 msleep(2);
3567 status = mt2063_read(state,
3568 MT2063_REG_XO_STATUS,
3569 &state->
3570 reg[MT2063_REG_XO_STATUS], 1);
3571 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
3572 }
3573
3574 if (FCRUN != 0 || status < 0)
3575 return -ENODEV;
3576
3577 status = mt2063_read(state,
3578 MT2063_REG_FIFFC,
3579 &state->reg[MT2063_REG_FIFFC], 1);
3580 if (status < 0)
3581 return status;
3582
3583 /* Read back all the registers from the tuner */
3584 status = mt2063_read(state,
3585 MT2063_REG_PART_REV,
3586 state->reg, MT2063_REG_END_REGS);
3587 if (status < 0)
3588 return status;
3589
3590 /* Initialize the tuner state. */
3591 state->tuner_id = state->reg[MT2063_REG_PART_REV];
3592 state->AS_Data.f_ref = MT2063_REF_FREQ;
3593 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
3594 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
3595 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
3596 state->AS_Data.f_out = 43750000UL;
3597 state->AS_Data.f_out_bw = 6750000UL;
3598 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3599 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
3600 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3601 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3602 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3603 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3604 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
3605 state->AS_Data.f_LO1 = 2181000000UL;
3606 state->AS_Data.f_LO2 = 1486249786UL;
3607 state->f_IF1_actual = state->AS_Data.f_if1_Center;
3608 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
3609 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3610 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3611 state->num_regs = MT2063_REG_END_REGS;
3612 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3613 state->ctfilt_sw = 0;
3614
3615 state->CTFiltMax[0] = 69230000;
3616 state->CTFiltMax[1] = 105770000;
3617 state->CTFiltMax[2] = 140350000;
3618 state->CTFiltMax[3] = 177110000;
3619 state->CTFiltMax[4] = 212860000;
3620 state->CTFiltMax[5] = 241130000;
3621 state->CTFiltMax[6] = 274370000;
3622 state->CTFiltMax[7] = 309820000;
3623 state->CTFiltMax[8] = 342450000;
3624 state->CTFiltMax[9] = 378870000;
3625 state->CTFiltMax[10] = 416210000;
3626 state->CTFiltMax[11] = 456500000;
3627 state->CTFiltMax[12] = 495790000;
3628 state->CTFiltMax[13] = 534530000;
3629 state->CTFiltMax[14] = 572610000;
3630 state->CTFiltMax[15] = 598970000;
3631 state->CTFiltMax[16] = 635910000;
3632 state->CTFiltMax[17] = 672130000;
3633 state->CTFiltMax[18] = 714840000;
3634 state->CTFiltMax[19] = 739660000;
3635 state->CTFiltMax[20] = 770410000;
3636 state->CTFiltMax[21] = 814660000;
3637 state->CTFiltMax[22] = 846950000;
3638 state->CTFiltMax[23] = 867820000;
3639 state->CTFiltMax[24] = 915980000;
3640 state->CTFiltMax[25] = 947450000;
3641 state->CTFiltMax[26] = 983110000;
3642 state->CTFiltMax[27] = 1021630000;
3643 state->CTFiltMax[28] = 1061870000;
3644 state->CTFiltMax[29] = 1098330000;
3645 state->CTFiltMax[30] = 1138990000;
3646
3647 /*
3648 ** Fetch the FCU osc value and use it and the fRef value to
3649 ** scale all of the Band Max values
3650 */
3651
3652 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3653 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3654 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3655 if (status < 0)
3656 return status;
3657
3658 /* Read the ClearTune filter calibration value */
3659 status = mt2063_read(state, MT2063_REG_FIFFC,
3660 &state->reg[MT2063_REG_FIFFC], 1);
3661 if (status < 0)
3662 return status;
3663
3664 fcu_osc = state->reg[MT2063_REG_FIFFC];
3665
3666 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3667 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3668 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3669 if (status < 0)
3670 return status;
3671
3672 /* Adjust each of the values in the ClearTune filter cross-over table */
3673 for (i = 0; i < 31; i++)
3674 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
3675
3676 status = MT2063_SoftwareShutdown(state, 1);
3677 if (status < 0)
3678 return status;
3679 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
3680 if (status < 0)
3681 return status;
3682
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003683 return 0;
3684}
3685
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003686static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3687{
3688 int rc = 0;
3689
3690 //get tuner lock status
3691
3692 return rc;
3693}
3694
3695static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003696 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003697{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003698 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003699
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003700 switch (param) {
3701 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003702 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003703 break;
3704 case DVBFE_TUNER_TUNERSTEP:
3705 break;
3706 case DVBFE_TUNER_IFFREQ:
3707 break;
3708 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003709 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003710 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003711 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003712 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003713 break;
3714 default:
3715 break;
3716 }
3717
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003718 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003719}
3720
3721static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003722 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003723{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003724 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003725 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003726
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003727 switch (param) {
3728 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003729 //set frequency
3730
3731 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003732 MT_Tune_atv(state,
3733 tunstate->frequency, tunstate->bandwidth,
3734 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003735
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003736 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003737 break;
3738 case DVBFE_TUNER_TUNERSTEP:
3739 break;
3740 case DVBFE_TUNER_IFFREQ:
3741 break;
3742 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003743 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003744 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003745 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003746 case DVBFE_TUNER_REFCLOCK:
3747
3748 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003749 default:
3750 break;
3751 }
3752
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003753 return (int)status;
3754}
3755
3756static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003757{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003758 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003759
3760 fe->tuner_priv = NULL;
3761 kfree(state);
3762
3763 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003764}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003765
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003766static struct dvb_tuner_ops mt2063_ops = {
3767 .info = {
3768 .name = "MT2063 Silicon Tuner",
3769 .frequency_min = 45000000,
3770 .frequency_max = 850000000,
3771 .frequency_step = 0,
3772 },
3773
3774 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003775 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003776 .get_status = mt2063_get_status,
3777 .get_state = mt2063_get_state,
3778 .set_state = mt2063_set_state,
3779 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003780};
3781
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003782struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3783 struct mt2063_config *config,
3784 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003785{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003786 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003787
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003788 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003789 if (state == NULL)
3790 goto error;
3791
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003792 state->config = config;
3793 state->i2c = i2c;
3794 state->frontend = fe;
3795 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003796 fe->tuner_priv = state;
3797 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003798
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003799 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003800 return fe;
3801
3802error:
3803 kfree(state);
3804 return NULL;
3805}
3806
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003807EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003808MODULE_PARM_DESC(verbose, "Set Verbosity level");
3809
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003810MODULE_AUTHOR("Henry");
3811MODULE_DESCRIPTION("MT2063 Silicon tuner");
3812MODULE_LICENSE("GPL");