blob: a1acfcc26bd0774ada6b2f55f5f30f49098042ac [file] [log] [blame]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03002#include <linux/init.h>
3#include <linux/kernel.h>
4#include <linux/module.h>
5#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03007#include "mt2063.h"
8
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03009static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -030010module_param(verbose, int, 0644);
11
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030012/* Internal structures and types */
13
Mauro Carvalho Chehab065719a2011-07-20 22:45:06 -030014/* FIXME: we probably don't need these new FE get/set property types for tuner */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030015#define DVBFE_TUNER_OPEN 99
16#define DVBFE_TUNER_SOFTWARE_SHUTDOWN 100
17#define DVBFE_TUNER_CLEAR_POWER_MASKBITS 101
18
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030019/* FIXME: Those error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030020/* Error: Upconverter PLL is not locked */
21#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030022/* Error: Downconverter PLL is not locked */
23#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030024/* Info: Unavoidable LO-related spur may be present in the output */
25#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026
27/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
28#define MT2063_SPUR_CNT_MASK (0x001f0000)
29#define MT2063_SPUR_SHIFT (16)
30
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030031
32/* Info: Tuner input frequency is out of range */
33#define MT2063_FIN_RANGE (0x01000000)
34
35/* Info: Tuner output frequency is out of range */
36#define MT2063_FOUT_RANGE (0x02000000)
37
38/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
39#define MT2063_UPC_RANGE (0x04000000)
40
41/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
42#define MT2063_DNC_RANGE (0x08000000)
43
44/*
45 * Data Types
46 */
47
48#define MAX_UDATA (4294967295) /* max value storable in u32 */
49
50/*
51 * Define an MTxxxx_CNT macro for each type of tuner that will be built
52 * into your application (e.g., MT2121, MT2060). MT_TUNER_CNT
53 * must be set to the SUM of all of the MTxxxx_CNT macros.
54 *
55 * #define MT2050_CNT (1)
56 * #define MT2060_CNT (1)
57 * #define MT2111_CNT (1)
58 * #define MT2121_CNT (3)
59 */
60
61
62#define MT2063_TUNER_CNT (1) /* total num of MicroTuner tuners */
63#define MT2063_I2C (0xC0)
64
65/*
66 * Constant defining the version of the following structure
67 * and therefore the API for this code.
68 *
69 * When compiling the tuner driver, the preprocessor will
70 * check against this version number to make sure that
71 * it matches the version that the tuner driver knows about.
72 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030073
74/* DECT Frequency Avoidance */
75#define MT2063_DECT_AVOID_US_FREQS 0x00000001
76
77#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
78
79#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
80
81#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
82
83enum MT2063_DECT_Avoid_Type {
84 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
85 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
86 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
87 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
88};
89
90#define MT2063_MAX_ZONES 48
91
92struct MT2063_ExclZone_t;
93
94struct MT2063_ExclZone_t {
95 u32 min_;
96 u32 max_;
97 struct MT2063_ExclZone_t *next_;
98};
99
100/*
101 * Structure of data needed for Spur Avoidance
102 */
103struct MT2063_AvoidSpursData_t {
104 u32 nAS_Algorithm;
105 u32 f_ref;
106 u32 f_in;
107 u32 f_LO1;
108 u32 f_if1_Center;
109 u32 f_if1_Request;
110 u32 f_if1_bw;
111 u32 f_LO2;
112 u32 f_out;
113 u32 f_out_bw;
114 u32 f_LO1_Step;
115 u32 f_LO2_Step;
116 u32 f_LO1_FracN_Avoid;
117 u32 f_LO2_FracN_Avoid;
118 u32 f_zif_bw;
119 u32 f_min_LO_Separation;
120 u32 maxH1;
121 u32 maxH2;
122 enum MT2063_DECT_Avoid_Type avoidDECT;
123 u32 bSpurPresent;
124 u32 bSpurAvoided;
125 u32 nSpursFound;
126 u32 nZones;
127 struct MT2063_ExclZone_t *freeZones;
128 struct MT2063_ExclZone_t *usedZones;
129 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
130};
131
132/*
133 * Values returned by the MT2063's on-chip temperature sensor
134 * to be read/written.
135 */
136enum MT2063_Temperature {
137 MT2063_T_0C = 0, /* Temperature approx 0C */
138 MT2063_T_10C, /* Temperature approx 10C */
139 MT2063_T_20C, /* Temperature approx 20C */
140 MT2063_T_30C, /* Temperature approx 30C */
141 MT2063_T_40C, /* Temperature approx 40C */
142 MT2063_T_50C, /* Temperature approx 50C */
143 MT2063_T_60C, /* Temperature approx 60C */
144 MT2063_T_70C, /* Temperature approx 70C */
145 MT2063_T_80C, /* Temperature approx 80C */
146 MT2063_T_90C, /* Temperature approx 90C */
147 MT2063_T_100C, /* Temperature approx 100C */
148 MT2063_T_110C, /* Temperature approx 110C */
149 MT2063_T_120C, /* Temperature approx 120C */
150 MT2063_T_130C, /* Temperature approx 130C */
151 MT2063_T_140C, /* Temperature approx 140C */
152 MT2063_T_150C, /* Temperature approx 150C */
153};
154
155/*
156 * Parameters for selecting GPIO bits
157 */
158enum MT2063_GPIO_Attr {
159 MT2063_GPIO_IN,
160 MT2063_GPIO_DIR,
161 MT2063_GPIO_OUT,
162};
163
164enum MT2063_GPIO_ID {
165 MT2063_GPIO0,
166 MT2063_GPIO1,
167 MT2063_GPIO2,
168};
169
170/*
171 * Parameter for function MT2063_SetExtSRO that specifies the external
172 * SRO drive frequency.
173 *
174 * MT2063_EXT_SRO_OFF is the power-up default value.
175 */
176enum MT2063_Ext_SRO {
177 MT2063_EXT_SRO_OFF, /* External SRO drive off */
178 MT2063_EXT_SRO_BY_4, /* External SRO drive divide by 4 */
179 MT2063_EXT_SRO_BY_2, /* External SRO drive divide by 2 */
180 MT2063_EXT_SRO_BY_1 /* External SRO drive divide by 1 */
181};
182
183/*
184 * Parameter for function MT2063_SetPowerMask that specifies the power down
185 * of various sections of the MT2063.
186 */
187enum MT2063_Mask_Bits {
188 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
189 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
190 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
191 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
192 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
193 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
194 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
195 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
196 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
197 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
198 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
199 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
200 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
201 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
202 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
203};
204
205/*
206 * Parameter for function MT2063_GetParam & MT2063_SetParam that
207 * specifies the tuning algorithm parameter to be read/written.
208 */
209enum MT2063_Param {
210 /* tuner address set by MT2063_Open() */
211 MT2063_IC_ADDR,
212
213 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
214 MT2063_MAX_OPEN,
215
216 /* current number of open MT2063 tuners set by MT2063_Open() */
217 MT2063_NUM_OPEN,
218
219 /* crystal frequency (default: 16000000 Hz) */
220 MT2063_SRO_FREQ,
221
222 /* min tuning step size (default: 50000 Hz) */
223 MT2063_STEPSIZE,
224
225 /* input center frequency set by MT2063_Tune() */
226 MT2063_INPUT_FREQ,
227
228 /* LO1 Frequency set by MT2063_Tune() */
229 MT2063_LO1_FREQ,
230
231 /* LO1 minimum step size (default: 250000 Hz) */
232 MT2063_LO1_STEPSIZE,
233
234 /* LO1 FracN keep-out region (default: 999999 Hz) */
235 MT2063_LO1_FRACN_AVOID_PARAM,
236
237 /* Current 1st IF in use set by MT2063_Tune() */
238 MT2063_IF1_ACTUAL,
239
240 /* Requested 1st IF set by MT2063_Tune() */
241 MT2063_IF1_REQUEST,
242
243 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
244 MT2063_IF1_CENTER,
245
246 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
247 MT2063_IF1_BW,
248
249 /* zero-IF bandwidth (default: 2000000 Hz) */
250 MT2063_ZIF_BW,
251
252 /* LO2 Frequency set by MT2063_Tune() */
253 MT2063_LO2_FREQ,
254
255 /* LO2 minimum step size (default: 50000 Hz) */
256 MT2063_LO2_STEPSIZE,
257
258 /* LO2 FracN keep-out region (default: 374999 Hz) */
259 MT2063_LO2_FRACN_AVOID,
260
261 /* output center frequency set by MT2063_Tune() */
262 MT2063_OUTPUT_FREQ,
263
264 /* output bandwidth set by MT2063_Tune() */
265 MT2063_OUTPUT_BW,
266
267 /* min inter-tuner LO separation (default: 1000000 Hz) */
268 MT2063_LO_SEPARATION,
269
270 /* ID of avoid-spurs algorithm in use compile-time constant */
271 MT2063_AS_ALG,
272
273 /* max # of intra-tuner harmonics (default: 15) */
274 MT2063_MAX_HARM1,
275
276 /* max # of inter-tuner harmonics (default: 7) */
277 MT2063_MAX_HARM2,
278
279 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
280 MT2063_EXCL_ZONES,
281
282 /* # of spurs found/avoided set by MT2063_Tune() */
283 MT2063_NUM_SPURS,
284
285 /* >0 spurs avoided set by MT2063_Tune() */
286 MT2063_SPUR_AVOIDED,
287
288 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
289 MT2063_SPUR_PRESENT,
290
291 /* Receiver Mode for some parameters. 1 is DVB-T */
292 MT2063_RCVR_MODE,
293
294 /* directly set LNA attenuation, parameter is value to set */
295 MT2063_ACLNA,
296
297 /* maximum LNA attenuation, parameter is value to set */
298 MT2063_ACLNA_MAX,
299
300 /* directly set ATN attenuation. Paremeter is value to set. */
301 MT2063_ACRF,
302
303 /* maxium ATN attenuation. Paremeter is value to set. */
304 MT2063_ACRF_MAX,
305
306 /* directly set FIF attenuation. Paremeter is value to set. */
307 MT2063_ACFIF,
308
309 /* maxium FIF attenuation. Paremeter is value to set. */
310 MT2063_ACFIF_MAX,
311
312 /* LNA Rin */
313 MT2063_LNA_RIN,
314
315 /* Power Detector LNA level target */
316 MT2063_LNA_TGT,
317
318 /* Power Detector 1 level */
319 MT2063_PD1,
320
321 /* Power Detector 1 level target */
322 MT2063_PD1_TGT,
323
324 /* Power Detector 2 level */
325 MT2063_PD2,
326
327 /* Power Detector 2 level target */
328 MT2063_PD2_TGT,
329
330 /* Selects, which DNC is activ */
331 MT2063_DNC_OUTPUT_ENABLE,
332
333 /* VGA gain code */
334 MT2063_VGAGC,
335
336 /* VGA bias current */
337 MT2063_VGAOI,
338
339 /* TAGC, determins the speed of the AGC */
340 MT2063_TAGC,
341
342 /* AMP gain code */
343 MT2063_AMPGC,
344
345 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
346 MT2063_AVOID_DECT,
347
348 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
349 MT2063_CTFILT_SW,
350
351 MT2063_EOP /* last entry in enumerated list */
352};
353
354/*
355 * Parameter for selecting tuner mode
356 */
357enum MT2063_RCVR_MODES {
358 MT2063_CABLE_QAM = 0, /* Digital cable */
359 MT2063_CABLE_ANALOG, /* Analog cable */
360 MT2063_OFFAIR_COFDM, /* Digital offair */
361 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
362 MT2063_OFFAIR_ANALOG, /* Analog offair */
363 MT2063_OFFAIR_8VSB, /* Analog offair */
364 MT2063_NUM_RCVR_MODES
365};
366
367/*
368 * Possible values for MT2063_DNC_OUTPUT
369 */
370enum MT2063_DNC_Output_Enable {
371 MT2063_DNC_NONE = 0,
372 MT2063_DNC_1,
373 MT2063_DNC_2,
374 MT2063_DNC_BOTH
375};
376
377/*
378** Two-wire serial bus subaddresses of the tuner registers.
379** Also known as the tuner's register addresses.
380*/
381enum MT2063_Register_Offsets {
382 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
383 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
384 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
385 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
386 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
387 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
388 MT2063_REG_RSVD_06, /* 0x06: Reserved */
389 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
390 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
391 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
392 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
393 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
394 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
395 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
396 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
397 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
398 MT2063_REG_RSVD_10, /* 0x10: Reserved */
399 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
400 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
401 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
402 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
403 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
404 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
405 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
406 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
407 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
408 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
409 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
410 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
411 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
412 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
413 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
414 MT2063_REG_RSVD_20, /* 0x20: Reserved */
415 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
416 MT2063_REG_RSVD_22, /* 0x22: Reserved */
417 MT2063_REG_RSVD_23, /* 0x23: Reserved */
418 MT2063_REG_RSVD_24, /* 0x24: Reserved */
419 MT2063_REG_RSVD_25, /* 0x25: Reserved */
420 MT2063_REG_RSVD_26, /* 0x26: Reserved */
421 MT2063_REG_RSVD_27, /* 0x27: Reserved */
422 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
423 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
424 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
425 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
426 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
427 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
428 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
429 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
430 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
431 MT2063_REG_RSVD_31, /* 0x31: Reserved */
432 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
433 MT2063_REG_RSVD_33, /* 0x33: Reserved */
434 MT2063_REG_RSVD_34, /* 0x34: Reserved */
435 MT2063_REG_RSVD_35, /* 0x35: Reserved */
436 MT2063_REG_RSVD_36, /* 0x36: Reserved */
437 MT2063_REG_RSVD_37, /* 0x37: Reserved */
438 MT2063_REG_RSVD_38, /* 0x38: Reserved */
439 MT2063_REG_RSVD_39, /* 0x39: Reserved */
440 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
441 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
442 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
443 MT2063_REG_END_REGS
444};
445
446struct MT2063_Info_t {
447 void *handle;
448 void *hUserData;
449 u32 address;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300450 u32 tuner_id;
451 struct MT2063_AvoidSpursData_t AS_Data;
452 u32 f_IF1_actual;
453 u32 rcvr_mode;
454 u32 ctfilt_sw;
455 u32 CTFiltMax[31];
456 u32 num_regs;
457 u8 reg[MT2063_REG_END_REGS];
458};
459typedef struct MT2063_Info_t *pMT2063_Info_t;
460
461enum MTTune_atv_standard {
462 MTTUNEA_UNKNOWN = 0,
463 MTTUNEA_PAL_B,
464 MTTUNEA_PAL_G,
465 MTTUNEA_PAL_I,
466 MTTUNEA_PAL_L,
467 MTTUNEA_PAL_MN,
468 MTTUNEA_PAL_DK,
469 MTTUNEA_DIGITAL,
470 MTTUNEA_FMRADIO,
471 MTTUNEA_DVBC,
472 MTTUNEA_DVBT
473};
474
475
476struct mt2063_state {
477 struct i2c_adapter *i2c;
478
479 const struct mt2063_config *config;
480 struct dvb_tuner_ops ops;
481 struct dvb_frontend *frontend;
482 struct tuner_state status;
483 struct MT2063_Info_t *MT2063_ht;
484 bool MT2063_init;
485
486 enum MTTune_atv_standard tv_type;
487 u32 frequency;
488 u32 srate;
489 u32 bandwidth;
490 u32 reference;
491};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300492
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300493/* Prototypes */
494static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
495 u32 f_min, u32 f_max);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300496static u32 MT2063_ReInit(struct MT2063_Info_t *pInfo);
497static u32 MT2063_Close(struct MT2063_Info_t *pInfo);
498static u32 MT2063_GetReg(struct MT2063_Info_t *pInfo, u8 reg, u8 * val);
499static u32 MT2063_GetParam(struct MT2063_Info_t *pInfo, enum MT2063_Param param, u32 * pValue);
500static u32 MT2063_SetReg(struct MT2063_Info_t *pInfo, u8 reg, u8 val);
501static u32 MT2063_SetParam(struct MT2063_Info_t *pInfo, enum MT2063_Param param, u32 nValue);
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300502
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300503/*****************/
504/* From drivers/media/common/tuners/mt2063_cfg.h */
505
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300506unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300507 u32 bw_in,
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300508 enum MTTune_atv_standard tv_type)
509{
510 //return (int)MT_Tune_atv(h, f_in, bw_in, tv_type);
511
512 struct dvb_frontend_ops *frontend_ops = NULL;
513 struct dvb_tuner_ops *tuner_ops = NULL;
514 struct tuner_state t_state;
515 struct mt2063_state *mt2063State = fe->tuner_priv;
516 int err = 0;
517
518 t_state.frequency = f_in;
519 t_state.bandwidth = bw_in;
520 mt2063State->tv_type = tv_type;
521 if (&fe->ops)
522 frontend_ops = &fe->ops;
523 if (&frontend_ops->tuner_ops)
524 tuner_ops = &frontend_ops->tuner_ops;
525 if (tuner_ops->set_state) {
526 if ((err =
527 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
528 &t_state)) < 0) {
529 printk("%s: Invalid parameter\n", __func__);
530 return err;
531 }
532 }
533
534 return err;
535}
536
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300537unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300538{
539 struct dvb_frontend_ops *frontend_ops = &fe->ops;
540 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
541 struct tuner_state t_state;
542 int err = 0;
543
544 if (&fe->ops)
545 frontend_ops = &fe->ops;
546 if (&frontend_ops->tuner_ops)
547 tuner_ops = &frontend_ops->tuner_ops;
548 if (tuner_ops->get_state) {
549 if ((err =
550 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
551 &t_state)) < 0) {
552 printk("%s: Invalid parameter\n", __func__);
553 return err;
554 }
555 }
556 return err;
557}
558
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300559unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300560{
561 struct dvb_frontend_ops *frontend_ops = &fe->ops;
562 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
563 struct tuner_state t_state;
564 int err = 0;
565
566 if (&fe->ops)
567 frontend_ops = &fe->ops;
568 if (&frontend_ops->tuner_ops)
569 tuner_ops = &frontend_ops->tuner_ops;
570 if (tuner_ops->set_state) {
571 if ((err =
572 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
573 &t_state)) < 0) {
574 printk("%s: Invalid parameter\n", __func__);
575 return err;
576 }
577 }
578
579 return err;
580}
581
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300582unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300583{
584 struct dvb_frontend_ops *frontend_ops = &fe->ops;
585 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
586 struct tuner_state t_state;
587 int err = 0;
588
589 if (&fe->ops)
590 frontend_ops = &fe->ops;
591 if (&frontend_ops->tuner_ops)
592 tuner_ops = &frontend_ops->tuner_ops;
593 if (tuner_ops->set_state) {
594 if ((err =
595 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
596 &t_state)) < 0) {
597 printk("%s: Invalid parameter\n", __func__);
598 return err;
599 }
600 }
601
602 return err;
603}
604
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300605unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300606{
607 struct dvb_frontend_ops *frontend_ops = &fe->ops;
608 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
609 struct tuner_state t_state;
610 int err = 0;
611
612 if (&fe->ops)
613 frontend_ops = &fe->ops;
614 if (&frontend_ops->tuner_ops)
615 tuner_ops = &frontend_ops->tuner_ops;
616 if (tuner_ops->set_state) {
617 if ((err =
618 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
619 &t_state)) < 0) {
620 printk("%s: Invalid parameter\n", __func__);
621 return err;
622 }
623 }
624
625 return err;
626}
627
628/*****************/
629
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300630//i2c operation
631static int mt2063_writeregs(struct mt2063_state *state, u8 reg1,
632 u8 * data, int len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300633{
634 int ret;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300635 u8 buf[60]; /* = { reg1, data }; */
636
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300637 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300638 .addr = state->config->tuner_address,
639 .flags = 0,
640 .buf = buf,
641 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300642 };
643
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300644 msg.buf[0] = reg1;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300645 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300646
647 //printk("mt2063_writeregs state->i2c=%p\n", state->i2c);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300648 ret = i2c_transfer(state->i2c, &msg, 1);
649
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300650 if (ret < 0)
651 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300652
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300653 return ret;
654}
655
656static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 * b, u8 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300657{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300658 int ret;
659 u8 b0[] = { reg1 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300660 struct i2c_msg msg[] = {
661 {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300662 .addr = state->config->tuner_address,
663 .flags = I2C_M_RD,
664 .buf = b0,
665 .len = 1}, {
666 .addr = state->config->tuner_address,
667 .flags = I2C_M_RD,
668 .buf = b,
669 .len = len}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300670 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300671
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300672 //printk("mt2063_read_regs state->i2c=%p\n", state->i2c);
673 ret = i2c_transfer(state->i2c, msg, 2);
674 if (ret < 0)
675 printk("mt2063_readregs error ret=%d\n", ret);
676
677 return ret;
678}
679
680//context of mt2063_userdef.c <Henry> ======================================
681//#################################################################
682//=================================================================
683/*****************************************************************************
684**
685** Name: MT_WriteSub
686**
687** Description: Write values to device using a two-wire serial bus.
688**
689** Parameters: hUserData - User-specific I/O parameter that was
690** passed to tuner's Open function.
691** addr - device serial bus address (value passed
692** as parameter to MTxxxx_Open)
693** subAddress - serial bus sub-address (Register Address)
694** pData - pointer to the Data to be written to the
695** device
696** cnt - number of bytes/registers to be written
697**
698** Returns: status:
699** MT_OK - No errors
700** MT_COMM_ERR - Serial bus communications error
701** user-defined
702**
703** Notes: This is a callback function that is called from the
704** the tuning algorithm. You MUST provide code for this
705** function to write data using the tuner's 2-wire serial
706** bus.
707**
708** The hUserData parameter is a user-specific argument.
709** If additional arguments are needed for the user's
710** serial bus read/write functions, this argument can be
711** used to supply the necessary information.
712** The hUserData parameter is initialized in the tuner's Open
713** function.
714**
715** Revision History:
716**
717** SCR Date Author Description
718** -------------------------------------------------------------------------
719** N/A 03-25-2004 DAD Original
720**
721*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300722static u32 MT2063_WriteSub(void *hUserData,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300723 u32 addr,
724 u8 subAddress, u8 * pData, u32 cnt)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300725{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300726 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300727 struct dvb_frontend *fe = hUserData;
728 struct mt2063_state *state = fe->tuner_priv;
729 /*
730 ** ToDo: Add code here to implement a serial-bus write
731 ** operation to the MTxxxx tuner. If successful,
732 ** return MT_OK.
733 */
734/* return status; */
735
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300736 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300737
738 if (mt2063_writeregs(state, subAddress, pData, cnt) < 0) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300739 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300740 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300741 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300742
743 return (status);
744}
745
746/*****************************************************************************
747**
748** Name: MT_ReadSub
749**
750** Description: Read values from device using a two-wire serial bus.
751**
752** Parameters: hUserData - User-specific I/O parameter that was
753** passed to tuner's Open function.
754** addr - device serial bus address (value passed
755** as parameter to MTxxxx_Open)
756** subAddress - serial bus sub-address (Register Address)
757** pData - pointer to the Data to be written to the
758** device
759** cnt - number of bytes/registers to be written
760**
761** Returns: status:
762** MT_OK - No errors
763** MT_COMM_ERR - Serial bus communications error
764** user-defined
765**
766** Notes: This is a callback function that is called from the
767** the tuning algorithm. You MUST provide code for this
768** function to read data using the tuner's 2-wire serial
769** bus.
770**
771** The hUserData parameter is a user-specific argument.
772** If additional arguments are needed for the user's
773** serial bus read/write functions, this argument can be
774** used to supply the necessary information.
775** The hUserData parameter is initialized in the tuner's Open
776** function.
777**
778** Revision History:
779**
780** SCR Date Author Description
781** -------------------------------------------------------------------------
782** N/A 03-25-2004 DAD Original
783**
784*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300785static u32 MT2063_ReadSub(void *hUserData,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300786 u32 addr,
787 u8 subAddress, u8 * pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300788{
789 /*
790 ** ToDo: Add code here to implement a serial-bus read
791 ** operation to the MTxxxx tuner. If successful,
792 ** return MT_OK.
793 */
794/* return status; */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300795 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300796 struct dvb_frontend *fe = hUserData;
797 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300798 u32 i = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300799 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300800
801 for (i = 0; i < cnt; i++) {
802 if (mt2063_read_regs(state, subAddress + i, pData + i, 1) < 0) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300803 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300804 break;
805 }
806 }
807
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300808 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300809
810 return (status);
811}
812
813/*****************************************************************************
814**
815** Name: MT_Sleep
816**
817** Description: Delay execution for "nMinDelayTime" milliseconds
818**
819** Parameters: hUserData - User-specific I/O parameter that was
820** passed to tuner's Open function.
821** nMinDelayTime - Delay time in milliseconds
822**
823** Returns: None.
824**
825** Notes: This is a callback function that is called from the
826** the tuning algorithm. You MUST provide code that
827** blocks execution for the specified period of time.
828**
829** Revision History:
830**
831** SCR Date Author Description
832** -------------------------------------------------------------------------
833** N/A 03-25-2004 DAD Original
834**
835*****************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300836static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300837{
838 /*
839 ** ToDo: Add code here to implement a OS blocking
840 ** for a period of "nMinDelayTime" milliseconds.
841 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300842 msleep(10);
843
844 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300845}
846
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300847//end of mt2063_userdef.c
848//=================================================================
849//#################################################################
850//=================================================================
851
852//context of mt2063_spuravoid.c <Henry> ======================================
853//#################################################################
854//=================================================================
855
856/*****************************************************************************
857**
858** Name: mt_spuravoid.c
859**
860** Description: Microtune spur avoidance software module.
861** Supports Microtune tuner drivers.
862**
863** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
864** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
865**
866** Revision History:
867**
868** SCR Date Author Description
869** -------------------------------------------------------------------------
870** 082 03-25-2005 JWS Original multi-tuner support - requires
871** MTxxxx_CNT declarations
872** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
873** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
874** of compiler warnings
875** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
876** avoidance into a single module.
877** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
878** (f_min, f_max) < 0, ignore the entry.
879** 115 03-23-2007 DAD Fix declaration of spur due to truncation
880** errors.
881** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
882** tuner DLL.
883** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
884** multi-tuners that have
885** (delta IF1) > (f_out-f_outbw/2).
886** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
887** Added logic to force f_Center within 1/2 f_Step.
888** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
889** Type casts added to preserve correct sign.
890** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
891** frequencies into MT_ResetExclZones().
892** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
893**
894*****************************************************************************/
895
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300896/* Version of this module */
897#define MT2063_SPUR_VERSION 10201 /* Version 01.21 */
898
899/* Implement ceiling, floor functions. */
900#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
901#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
902#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
903#define ufloor(n, d) ((n)/(d))
904
905struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300906 s32 min_;
907 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300908};
909
910#if MT2063_TUNER_CNT > 1
911static struct MT2063_AvoidSpursData_t *TunerList[MT2063_TUNER_CNT];
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300912static u32 TunerCount = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300913#endif
914
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300915static u32 MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300916{
917#if MT2063_TUNER_CNT == 1
918 pAS_Info->nAS_Algorithm = 1;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300919 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300920#else
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300921 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300922
923 pAS_Info->nAS_Algorithm = 2;
924
925 /*
926 ** Check to see if tuner is already registered
927 */
928 for (index = 0; index < TunerCount; index++) {
929 if (TunerList[index] == pAS_Info) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300930 return 0; /* Already here - no problem */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300931 }
932 }
933
934 /*
935 ** Add tuner to list - if there is room.
936 */
937 if (TunerCount < MT2063_TUNER_CNT) {
938 TunerList[TunerCount] = pAS_Info;
939 TunerCount++;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300940 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300941 } else
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300942 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300943#endif
944}
945
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300946static void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300947{
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300948#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300949 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300950
951 for (index = 0; index < TunerCount; index++) {
952 if (TunerList[index] == pAS_Info) {
953 TunerList[index] = TunerList[--TunerCount];
954 }
955 }
956#endif
957}
958
959/*
960** Reset all exclusion zones.
961** Add zones to protect the PLL FracN regions near zero
962**
963** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
964** frequencies into MT_ResetExclZones().
965*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300966static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300967{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300968 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300969#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300970 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300971 struct MT2063_AvoidSpursData_t *adj;
972#endif
973
974 pAS_Info->nZones = 0; /* this clears the used list */
975 pAS_Info->usedZones = NULL; /* reset ptr */
976 pAS_Info->freeZones = NULL; /* reset ptr */
977
978 center =
979 pAS_Info->f_ref *
980 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
981 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
982 while (center <
983 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
984 pAS_Info->f_LO1_FracN_Avoid) {
985 /* Exclude LO1 FracN */
986 MT2063_AddExclZone(pAS_Info,
987 center - pAS_Info->f_LO1_FracN_Avoid,
988 center - 1);
989 MT2063_AddExclZone(pAS_Info, center + 1,
990 center + pAS_Info->f_LO1_FracN_Avoid);
991 center += pAS_Info->f_ref;
992 }
993
994 center =
995 pAS_Info->f_ref *
996 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
997 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
998 while (center <
999 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
1000 pAS_Info->f_LO2_FracN_Avoid) {
1001 /* Exclude LO2 FracN */
1002 MT2063_AddExclZone(pAS_Info,
1003 center - pAS_Info->f_LO2_FracN_Avoid,
1004 center - 1);
1005 MT2063_AddExclZone(pAS_Info, center + 1,
1006 center + pAS_Info->f_LO2_FracN_Avoid);
1007 center += pAS_Info->f_ref;
1008 }
1009
1010 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
1011 /* Exclude LO1 values that conflict with DECT channels */
1012 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
1013 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
1014 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
1015 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
1016 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
1017 }
1018
1019 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
1020 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
1021 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
1022 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
1023 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
1024 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
1025 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
1026 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
1027 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
1028 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
1029 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
1030 }
1031#if MT2063_TUNER_CNT > 1
1032 /*
1033 ** Iterate through all adjacent tuners and exclude frequencies related to them
1034 */
1035 for (index = 0; index < TunerCount; ++index) {
1036 adj = TunerList[index];
1037 if (pAS_Info == adj) /* skip over our own data, don't process it */
1038 continue;
1039
1040 /*
1041 ** Add 1st IF exclusion zone covering adjacent tuner's LO2
1042 ** at "adjfLO2 + f_out" +/- m_MinLOSpacing
1043 */
1044 if (adj->f_LO2 != 0)
1045 MT2063_AddExclZone(pAS_Info,
1046 (adj->f_LO2 + pAS_Info->f_out) -
1047 pAS_Info->f_min_LO_Separation,
1048 (adj->f_LO2 + pAS_Info->f_out) +
1049 pAS_Info->f_min_LO_Separation);
1050
1051 /*
1052 ** Add 1st IF exclusion zone covering adjacent tuner's LO1
1053 ** at "adjfLO1 - f_in" +/- m_MinLOSpacing
1054 */
1055 if (adj->f_LO1 != 0)
1056 MT2063_AddExclZone(pAS_Info,
1057 (adj->f_LO1 - pAS_Info->f_in) -
1058 pAS_Info->f_min_LO_Separation,
1059 (adj->f_LO1 - pAS_Info->f_in) +
1060 pAS_Info->f_min_LO_Separation);
1061 }
1062#endif
1063}
1064
1065static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
1066 *pAS_Info,
1067 struct MT2063_ExclZone_t *pPrevNode)
1068{
1069 struct MT2063_ExclZone_t *pNode;
1070 /* Check for a node in the free list */
1071 if (pAS_Info->freeZones != NULL) {
1072 /* Use one from the free list */
1073 pNode = pAS_Info->freeZones;
1074 pAS_Info->freeZones = pNode->next_;
1075 } else {
1076 /* Grab a node from the array */
1077 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
1078 }
1079
1080 if (pPrevNode != NULL) {
1081 pNode->next_ = pPrevNode->next_;
1082 pPrevNode->next_ = pNode;
1083 } else { /* insert at the beginning of the list */
1084
1085 pNode->next_ = pAS_Info->usedZones;
1086 pAS_Info->usedZones = pNode;
1087 }
1088
1089 pAS_Info->nZones++;
1090 return pNode;
1091}
1092
1093static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
1094 *pAS_Info,
1095 struct MT2063_ExclZone_t *pPrevNode,
1096 struct MT2063_ExclZone_t
1097 *pNodeToRemove)
1098{
1099 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
1100
1101 /* Make previous node point to the subsequent node */
1102 if (pPrevNode != NULL)
1103 pPrevNode->next_ = pNext;
1104
1105 /* Add pNodeToRemove to the beginning of the freeZones */
1106 pNodeToRemove->next_ = pAS_Info->freeZones;
1107 pAS_Info->freeZones = pNodeToRemove;
1108
1109 /* Decrement node count */
1110 pAS_Info->nZones--;
1111
1112 return pNext;
1113}
1114
1115/*****************************************************************************
1116**
1117** Name: MT_AddExclZone
1118**
1119** Description: Add (and merge) an exclusion zone into the list.
1120** If the range (f_min, f_max) is totally outside the
1121** 1st IF BW, ignore the entry.
1122** If the range (f_min, f_max) is negative, ignore the entry.
1123**
1124** Revision History:
1125**
1126** SCR Date Author Description
1127** -------------------------------------------------------------------------
1128** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
1129** (f_min, f_max) < 0, ignore the entry.
1130**
1131*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001132static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001133 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001134{
1135 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
1136 struct MT2063_ExclZone_t *pPrev = NULL;
1137 struct MT2063_ExclZone_t *pNext = NULL;
1138
1139 /* Check to see if this overlaps the 1st IF filter */
1140 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
1141 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
1142 && (f_min < f_max)) {
1143 /*
1144 ** 1 2 3 4 5 6
1145 **
1146 ** New entry: |---| |--| |--| |-| |---| |--|
1147 ** or or or or or
1148 ** Existing: |--| |--| |--| |---| |-| |--|
1149 */
1150
1151 /* Check for our place in the list */
1152 while ((pNode != NULL) && (pNode->max_ < f_min)) {
1153 pPrev = pNode;
1154 pNode = pNode->next_;
1155 }
1156
1157 if ((pNode != NULL) && (pNode->min_ < f_max)) {
1158 /* Combine me with pNode */
1159 if (f_min < pNode->min_)
1160 pNode->min_ = f_min;
1161 if (f_max > pNode->max_)
1162 pNode->max_ = f_max;
1163 } else {
1164 pNode = InsertNode(pAS_Info, pPrev);
1165 pNode->min_ = f_min;
1166 pNode->max_ = f_max;
1167 }
1168
1169 /* Look for merging possibilities */
1170 pNext = pNode->next_;
1171 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
1172 if (pNext->max_ > pNode->max_)
1173 pNode->max_ = pNext->max_;
1174 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
1175 }
1176 }
1177}
1178
1179/*****************************************************************************
1180**
1181** Name: MT_ChooseFirstIF
1182**
1183** Description: Choose the best available 1st IF
1184** If f_Desired is not excluded, choose that first.
1185** Otherwise, return the value closest to f_Center that is
1186** not excluded
1187**
1188** Revision History:
1189**
1190** SCR Date Author Description
1191** -------------------------------------------------------------------------
1192** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
1193** tuner DLL.
1194** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
1195** Added logic to force f_Center within 1/2 f_Step.
1196**
1197*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001198static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001199{
1200 /*
1201 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
1202 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
1203 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
1204 ** However, the sum must be.
1205 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001206 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001207 pAS_Info->f_LO1_Step *
1208 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
1209 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
1210 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001211 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001212 (pAS_Info->f_LO1_Step >
1213 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
1214 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001215 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001216
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001217 s32 i;
1218 s32 j = 0;
1219 u32 bDesiredExcluded = 0;
1220 u32 bZeroExcluded = 0;
1221 s32 tmpMin, tmpMax;
1222 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001223 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
1224 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
1225
1226 if (pAS_Info->nZones == 0)
1227 return f_Desired;
1228
1229 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
1230 if (pAS_Info->f_if1_Center > f_Desired)
1231 f_Center =
1232 f_Desired +
1233 f_Step *
1234 ((pAS_Info->f_if1_Center - f_Desired +
1235 f_Step / 2) / f_Step);
1236 else
1237 f_Center =
1238 f_Desired -
1239 f_Step *
1240 ((f_Desired - pAS_Info->f_if1_Center +
1241 f_Step / 2) / f_Step);
1242
1243 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001244 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001245 // return 0;
1246
1247 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
1248 while (pNode != NULL) {
1249 /* floor function */
1250 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001251 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001252
1253 /* ceil function */
1254 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001255 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001256
1257 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
1258 bDesiredExcluded = 1;
1259
1260 if ((tmpMin < 0) && (tmpMax > 0))
1261 bZeroExcluded = 1;
1262
1263 /* See if this zone overlaps the previous */
1264 if ((j > 0) && (tmpMin < zones[j - 1].max_))
1265 zones[j - 1].max_ = tmpMax;
1266 else {
1267 /* Add new zone */
1268 //assert(j<MT2063_MAX_ZONES);
1269 //if (j>=MT2063_MAX_ZONES)
1270 //break;
1271
1272 zones[j].min_ = tmpMin;
1273 zones[j].max_ = tmpMax;
1274 j++;
1275 }
1276 pNode = pNode->next_;
1277 }
1278
1279 /*
1280 ** If the desired is okay, return with it
1281 */
1282 if (bDesiredExcluded == 0)
1283 return f_Desired;
1284
1285 /*
1286 ** If the desired is excluded and the center is okay, return with it
1287 */
1288 if (bZeroExcluded == 0)
1289 return f_Center;
1290
1291 /* Find the value closest to 0 (f_Center) */
1292 bestDiff = zones[0].min_;
1293 for (i = 0; i < j; i++) {
1294 if (abs(zones[i].min_) < abs(bestDiff))
1295 bestDiff = zones[i].min_;
1296 if (abs(zones[i].max_) < abs(bestDiff))
1297 bestDiff = zones[i].max_;
1298 }
1299
1300 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001301 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001302
1303 return f_Center + (bestDiff * f_Step);
1304}
1305
1306/****************************************************************************
1307**
1308** Name: gcd
1309**
1310** Description: Uses Euclid's algorithm
1311**
1312** Parameters: u, v - unsigned values whose GCD is desired.
1313**
1314** Global: None
1315**
1316** Returns: greatest common divisor of u and v, if either value
1317** is 0, the other value is returned as the result.
1318**
1319** Dependencies: None.
1320**
1321** Revision History:
1322**
1323** SCR Date Author Description
1324** -------------------------------------------------------------------------
1325** N/A 06-01-2004 JWS Original
1326** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
1327** unsigned numbers.
1328**
1329****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001330static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001331{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001332 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001333
1334 while (v != 0) {
1335 r = u % v;
1336 u = v;
1337 v = r;
1338 }
1339
1340 return u;
1341}
1342
1343/****************************************************************************
1344**
1345** Name: umax
1346**
1347** Description: Implements a simple maximum function for unsigned numbers.
1348** Implemented as a function rather than a macro to avoid
1349** multiple evaluation of the calling parameters.
1350**
1351** Parameters: a, b - Values to be compared
1352**
1353** Global: None
1354**
1355** Returns: larger of the input values.
1356**
1357** Dependencies: None.
1358**
1359** Revision History:
1360**
1361** SCR Date Author Description
1362** -------------------------------------------------------------------------
1363** N/A 06-02-2004 JWS Original
1364**
1365****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001366static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001367{
1368 return (a >= b) ? a : b;
1369}
1370
1371#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001372static s32 RoundAwayFromZero(s32 n, s32 d)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001373{
1374 return (n < 0) ? floor(n, d) : ceil(n, d);
1375}
1376
1377/****************************************************************************
1378**
1379** Name: IsSpurInAdjTunerBand
1380**
1381** Description: Checks to see if a spur will be present within the IF's
1382** bandwidth or near the zero IF.
1383** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2)
1384** and
1385** (0 +/- fZIFBW/2)
1386**
1387** ma mb me mf mc md
1388** <--+-+-+-----------------+-+-+-----------------+-+-+-->
1389** | ^ 0 ^ |
1390** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1391** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1392**
1393** Note that some equations are doubled to prevent round-off
1394** problems when calculating fIFBW/2
1395**
1396** The spur frequencies are computed as:
1397**
1398** fSpur = n * f1 - m * f2 - fOffset
1399**
1400** Parameters: f1 - The 1st local oscillator (LO) frequency
1401** of the tuner whose output we are examining
1402** f2 - The 1st local oscillator (LO) frequency
1403** of the adjacent tuner
1404** fOffset - The 2nd local oscillator of the tuner whose
1405** output we are examining
1406** fIFOut - Output IF center frequency
1407** fIFBW - Output IF Bandwidth
1408** nMaxH - max # of LO harmonics to search
1409** fp - If spur, positive distance to spur-free band edge (returned)
1410** fm - If spur, negative distance to spur-free band edge (returned)
1411**
1412** Returns: 1 if an LO spur would be present, otherwise 0.
1413**
1414** Dependencies: None.
1415**
1416** Revision History:
1417**
1418** SCR Date Author Description
1419** -------------------------------------------------------------------------
1420** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion.
1421** 115 03-23-2007 DAD Fix declaration of spur due to truncation
1422** errors.
1423** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
1424** multi-tuners that have
1425** (delta IF1) > (f_out-f_outbw/2).
1426** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
1427** Type casts added to preserve correct sign.
1428**
1429****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001430static u32 IsSpurInAdjTunerBand(u32 bIsMyOutput,
1431 u32 f1,
1432 u32 f2,
1433 u32 fOffset,
1434 u32 fIFOut,
1435 u32 fIFBW,
1436 u32 fZIFBW,
1437 u32 nMaxH, u32 * fp, u32 * fm)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001438{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001439 u32 bSpurFound = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001440
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001441 const u32 fHalf_IFBW = fIFBW / 2;
1442 const u32 fHalf_ZIFBW = fZIFBW / 2;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001443
1444 /* Calculate a scale factor for all frequencies, so that our
1445 calculations all stay within 31 bits */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001446 const u32 f_Scale =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001447 ((f1 +
1448 (fOffset + fIFOut +
1449 fHalf_IFBW) / nMaxH) / (MAX_UDATA / 2 / nMaxH)) + 1;
1450
1451 /*
1452 ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into
1453 ** signed data types (smaller than MAX_UDATA/2)
1454 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001455 const s32 _f1 = (s32) (f1 / f_Scale);
1456 const s32 _f2 = (s32) (f2 / f_Scale);
1457 const s32 _f3 = (s32) (fOffset / f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001458
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001459 const s32 c = (s32) (fIFOut - fHalf_IFBW) / (s32) f_Scale;
1460 const s32 d = (s32) ((fIFOut + fHalf_IFBW) / f_Scale);
1461 const s32 f = (s32) (fHalf_ZIFBW / f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001462
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001463 s32 ma, mb, mc, md, me, mf;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001464
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001465 s32 fp_ = 0;
1466 s32 fm_ = 0;
1467 s32 n;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001468
1469 /*
1470 ** If the other tuner does not have an LO frequency defined,
1471 ** assume that we cannot interfere with it
1472 */
1473 if (f2 == 0)
1474 return 0;
1475
1476 /* Check out all multiples of f1 from -nMaxH to +nMaxH */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001477 for (n = -(s32) nMaxH; n <= (s32) nMaxH; ++n) {
1478 const s32 nf1 = n * _f1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001479 md = (_f3 + d - nf1) / _f2;
1480
1481 /* If # f2 harmonics > nMaxH, then no spurs present */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001482 if (md <= -(s32) nMaxH)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001483 break;
1484
1485 ma = (_f3 - d - nf1) / _f2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001486 if ((ma == md) || (ma >= (s32) (nMaxH)))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001487 continue;
1488
1489 mc = (_f3 + c - nf1) / _f2;
1490 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001491 const s32 m = (n < 0) ? md : mc;
1492 const s32 fspur = (nf1 + m * _f2 - _f3);
1493 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001494 if (den == 0) {
1495 fp_ = (d - fspur) * f_Scale;
1496 fm_ = (fspur - c) * f_Scale;
1497 } else {
1498 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001499 (s32) RoundAwayFromZero((d - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001500 f_Scale, den);
1501 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001502 (s32) RoundAwayFromZero((fspur - c) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001503 f_Scale, den);
1504 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001505 if (((u32) abs(fm_) >= f_Scale)
1506 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001507 bSpurFound = 1;
1508 break;
1509 }
1510 }
1511
1512 /* Location of Zero-IF-spur to be checked */
1513 mf = (_f3 + f - nf1) / _f2;
1514 me = (_f3 - f - nf1) / _f2;
1515 if (me != mf) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001516 const s32 m = (n < 0) ? mf : me;
1517 const s32 fspur = (nf1 + m * _f2 - _f3);
1518 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001519 if (den == 0) {
1520 fp_ = (d - fspur) * f_Scale;
1521 fm_ = (fspur - c) * f_Scale;
1522 } else {
1523 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001524 (s32) RoundAwayFromZero((f - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001525 f_Scale, den);
1526 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001527 (s32) RoundAwayFromZero((fspur + f) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001528 f_Scale, den);
1529 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001530 if (((u32) abs(fm_) >= f_Scale)
1531 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001532 bSpurFound = 1;
1533 break;
1534 }
1535 }
1536
1537 mb = (_f3 - c - nf1) / _f2;
1538 if (ma != mb) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001539 const s32 m = (n < 0) ? mb : ma;
1540 const s32 fspur = (nf1 + m * _f2 - _f3);
1541 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001542 if (den == 0) {
1543 fp_ = (d - fspur) * f_Scale;
1544 fm_ = (fspur - c) * f_Scale;
1545 } else {
1546 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001547 (s32) RoundAwayFromZero((-c - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001548 f_Scale, den);
1549 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001550 (s32) RoundAwayFromZero((fspur + d) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001551 f_Scale, den);
1552 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001553 if (((u32) abs(fm_) >= f_Scale)
1554 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001555 bSpurFound = 1;
1556 break;
1557 }
1558 }
1559 }
1560
1561 /*
1562 ** Verify that fm & fp are both positive
1563 ** Add one to ensure next 1st IF choice is not right on the edge
1564 */
1565 if (fp_ < 0) {
1566 *fp = -fm_ + 1;
1567 *fm = -fp_ + 1;
1568 } else if (fp_ > 0) {
1569 *fp = fp_ + 1;
1570 *fm = fm_ + 1;
1571 } else {
1572 *fp = 1;
1573 *fm = abs(fm_) + 1;
1574 }
1575
1576 return bSpurFound;
1577}
1578#endif
1579
1580/****************************************************************************
1581**
1582** Name: IsSpurInBand
1583**
1584** Description: Checks to see if a spur will be present within the IF's
1585** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1586**
1587** ma mb mc md
1588** <--+-+-+-------------------+-------------------+-+-+-->
1589** | ^ 0 ^ |
1590** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1591** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1592**
1593** Note that some equations are doubled to prevent round-off
1594** problems when calculating fIFBW/2
1595**
1596** Parameters: pAS_Info - Avoid Spurs information block
1597** fm - If spur, amount f_IF1 has to move negative
1598** fp - If spur, amount f_IF1 has to move positive
1599**
1600** Global: None
1601**
1602** Returns: 1 if an LO spur would be present, otherwise 0.
1603**
1604** Dependencies: None.
1605**
1606** Revision History:
1607**
1608** SCR Date Author Description
1609** -------------------------------------------------------------------------
1610** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1611**
1612****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001613static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1614 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001615{
1616 /*
1617 ** Calculate LO frequency settings.
1618 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001619 u32 n, n0;
1620 const u32 f_LO1 = pAS_Info->f_LO1;
1621 const u32 f_LO2 = pAS_Info->f_LO2;
1622 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1623 const u32 c = d - pAS_Info->f_out_bw;
1624 const u32 f = pAS_Info->f_zif_bw / 2;
1625 const u32 f_Scale = (f_LO1 / (MAX_UDATA / 2 / pAS_Info->maxH1)) + 1;
1626 s32 f_nsLO1, f_nsLO2;
1627 s32 f_Spur;
1628 u32 ma, mb, mc, md, me, mf;
1629 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001630#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001631 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001632
1633 struct MT2063_AvoidSpursData_t *adj;
1634#endif
1635 *fm = 0;
1636
1637 /*
1638 ** For each edge (d, c & f), calculate a scale, based on the gcd
1639 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1640 ** gcd-based scale factor or f_Scale.
1641 */
1642 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001643 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001644 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001645 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001646 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001647 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001648 hgfs = gf_Scale / 2;
1649
1650 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1651
1652 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1653 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1654 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1655 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1656
1657 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1658 if (md >= pAS_Info->maxH1)
1659 break;
1660
1661 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1662 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1663
1664 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1665 if (md == ma)
1666 continue;
1667
1668 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1669 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1670 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001671 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1672 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001673 f_Spur =
1674 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1675 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1676
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001677 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1678 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001679 return 1;
1680 }
1681
1682 /* Location of Zero-IF-spur to be checked */
1683 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1684 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1685 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1686 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1687 if (me != mf) {
1688 f_nsLO1 = n * (f_LO1 / gf_Scale);
1689 f_nsLO2 = me * (f_LO2 / gf_Scale);
1690 f_Spur =
1691 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1692 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1693
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001694 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1695 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001696 return 1;
1697 }
1698
1699 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1700 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1701 if (ma != mb) {
1702 f_nsLO1 = n * (f_LO1 / gc_Scale);
1703 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1704 f_Spur =
1705 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1706 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1707
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001708 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1709 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001710 return 1;
1711 }
1712 }
1713
1714#if MT2063_TUNER_CNT > 1
1715 /* If no spur found, see if there are more tuners on the same board */
1716 for (index = 0; index < TunerCount; ++index) {
1717 adj = TunerList[index];
1718 if (pAS_Info == adj) /* skip over our own data, don't process it */
1719 continue;
1720
1721 /* Look for LO-related spurs from the adjacent tuner generated into my IF output */
1722 if (IsSpurInAdjTunerBand(1, /* check my IF output */
1723 pAS_Info->f_LO1, /* my fLO1 */
1724 adj->f_LO1, /* the other tuner's fLO1 */
1725 pAS_Info->f_LO2, /* my fLO2 */
1726 pAS_Info->f_out, /* my fOut */
1727 pAS_Info->f_out_bw, /* my output IF bandwidth */
1728 pAS_Info->f_zif_bw, /* my Zero-IF bandwidth */
1729 pAS_Info->maxH2, fp, /* minimum amount to move LO's positive */
1730 fm)) /* miminum amount to move LO's negative */
1731 return 1;
1732 /* Look for LO-related spurs from my tuner generated into the adjacent tuner's IF output */
1733 if (IsSpurInAdjTunerBand(0, /* check his IF output */
1734 pAS_Info->f_LO1, /* my fLO1 */
1735 adj->f_LO1, /* the other tuner's fLO1 */
1736 adj->f_LO2, /* the other tuner's fLO2 */
1737 adj->f_out, /* the other tuner's fOut */
1738 adj->f_out_bw, /* the other tuner's output IF bandwidth */
1739 pAS_Info->f_zif_bw, /* the other tuner's Zero-IF bandwidth */
1740 adj->maxH2, fp, /* minimum amount to move LO's positive */
1741 fm)) /* miminum amount to move LO's negative */
1742 return 1;
1743 }
1744#endif
1745 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001746 return 0;
1747}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001748
1749/*****************************************************************************
1750**
1751** Name: MT_AvoidSpurs
1752**
1753** Description: Main entry point to avoid spurs.
1754** Checks for existing spurs in present LO1, LO2 freqs
1755** and if present, chooses spur-free LO1, LO2 combination
1756** that tunes the same input/output frequencies.
1757**
1758** Revision History:
1759**
1760** SCR Date Author Description
1761** -------------------------------------------------------------------------
1762** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1763**
1764*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001765static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001766{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001767 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001768 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001769 pAS_Info->bSpurAvoided = 0;
1770 pAS_Info->nSpursFound = 0;
1771
1772 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001773 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001774
1775 /*
1776 ** Avoid LO Generated Spurs
1777 **
1778 ** Make sure that have no LO-related spurs within the IF output
1779 ** bandwidth.
1780 **
1781 ** If there is an LO spur in this band, start at the current IF1 frequency
1782 ** and work out until we find a spur-free frequency or run up against the
1783 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1784 ** will be unchanged if a spur-free setting is not found.
1785 */
1786 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1787 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001788 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1789 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1790 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1791 u32 delta_IF1;
1792 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001793
1794 /*
1795 ** Spur was found, attempt to find a spur-free 1st IF
1796 */
1797 do {
1798 pAS_Info->nSpursFound++;
1799
1800 /* Raise f_IF1_upper, if needed */
1801 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1802
1803 /* Choose next IF1 that is closest to f_IF1_CENTER */
1804 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1805
1806 if (new_IF1 > zfIF1) {
1807 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1808 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1809 } else {
1810 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1811 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1812 }
1813 zfIF1 = new_IF1;
1814
1815 if (zfIF1 > pAS_Info->f_if1_Center)
1816 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1817 else
1818 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1819 }
1820 /*
1821 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1822 ** and there is a spur in the band (again)
1823 */
1824 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1825 pAS_Info->f_if1_bw)
1826 && (pAS_Info->bSpurPresent =
1827 IsSpurInBand(pAS_Info, &fm, &fp)));
1828
1829 /*
1830 ** Use the LO-spur free values found. If the search went all the way to
1831 ** the 1st IF band edge and always found spurs, just leave the original
1832 ** choice. It's as "good" as any other.
1833 */
1834 if (pAS_Info->bSpurPresent == 1) {
1835 status |= MT2063_SPUR_PRESENT_ERR;
1836 pAS_Info->f_LO1 = zfLO1;
1837 pAS_Info->f_LO2 = zfLO2;
1838 } else
1839 pAS_Info->bSpurAvoided = 1;
1840 }
1841
1842 status |=
1843 ((pAS_Info->
1844 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1845
1846 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001847}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001848
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001849//end of mt2063_spuravoid.c
1850//=================================================================
1851//#################################################################
1852//=================================================================
1853
1854/*
1855** The expected version of MT_AvoidSpursData_t
1856** If the version is different, an updated file is needed from Microtune
1857*/
1858/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001859
1860typedef enum {
1861 MT2063_SET_ATTEN,
1862 MT2063_INCR_ATTEN,
1863 MT2063_DECR_ATTEN
1864} MT2063_ATTEN_CNTL_MODE;
1865
1866//#define TUNER_MT2063_OPTIMIZATION
1867/*
1868** Constants used by the tuning algorithm
1869*/
1870#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1871#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1872#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1873#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1874#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1875#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1876#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1877#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1878#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1879#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1880#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1881#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1882#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1883#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1884#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1885#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1886#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1887#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1888
1889/*
1890** Define the supported Part/Rev codes for the MT2063
1891*/
1892#define MT2063_B0 (0x9B)
1893#define MT2063_B1 (0x9C)
1894#define MT2063_B2 (0x9D)
1895#define MT2063_B3 (0x9E)
1896
1897/*
1898** The number of Tuner Registers
1899*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001900static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001901
1902#define USE_GLOBAL_TUNER 0
1903
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001904static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001905static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001906
1907/*
1908** Constants for setting receiver modes.
1909** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1910** (DNC1GC & DNC2GC are the values, which are used, when the specific
1911** DNC Output is selected, the other is always off)
1912**
1913** If PAL-L or L' is received, set:
1914** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1915**
1916** --------------+----------------------------------------------
1917** Mode 0 : | MT2063_CABLE_QAM
1918** Mode 1 : | MT2063_CABLE_ANALOG
1919** Mode 2 : | MT2063_OFFAIR_COFDM
1920** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1921** Mode 4 : | MT2063_OFFAIR_ANALOG
1922** Mode 5 : | MT2063_OFFAIR_8VSB
1923** --------------+----+----+----+----+-----+-----+--------------
1924** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1925** --------------+----+----+----+----+-----+-----+
1926**
1927**
1928*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001929static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1930static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1931static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1932static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1933static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1934static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1935static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1936static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1937static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1938static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1939static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1940static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1941static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1942static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001943
1944/*
1945** Local Function Prototypes - not available for external access.
1946*/
1947
1948/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001949static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1950 u32 f_LO_Step, u32 f_Ref);
1951static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1952 u32 f_LO_Step, u32 f_Ref);
1953static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1954 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001955
1956/******************************************************************************
1957**
1958** Name: MT2063_Open
1959**
1960** Description: Initialize the tuner's register values.
1961**
1962** Parameters: MT2063_Addr - Serial bus address of the tuner.
1963** hMT2063 - Tuner handle passed back.
1964** hUserData - User-defined data, if needed for the
1965** MT_ReadSub() & MT_WriteSub functions.
1966**
1967** Returns: status:
1968** MT_OK - No errors
1969** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1970** MT_TUNER_INIT_ERR - Tuner initialization failed
1971** MT_COMM_ERR - Serial bus communications error
1972** MT_ARG_NULL - Null pointer argument passed
1973** MT_TUNER_CNT_ERR - Too many tuners open
1974**
1975** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1976** MT_WriteSub - Write byte(s) of data to the two-wire bus
1977**
1978** Revision History:
1979**
1980** SCR Date Author Description
1981** -------------------------------------------------------------------------
1982** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1983**
1984******************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03001985static u32 MT2063_Open(u32 MT2063_Addr, struct MT2063_Info_t **hMT2063, void *hUserData)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001986{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001987 u32 status = 0; /* Status to be returned. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001988 struct MT2063_Info_t *pInfo = NULL;
1989 struct dvb_frontend *fe = (struct dvb_frontend *)hUserData;
1990 struct mt2063_state *state = fe->tuner_priv;
1991
1992 /* Check the argument before using */
1993 if (hMT2063 == NULL) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001994 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995 }
1996
1997 /* Default tuner handle to NULL. If successful, it will be reassigned */
1998
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001999 if (state->MT2063_init == false) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002000 pInfo = kzalloc(sizeof(struct MT2063_Info_t), GFP_KERNEL);
2001 if (pInfo == NULL) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002002 return -ENOMEM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002003 }
2004 pInfo->handle = NULL;
2005 pInfo->address = MAX_UDATA;
2006 pInfo->rcvr_mode = MT2063_CABLE_QAM;
2007 pInfo->hUserData = NULL;
2008 } else {
2009 pInfo = *hMT2063;
2010 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002011
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002012 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002013 status |= MT2063_RegisterTuner(&pInfo->AS_Data);
2014 }
2015
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002016 if (status >= 0) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002017 pInfo->handle = (void *) pInfo;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002018
2019 pInfo->hUserData = hUserData;
2020 pInfo->address = MT2063_Addr;
2021 pInfo->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002022 status |= MT2063_ReInit((void *) pInfo);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002023 }
2024
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002025 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002026 /* MT2063_Close handles the un-registration of the tuner */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002027 MT2063_Close((void *) pInfo);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002028 else {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002029 state->MT2063_init = true;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002030 *hMT2063 = pInfo->handle;
2031
2032 }
2033
2034 return (status);
2035}
2036
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002037static u32 MT2063_IsValidHandle(struct MT2063_Info_t *handle)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002038{
2039 return ((handle != NULL) && (handle->handle == handle)) ? 1 : 0;
2040}
2041
2042/******************************************************************************
2043**
2044** Name: MT2063_Close
2045**
2046** Description: Release the handle to the tuner.
2047**
2048** Parameters: hMT2063 - Handle to the MT2063 tuner
2049**
2050** Returns: status:
2051** MT_OK - No errors
2052** MT_INV_HANDLE - Invalid tuner handle
2053**
2054** Dependencies: mt_errordef.h - definition of error codes
2055**
2056** Revision History:
2057**
2058** SCR Date Author Description
2059** -------------------------------------------------------------------------
2060** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2061**
2062******************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002063static u32 MT2063_Close(struct MT2063_Info_t *pInfo)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002064{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002065 if (!MT2063_IsValidHandle(pInfo))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002066 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002067
2068 /* Unregister tuner with SpurAvoidance routines (if needed) */
2069 MT2063_UnRegisterTuner(&pInfo->AS_Data);
2070 /* Now remove the tuner from our own list of tuners */
2071 pInfo->handle = NULL;
2072 pInfo->address = MAX_UDATA;
2073 pInfo->hUserData = NULL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002074 //kfree(pInfo);
2075 //pInfo = NULL;
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03002076
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002077 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002078}
2079
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002080/****************************************************************************
2081**
2082** Name: MT2063_GetLocked
2083**
2084** Description: Checks to see if LO1 and LO2 are locked.
2085**
2086** Parameters: h - Open handle to the tuner (from MT2063_Open).
2087**
2088** Returns: status:
2089** MT_OK - No errors
2090** MT_UPC_UNLOCK - Upconverter PLL unlocked
2091** MT_DNC_UNLOCK - Downconverter PLL unlocked
2092** MT_COMM_ERR - Serial bus communications error
2093** MT_INV_HANDLE - Invalid tuner handle
2094**
2095** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
2096** MT_Sleep - Delay execution for x milliseconds
2097**
2098** Revision History:
2099**
2100** SCR Date Author Description
2101** -------------------------------------------------------------------------
2102** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2103**
2104****************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002105static u32 MT2063_GetLocked(struct MT2063_Info_t *pInfo)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002106{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002107 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
2108 const u32 nPollRate = 2; /* poll status bits every 2 ms */
2109 const u32 nMaxLoops = nMaxWait / nPollRate;
2110 const u8 LO1LK = 0x80;
2111 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002112 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002113 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002114
2115 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002116 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002117
2118 /* LO2 Lock bit was in a different place for B0 version */
2119 if (pInfo->tuner_id == MT2063_B0)
2120 LO2LK = 0x40;
2121
2122 do {
2123 status |=
2124 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2125 MT2063_REG_LO_STATUS,
2126 &pInfo->reg[MT2063_REG_LO_STATUS], 1);
2127
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002128 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002129 return (status);
2130
2131 if ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
2132 (LO1LK | LO2LK)) {
2133 return (status);
2134 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03002135 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002136 }
2137 while (++nDelays < nMaxLoops);
2138
2139 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
2140 status |= MT2063_UPC_UNLOCK;
2141 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
2142 status |= MT2063_DNC_UNLOCK;
2143
2144 return (status);
2145}
2146
2147/****************************************************************************
2148**
2149** Name: MT2063_GetParam
2150**
2151** Description: Gets a tuning algorithm parameter.
2152**
2153** This function provides access to the internals of the
2154** tuning algorithm - mostly for testing purposes.
2155**
2156** Parameters: h - Tuner handle (returned by MT2063_Open)
2157** param - Tuning algorithm parameter
2158** (see enum MT2063_Param)
2159** pValue - ptr to returned value
2160**
2161** param Description
2162** ---------------------- --------------------------------
2163** MT2063_IC_ADDR Serial Bus address of this tuner
2164** MT2063_MAX_OPEN Max # of MT2063's allowed open
2165** MT2063_NUM_OPEN # of MT2063's open
2166** MT2063_SRO_FREQ crystal frequency
2167** MT2063_STEPSIZE minimum tuning step size
2168** MT2063_INPUT_FREQ input center frequency
2169** MT2063_LO1_FREQ LO1 Frequency
2170** MT2063_LO1_STEPSIZE LO1 minimum step size
2171** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2172** MT2063_IF1_ACTUAL Current 1st IF in use
2173** MT2063_IF1_REQUEST Requested 1st IF
2174** MT2063_IF1_CENTER Center of 1st IF SAW filter
2175** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
2176** MT2063_ZIF_BW zero-IF bandwidth
2177** MT2063_LO2_FREQ LO2 Frequency
2178** MT2063_LO2_STEPSIZE LO2 minimum step size
2179** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2180** MT2063_OUTPUT_FREQ output center frequency
2181** MT2063_OUTPUT_BW output bandwidth
2182** MT2063_LO_SEPARATION min inter-tuner LO separation
2183** MT2063_AS_ALG ID of avoid-spurs algorithm in use
2184** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2185** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2186** MT2063_EXCL_ZONES # of 1st IF exclusion zones
2187** MT2063_NUM_SPURS # of spurs found/avoided
2188** MT2063_SPUR_AVOIDED >0 spurs avoided
2189** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
2190** MT2063_RCVR_MODE Predefined modes.
2191** MT2063_ACLNA LNA attenuator gain code
2192** MT2063_ACRF RF attenuator gain code
2193** MT2063_ACFIF FIF attenuator gain code
2194** MT2063_ACLNA_MAX LNA attenuator limit
2195** MT2063_ACRF_MAX RF attenuator limit
2196** MT2063_ACFIF_MAX FIF attenuator limit
2197** MT2063_PD1 Actual value of PD1
2198** MT2063_PD2 Actual value of PD2
2199** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2200** MT2063_VGAGC VGA gain code
2201** MT2063_VGAOI VGA output current
2202** MT2063_TAGC TAGC setting
2203** MT2063_AMPGC AMP gain code
2204** MT2063_AVOID_DECT Avoid DECT Frequencies
2205** MT2063_CTFILT_SW Cleartune filter selection
2206**
2207** Usage: status |= MT2063_GetParam(hMT2063,
2208** MT2063_IF1_ACTUAL,
2209** &f_IF1_Actual);
2210**
2211** Returns: status:
2212** MT_OK - No errors
2213** MT_INV_HANDLE - Invalid tuner handle
2214** MT_ARG_NULL - Null pointer argument passed
2215** MT_ARG_RANGE - Invalid parameter requested
2216**
2217** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2218**
2219** See Also: MT2063_SetParam, MT2063_Open
2220**
2221** Revision History:
2222**
2223** SCR Date Author Description
2224** -------------------------------------------------------------------------
2225** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2226** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2227** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2228** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
2229** in GetParam.
2230** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2231** Split SetParam up to ACLNA / ACLNA_MAX
2232** removed ACLNA_INRC/DECR (+RF & FIF)
2233** removed GCUAUTO / BYPATNDN/UP
2234** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2235** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2236** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2237**
2238****************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002239static u32 MT2063_GetParam(struct MT2063_Info_t *pInfo, enum MT2063_Param param, u32 * pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002240{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002241 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002242 u32 Div;
2243 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002244
2245 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002246 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002247
2248 /* Verify that the handle passed points to a valid tuner */
2249 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002250 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002251
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002252 switch (param) {
2253 /* Serial Bus address of this tuner */
2254 case MT2063_IC_ADDR:
2255 *pValue = pInfo->address;
2256 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002257
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002258 /* Max # of MT2063's allowed to be open */
2259 case MT2063_MAX_OPEN:
2260 *pValue = nMT2063MaxTuners;
2261 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002262
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002263 /* # of MT2063's open */
2264 case MT2063_NUM_OPEN:
2265 *pValue = nMT2063OpenTuners;
2266 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002267
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002268 /* crystal frequency */
2269 case MT2063_SRO_FREQ:
2270 *pValue = pInfo->AS_Data.f_ref;
2271 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002272
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002273 /* minimum tuning step size */
2274 case MT2063_STEPSIZE:
2275 *pValue = pInfo->AS_Data.f_LO2_Step;
2276 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002277
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002278 /* input center frequency */
2279 case MT2063_INPUT_FREQ:
2280 *pValue = pInfo->AS_Data.f_in;
2281 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002282
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002283 /* LO1 Frequency */
2284 case MT2063_LO1_FREQ:
2285 {
2286 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
2287 status |=
2288 MT2063_ReadSub(pInfo->hUserData,
2289 pInfo->address,
2290 MT2063_REG_LO1C_1,
2291 &pInfo->
2292 reg[MT2063_REG_LO1C_1], 2);
2293 Div = pInfo->reg[MT2063_REG_LO1C_1];
2294 Num = pInfo->reg[MT2063_REG_LO1C_2] & 0x3F;
2295 pInfo->AS_Data.f_LO1 =
2296 (pInfo->AS_Data.f_ref * Div) +
2297 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2298 f_ref, Num, 64);
2299 }
2300 *pValue = pInfo->AS_Data.f_LO1;
2301 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002302
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002303 /* LO1 minimum step size */
2304 case MT2063_LO1_STEPSIZE:
2305 *pValue = pInfo->AS_Data.f_LO1_Step;
2306 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002307
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002308 /* LO1 FracN keep-out region */
2309 case MT2063_LO1_FRACN_AVOID_PARAM:
2310 *pValue = pInfo->AS_Data.f_LO1_FracN_Avoid;
2311 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002312
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002313 /* Current 1st IF in use */
2314 case MT2063_IF1_ACTUAL:
2315 *pValue = pInfo->f_IF1_actual;
2316 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002317
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002318 /* Requested 1st IF */
2319 case MT2063_IF1_REQUEST:
2320 *pValue = pInfo->AS_Data.f_if1_Request;
2321 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002322
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002323 /* Center of 1st IF SAW filter */
2324 case MT2063_IF1_CENTER:
2325 *pValue = pInfo->AS_Data.f_if1_Center;
2326 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002327
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002328 /* Bandwidth of 1st IF SAW filter */
2329 case MT2063_IF1_BW:
2330 *pValue = pInfo->AS_Data.f_if1_bw;
2331 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002332
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002333 /* zero-IF bandwidth */
2334 case MT2063_ZIF_BW:
2335 *pValue = pInfo->AS_Data.f_zif_bw;
2336 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002337
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002338 /* LO2 Frequency */
2339 case MT2063_LO2_FREQ:
2340 {
2341 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
2342 status |=
2343 MT2063_ReadSub(pInfo->hUserData,
2344 pInfo->address,
2345 MT2063_REG_LO2C_1,
2346 &pInfo->
2347 reg[MT2063_REG_LO2C_1], 3);
2348 Div =
2349 (pInfo->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
2350 Num =
2351 ((pInfo->
2352 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
2353 (pInfo->
2354 reg[MT2063_REG_LO2C_2] << 4) | (pInfo->
2355 reg
2356 [MT2063_REG_LO2C_3]
2357 & 0x00F);
2358 pInfo->AS_Data.f_LO2 =
2359 (pInfo->AS_Data.f_ref * Div) +
2360 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2361 f_ref, Num, 8191);
2362 }
2363 *pValue = pInfo->AS_Data.f_LO2;
2364 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002365
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002366 /* LO2 minimum step size */
2367 case MT2063_LO2_STEPSIZE:
2368 *pValue = pInfo->AS_Data.f_LO2_Step;
2369 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002370
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002371 /* LO2 FracN keep-out region */
2372 case MT2063_LO2_FRACN_AVOID:
2373 *pValue = pInfo->AS_Data.f_LO2_FracN_Avoid;
2374 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002375
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002376 /* output center frequency */
2377 case MT2063_OUTPUT_FREQ:
2378 *pValue = pInfo->AS_Data.f_out;
2379 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002380
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002381 /* output bandwidth */
2382 case MT2063_OUTPUT_BW:
2383 *pValue = pInfo->AS_Data.f_out_bw - 750000;
2384 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002385
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002386 /* min inter-tuner LO separation */
2387 case MT2063_LO_SEPARATION:
2388 *pValue = pInfo->AS_Data.f_min_LO_Separation;
2389 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002390
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002391 /* ID of avoid-spurs algorithm in use */
2392 case MT2063_AS_ALG:
2393 *pValue = pInfo->AS_Data.nAS_Algorithm;
2394 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002395
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002396 /* max # of intra-tuner harmonics */
2397 case MT2063_MAX_HARM1:
2398 *pValue = pInfo->AS_Data.maxH1;
2399 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002400
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002401 /* max # of inter-tuner harmonics */
2402 case MT2063_MAX_HARM2:
2403 *pValue = pInfo->AS_Data.maxH2;
2404 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002405
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002406 /* # of 1st IF exclusion zones */
2407 case MT2063_EXCL_ZONES:
2408 *pValue = pInfo->AS_Data.nZones;
2409 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002410
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002411 /* # of spurs found/avoided */
2412 case MT2063_NUM_SPURS:
2413 *pValue = pInfo->AS_Data.nSpursFound;
2414 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002415
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002416 /* >0 spurs avoided */
2417 case MT2063_SPUR_AVOIDED:
2418 *pValue = pInfo->AS_Data.bSpurAvoided;
2419 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002420
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002421 /* >0 spurs in output (mathematically) */
2422 case MT2063_SPUR_PRESENT:
2423 *pValue = pInfo->AS_Data.bSpurPresent;
2424 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002425
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002426 /* Predefined receiver setup combination */
2427 case MT2063_RCVR_MODE:
2428 *pValue = pInfo->rcvr_mode;
2429 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002430
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002431 case MT2063_PD1:
2432 case MT2063_PD2:
2433 {
2434 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
2435 u8 orig = (pInfo->reg[MT2063_REG_BYP_CTRL]);
2436 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
2437 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002438
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002439 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002440
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002441 /* Initiate ADC output to reg 0x0A */
2442 if (reg != orig)
2443 status |=
2444 MT2063_WriteSub(pInfo->hUserData,
2445 pInfo->address,
2446 MT2063_REG_BYP_CTRL,
2447 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002448
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002449 if (status < 0)
2450 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002451
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002452 for (i = 0; i < 8; i++) {
2453 status |=
2454 MT2063_ReadSub(pInfo->hUserData,
2455 pInfo->address,
2456 MT2063_REG_ADC_OUT,
2457 &pInfo->
2458 reg
2459 [MT2063_REG_ADC_OUT],
2460 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002461
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002462 if (status >= 0)
2463 *pValue +=
2464 pInfo->
2465 reg[MT2063_REG_ADC_OUT];
2466 else {
2467 if (i)
2468 *pValue /= i;
2469 return (status);
2470 }
2471 }
2472 *pValue /= 8; /* divide by number of reads */
2473 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002474
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002475 /* Restore value of Register BYP_CTRL */
2476 if (reg != orig)
2477 status |=
2478 MT2063_WriteSub(pInfo->hUserData,
2479 pInfo->address,
2480 MT2063_REG_BYP_CTRL,
2481 &orig, 1);
2482 }
2483 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002484
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002485 /* Get LNA attenuator code */
2486 case MT2063_ACLNA:
2487 {
2488 u8 val;
2489 status |=
2490 MT2063_GetReg(pInfo, MT2063_REG_XO_STATUS,
2491 &val);
2492 *pValue = val & 0x1f;
2493 }
2494 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002495
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002496 /* Get RF attenuator code */
2497 case MT2063_ACRF:
2498 {
2499 u8 val;
2500 status |=
2501 MT2063_GetReg(pInfo, MT2063_REG_RF_STATUS,
2502 &val);
2503 *pValue = val & 0x1f;
2504 }
2505 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002506
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002507 /* Get FIF attenuator code */
2508 case MT2063_ACFIF:
2509 {
2510 u8 val;
2511 status |=
2512 MT2063_GetReg(pInfo, MT2063_REG_FIF_STATUS,
2513 &val);
2514 *pValue = val & 0x1f;
2515 }
2516 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002517
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002518 /* Get LNA attenuator limit */
2519 case MT2063_ACLNA_MAX:
2520 {
2521 u8 val;
2522 status |=
2523 MT2063_GetReg(pInfo, MT2063_REG_LNA_OV,
2524 &val);
2525 *pValue = val & 0x1f;
2526 }
2527 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002528
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002529 /* Get RF attenuator limit */
2530 case MT2063_ACRF_MAX:
2531 {
2532 u8 val;
2533 status |=
2534 MT2063_GetReg(pInfo, MT2063_REG_RF_OV,
2535 &val);
2536 *pValue = val & 0x1f;
2537 }
2538 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002539
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002540 /* Get FIF attenuator limit */
2541 case MT2063_ACFIF_MAX:
2542 {
2543 u8 val;
2544 status |=
2545 MT2063_GetReg(pInfo, MT2063_REG_FIF_OV,
2546 &val);
2547 *pValue = val & 0x1f;
2548 }
2549 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002550
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002551 /* Get current used DNC output */
2552 case MT2063_DNC_OUTPUT_ENABLE:
2553 {
2554 if ((pInfo->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
2555 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2556 *pValue =
2557 (u32) MT2063_DNC_NONE;
2558 else
2559 *pValue =
2560 (u32) MT2063_DNC_2;
2561 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002562
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002563 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2564 *pValue =
2565 (u32) MT2063_DNC_1;
2566 else
2567 *pValue =
2568 (u32) MT2063_DNC_BOTH;
2569 }
2570 }
2571 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002572
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002573 /* Get VGA Gain Code */
2574 case MT2063_VGAGC:
2575 *pValue =
2576 ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
2577 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002578
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002579 /* Get VGA bias current */
2580 case MT2063_VGAOI:
2581 *pValue = (pInfo->reg[MT2063_REG_RSVD_31] & 0x07);
2582 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002583
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002584 /* Get TAGC setting */
2585 case MT2063_TAGC:
2586 *pValue = (pInfo->reg[MT2063_REG_RSVD_1E] & 0x03);
2587 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002588
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002589 /* Get AMP Gain Code */
2590 case MT2063_AMPGC:
2591 *pValue = (pInfo->reg[MT2063_REG_TEMP_SEL] & 0x03);
2592 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002593
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002594 /* Avoid DECT Frequencies */
2595 case MT2063_AVOID_DECT:
2596 *pValue = pInfo->AS_Data.avoidDECT;
2597 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002598
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002599 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2600 case MT2063_CTFILT_SW:
2601 *pValue = pInfo->ctfilt_sw;
2602 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002603
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002604 case MT2063_EOP:
2605 default:
2606 status |= -ERANGE;
2607 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002608 return (status);
2609}
2610
2611/****************************************************************************
2612**
2613** Name: MT2063_GetReg
2614**
2615** Description: Gets an MT2063 register.
2616**
2617** Parameters: h - Tuner handle (returned by MT2063_Open)
2618** reg - MT2063 register/subaddress location
2619** *val - MT2063 register/subaddress value
2620**
2621** Returns: status:
2622** MT_OK - No errors
2623** MT_COMM_ERR - Serial bus communications error
2624** MT_INV_HANDLE - Invalid tuner handle
2625** MT_ARG_NULL - Null pointer argument passed
2626** MT_ARG_RANGE - Argument out of range
2627**
2628** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2629**
2630** Use this function if you need to read a register from
2631** the MT2063.
2632**
2633** Revision History:
2634**
2635** SCR Date Author Description
2636** -------------------------------------------------------------------------
2637** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2638**
2639****************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002640static u32 MT2063_GetReg(struct MT2063_Info_t *pInfo, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002641{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002642 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002643
2644 /* Verify that the handle passed points to a valid tuner */
2645 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002646 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002647
2648 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002649 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002650
2651 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002652 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002653
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002654 status = MT2063_ReadSub(pInfo->hUserData, pInfo->address, reg,
2655 &pInfo->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002656
2657 return (status);
2658}
2659
2660/******************************************************************************
2661**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002662** Name: MT2063_SetReceiverMode
2663**
2664** Description: Set the MT2063 receiver mode
2665**
2666** --------------+----------------------------------------------
2667** Mode 0 : | MT2063_CABLE_QAM
2668** Mode 1 : | MT2063_CABLE_ANALOG
2669** Mode 2 : | MT2063_OFFAIR_COFDM
2670** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2671** Mode 4 : | MT2063_OFFAIR_ANALOG
2672** Mode 5 : | MT2063_OFFAIR_8VSB
2673** --------------+----+----+----+----+-----+--------------------
2674** (DNC1GC & DNC2GC are the values, which are used, when the specific
2675** DNC Output is selected, the other is always off)
2676**
2677** |<---------- Mode -------------->|
2678** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2679** ------------+-----+-----+-----+-----+-----+-----+
2680** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2681** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2682** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2683** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2684** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2685** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2686** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2687** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2688** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2689** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2690** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2691** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2692** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2693** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2694** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2695**
2696**
2697** Parameters: pInfo - ptr to MT2063_Info_t structure
2698** Mode - desired reciever mode
2699**
2700** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2701**
2702** Returns: status:
2703** MT_OK - No errors
2704** MT_COMM_ERR - Serial bus communications error
2705**
2706** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2707** Assumes that the tuner cache is valid.
2708**
2709** Revision History:
2710**
2711** SCR Date Author Description
2712** -------------------------------------------------------------------------
2713** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2714** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2715** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2716** modulation
2717** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2718** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2719** the same settings as with MT Launcher
2720** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2721** Add SetParam DNC_OUTPUT_ENABLE
2722** Removed VGAGC from receiver mode,
2723** default now 1
2724** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2725** Add SetParam AMPGC, removed from rcvr-mode
2726** Corrected names of GCU values
2727** reorganized receiver modes, removed,
2728** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2729** Actualized Receiver-Mode values
2730** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2731** N/A 11-27-2007 PINZ Improved buffered writing
2732** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2733** correct wakeup of the LNA after shutdown
2734** Set AFCsd = 1 as default
2735** Changed CAP1sel default
2736** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2737** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2738** Split SetParam up to ACLNA / ACLNA_MAX
2739** removed ACLNA_INRC/DECR (+RF & FIF)
2740** removed GCUAUTO / BYPATNDN/UP
2741**
2742******************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002743static u32 MT2063_SetReceiverMode(struct MT2063_Info_t *pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002744 enum MT2063_RCVR_MODES Mode)
2745{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002746 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002747 u8 val;
2748 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002749
2750 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002751 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002752
2753 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002754 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002755 val =
2756 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002757 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002758 ? 0x40 :
2759 0x00);
2760 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2761 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2762 }
2763 }
2764
2765 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002766 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002767 status |= MT2063_SetParam(pInfo, MT2063_LNA_RIN, LNARIN[Mode]);
2768 }
2769
2770 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002771 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002772 val =
2773 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002774 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002775 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
2776 if (pInfo->reg[MT2063_REG_FIFF_CTRL2] != val) {
2777 status |=
2778 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL2, val);
2779 /* trigger FIFF calibration, needed after changing FIFFQ */
2780 val =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002781 (pInfo->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002782 status |=
2783 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2784 val =
2785 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002786 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002787 status |=
2788 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2789 }
2790 }
2791
2792 /* DNC1GC & DNC2GC */
2793 status |= MT2063_GetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, &longval);
2794 status |= MT2063_SetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, longval);
2795
2796 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002797 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002798 status |=
2799 MT2063_SetParam(pInfo, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
2800 }
2801
2802 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002803 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002804 status |= MT2063_SetParam(pInfo, MT2063_LNA_TGT, LNATGT[Mode]);
2805 }
2806
2807 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002808 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002809 status |=
2810 MT2063_SetParam(pInfo, MT2063_ACRF_MAX, ACRFMAX[Mode]);
2811 }
2812
2813 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002814 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002815 status |= MT2063_SetParam(pInfo, MT2063_PD1_TGT, PD1TGT[Mode]);
2816 }
2817
2818 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002819 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002820 status |=
2821 MT2063_SetParam(pInfo, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
2822 }
2823
2824 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002825 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002826 status |= MT2063_SetParam(pInfo, MT2063_PD2_TGT, PD2TGT[Mode]);
2827 }
2828
2829 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002830 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002831 val =
2832 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002833 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002834 ? 0x80 :
2835 0x00);
2836 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
2837 status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val);
2838 }
2839 }
2840
2841 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002842 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002843 val =
2844 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002845 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002846 (FIFOVDIS[Mode] ? 0x80 : 0x00);
2847 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2848 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2849 }
2850 }
2851
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002852 if (status >= 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002853 pInfo->rcvr_mode = Mode;
2854
2855 return (status);
2856}
2857
2858/******************************************************************************
2859**
2860** Name: MT2063_ReInit
2861**
2862** Description: Initialize the tuner's register values.
2863**
2864** Parameters: h - Tuner handle (returned by MT2063_Open)
2865**
2866** Returns: status:
2867** MT_OK - No errors
2868** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2869** MT_INV_HANDLE - Invalid tuner handle
2870** MT_COMM_ERR - Serial bus communications error
2871**
2872** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2873** MT_WriteSub - Write byte(s) of data to the two-wire bus
2874**
2875** Revision History:
2876**
2877** SCR Date Author Description
2878** -------------------------------------------------------------------------
2879** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2880** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2881** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2882** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2883** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2884** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2885** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2886** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2887** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2888** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2889** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2890**
2891******************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002892static u32 MT2063_ReInit(struct MT2063_Info_t *pInfo)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002893{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002894 u8 all_resets = 0xF0; /* reset/load bits */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002895 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03002896 u8 *def = NULL;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002897 u32 FCRUN;
2898 s32 maxReads;
2899 u32 fcu_osc;
2900 u32 i;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002901 u8 MT2063B0_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002902 0x19, 0x05,
2903 0x1B, 0x1D,
2904 0x1C, 0x1F,
2905 0x1D, 0x0F,
2906 0x1E, 0x3F,
2907 0x1F, 0x0F,
2908 0x20, 0x3F,
2909 0x22, 0x21,
2910 0x23, 0x3F,
2911 0x24, 0x20,
2912 0x25, 0x3F,
2913 0x27, 0xEE,
2914 0x2C, 0x27, /* bit at 0x20 is cleared below */
2915 0x30, 0x03,
2916 0x2C, 0x07, /* bit at 0x20 is cleared here */
2917 0x2D, 0x87,
2918 0x2E, 0xAA,
2919 0x28, 0xE1, /* Set the FIFCrst bit here */
2920 0x28, 0xE0, /* Clear the FIFCrst bit here */
2921 0x00
2922 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002923 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002924 u8 MT2063B1_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002925 0x05, 0xF0,
2926 0x11, 0x10, /* New Enable AFCsd */
2927 0x19, 0x05,
2928 0x1A, 0x6C,
2929 0x1B, 0x24,
2930 0x1C, 0x28,
2931 0x1D, 0x8F,
2932 0x1E, 0x14,
2933 0x1F, 0x8F,
2934 0x20, 0x57,
2935 0x22, 0x21, /* New - ver 1.03 */
2936 0x23, 0x3C, /* New - ver 1.10 */
2937 0x24, 0x20, /* New - ver 1.03 */
2938 0x2C, 0x24, /* bit at 0x20 is cleared below */
2939 0x2D, 0x87, /* FIFFQ=0 */
2940 0x2F, 0xF3,
2941 0x30, 0x0C, /* New - ver 1.11 */
2942 0x31, 0x1B, /* New - ver 1.11 */
2943 0x2C, 0x04, /* bit at 0x20 is cleared here */
2944 0x28, 0xE1, /* Set the FIFCrst bit here */
2945 0x28, 0xE0, /* Clear the FIFCrst bit here */
2946 0x00
2947 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002948 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002949 u8 MT2063B3_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002950 0x05, 0xF0,
2951 0x19, 0x3D,
2952 0x2C, 0x24, /* bit at 0x20 is cleared below */
2953 0x2C, 0x04, /* bit at 0x20 is cleared here */
2954 0x28, 0xE1, /* Set the FIFCrst bit here */
2955 0x28, 0xE0, /* Clear the FIFCrst bit here */
2956 0x00
2957 };
2958
2959 /* Verify that the handle passed points to a valid tuner */
2960 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002961 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002962
2963 /* Read the Part/Rev code from the tuner */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002964 status = MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2965 MT2063_REG_PART_REV, pInfo->reg, 1);
2966 if (status < 0)
2967 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002968
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002969 /* Check the part/rev code */
2970 if (((pInfo->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2971 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2972 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
2973 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002974
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002975 /* Check the 2nd byte of the Part/Rev code from the tuner */
2976 status = MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2977 MT2063_REG_RSVD_3B,
2978 &pInfo->reg[MT2063_REG_RSVD_3B], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002979
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002980 if (status >= 0
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002981 &&((pInfo->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002982 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002983
2984 /* Reset the tuner */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002985 status = MT2063_WriteSub(pInfo->hUserData,
2986 pInfo->address,
2987 MT2063_REG_LO2CQ_3, &all_resets, 1);
2988 if (status < 0)
2989 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002990
2991 /* change all of the default values that vary from the HW reset values */
2992 /* def = (pInfo->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2993 switch (pInfo->reg[MT2063_REG_PART_REV]) {
2994 case MT2063_B3:
2995 def = MT2063B3_defaults;
2996 break;
2997
2998 case MT2063_B1:
2999 def = MT2063B1_defaults;
3000 break;
3001
3002 case MT2063_B0:
3003 def = MT2063B0_defaults;
3004 break;
3005
3006 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003007 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003008 break;
3009 }
3010
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003011 while (status >= 0 && *def) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003012 u8 reg = *def++;
3013 u8 val = *def++;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003014 status = MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg,
3015 &val, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003016 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003017 if (status < 0)
3018 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003019
3020 /* Wait for FIFF location to complete. */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003021 FCRUN = 1;
3022 maxReads = 10;
3023 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3024 msleep(2);
3025 status = MT2063_ReadSub(pInfo->hUserData,
3026 pInfo->address,
3027 MT2063_REG_XO_STATUS,
3028 &pInfo->
3029 reg[MT2063_REG_XO_STATUS], 1);
3030 FCRUN = (pInfo->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003031 }
3032
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003033 if (FCRUN != 0)
3034 return -ENODEV;
3035
3036 status = MT2063_ReadSub(pInfo->hUserData, pInfo->address,
3037 MT2063_REG_FIFFC,
3038 &pInfo->reg[MT2063_REG_FIFFC], 1);
3039 if (status < 0)
3040 return status;
3041
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003042 /* Read back all the registers from the tuner */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003043 status = MT2063_ReadSub(pInfo->hUserData,
3044 pInfo->address,
3045 MT2063_REG_PART_REV,
3046 pInfo->reg, MT2063_REG_END_REGS);
3047 if (status < 0)
3048 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003049
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003050 /* Initialize the tuner state. */
3051 pInfo->tuner_id = pInfo->reg[MT2063_REG_PART_REV];
3052 pInfo->AS_Data.f_ref = MT2063_REF_FREQ;
3053 pInfo->AS_Data.f_if1_Center = (pInfo->AS_Data.f_ref / 8) *
3054 ((u32) pInfo->reg[MT2063_REG_FIFFC] + 640);
3055 pInfo->AS_Data.f_if1_bw = MT2063_IF1_BW;
3056 pInfo->AS_Data.f_out = 43750000UL;
3057 pInfo->AS_Data.f_out_bw = 6750000UL;
3058 pInfo->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3059 pInfo->AS_Data.f_LO1_Step = pInfo->AS_Data.f_ref / 64;
3060 pInfo->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3061 pInfo->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3062 pInfo->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3063 pInfo->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3064 pInfo->AS_Data.f_if1_Request = pInfo->AS_Data.f_if1_Center;
3065 pInfo->AS_Data.f_LO1 = 2181000000UL;
3066 pInfo->AS_Data.f_LO2 = 1486249786UL;
3067 pInfo->f_IF1_actual = pInfo->AS_Data.f_if1_Center;
3068 pInfo->AS_Data.f_in = pInfo->AS_Data.f_LO1 - pInfo->f_IF1_actual;
3069 pInfo->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3070 pInfo->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3071 pInfo->num_regs = MT2063_REG_END_REGS;
3072 pInfo->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3073 pInfo->ctfilt_sw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003074
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003075 pInfo->CTFiltMax[0] = 69230000;
3076 pInfo->CTFiltMax[1] = 105770000;
3077 pInfo->CTFiltMax[2] = 140350000;
3078 pInfo->CTFiltMax[3] = 177110000;
3079 pInfo->CTFiltMax[4] = 212860000;
3080 pInfo->CTFiltMax[5] = 241130000;
3081 pInfo->CTFiltMax[6] = 274370000;
3082 pInfo->CTFiltMax[7] = 309820000;
3083 pInfo->CTFiltMax[8] = 342450000;
3084 pInfo->CTFiltMax[9] = 378870000;
3085 pInfo->CTFiltMax[10] = 416210000;
3086 pInfo->CTFiltMax[11] = 456500000;
3087 pInfo->CTFiltMax[12] = 495790000;
3088 pInfo->CTFiltMax[13] = 534530000;
3089 pInfo->CTFiltMax[14] = 572610000;
3090 pInfo->CTFiltMax[15] = 598970000;
3091 pInfo->CTFiltMax[16] = 635910000;
3092 pInfo->CTFiltMax[17] = 672130000;
3093 pInfo->CTFiltMax[18] = 714840000;
3094 pInfo->CTFiltMax[19] = 739660000;
3095 pInfo->CTFiltMax[20] = 770410000;
3096 pInfo->CTFiltMax[21] = 814660000;
3097 pInfo->CTFiltMax[22] = 846950000;
3098 pInfo->CTFiltMax[23] = 867820000;
3099 pInfo->CTFiltMax[24] = 915980000;
3100 pInfo->CTFiltMax[25] = 947450000;
3101 pInfo->CTFiltMax[26] = 983110000;
3102 pInfo->CTFiltMax[27] = 1021630000;
3103 pInfo->CTFiltMax[28] = 1061870000;
3104 pInfo->CTFiltMax[29] = 1098330000;
3105 pInfo->CTFiltMax[30] = 1138990000;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003106
3107 /*
3108 ** Fetch the FCU osc value and use it and the fRef value to
3109 ** scale all of the Band Max values
3110 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003111
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003112 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3113 status = MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3114 MT2063_REG_CTUNE_CTRL,
3115 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
3116 if (status < 0)
3117 return status;
3118 /* Read the ClearTune filter calibration value */
3119 status = MT2063_ReadSub(pInfo->hUserData, pInfo->address,
3120 MT2063_REG_FIFFC,
3121 &pInfo->reg[MT2063_REG_FIFFC], 1);
3122 if (status < 0)
3123 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003124
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003125 fcu_osc = pInfo->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003126
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003127 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3128 status = MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3129 MT2063_REG_CTUNE_CTRL,
3130 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
3131 if (status < 0)
3132 return status;
3133
3134 /* Adjust each of the values in the ClearTune filter cross-over table */
3135 for (i = 0; i < 31; i++)
3136 pInfo->CTFiltMax[i] =(pInfo->CTFiltMax[i] / 768) * (fcu_osc + 640);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003137
3138 return (status);
3139}
3140
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003141/****************************************************************************
3142**
3143** Name: MT2063_SetParam
3144**
3145** Description: Sets a tuning algorithm parameter.
3146**
3147** This function provides access to the internals of the
3148** tuning algorithm. You can override many of the tuning
3149** algorithm defaults using this function.
3150**
3151** Parameters: h - Tuner handle (returned by MT2063_Open)
3152** param - Tuning algorithm parameter
3153** (see enum MT2063_Param)
3154** nValue - value to be set
3155**
3156** param Description
3157** ---------------------- --------------------------------
3158** MT2063_SRO_FREQ crystal frequency
3159** MT2063_STEPSIZE minimum tuning step size
3160** MT2063_LO1_FREQ LO1 frequency
3161** MT2063_LO1_STEPSIZE LO1 minimum step size
3162** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
3163** MT2063_IF1_REQUEST Requested 1st IF
3164** MT2063_ZIF_BW zero-IF bandwidth
3165** MT2063_LO2_FREQ LO2 frequency
3166** MT2063_LO2_STEPSIZE LO2 minimum step size
3167** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
3168** MT2063_OUTPUT_FREQ output center frequency
3169** MT2063_OUTPUT_BW output bandwidth
3170** MT2063_LO_SEPARATION min inter-tuner LO separation
3171** MT2063_MAX_HARM1 max # of intra-tuner harmonics
3172** MT2063_MAX_HARM2 max # of inter-tuner harmonics
3173** MT2063_RCVR_MODE Predefined modes
3174** MT2063_LNA_RIN Set LNA Rin (*)
3175** MT2063_LNA_TGT Set target power level at LNA (*)
3176** MT2063_PD1_TGT Set target power level at PD1 (*)
3177** MT2063_PD2_TGT Set target power level at PD2 (*)
3178** MT2063_ACLNA_MAX LNA attenuator limit (*)
3179** MT2063_ACRF_MAX RF attenuator limit (*)
3180** MT2063_ACFIF_MAX FIF attenuator limit (*)
3181** MT2063_DNC_OUTPUT_ENABLE DNC output selection
3182** MT2063_VGAGC VGA gain code
3183** MT2063_VGAOI VGA output current
3184** MT2063_TAGC TAGC setting
3185** MT2063_AMPGC AMP gain code
3186** MT2063_AVOID_DECT Avoid DECT Frequencies
3187** MT2063_CTFILT_SW Cleartune filter selection
3188**
3189** (*) This parameter is set by MT2063_RCVR_MODE, do not call
3190** additionally.
3191**
3192** Usage: status |= MT2063_SetParam(hMT2063,
3193** MT2063_STEPSIZE,
3194** 50000);
3195**
3196** Returns: status:
3197** MT_OK - No errors
3198** MT_INV_HANDLE - Invalid tuner handle
3199** MT_ARG_NULL - Null pointer argument passed
3200** MT_ARG_RANGE - Invalid parameter requested
3201** or set value out of range
3202** or non-writable parameter
3203**
3204** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3205**
3206** See Also: MT2063_GetParam, MT2063_Open
3207**
3208** Revision History:
3209**
3210** SCR Date Author Description
3211** -------------------------------------------------------------------------
3212** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3213** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
3214** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
3215** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
3216** Split SetParam up to ACLNA / ACLNA_MAX
3217** removed ACLNA_INRC/DECR (+RF & FIF)
3218** removed GCUAUTO / BYPATNDN/UP
3219** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3220** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3221** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3222**
3223****************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003224static u32 MT2063_SetParam(struct MT2063_Info_t *pInfo, enum MT2063_Param param, u32 nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003225{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003226 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003227 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003228
3229 /* Verify that the handle passed points to a valid tuner */
3230 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003231 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003232
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003233 switch (param) {
3234 /* crystal frequency */
3235 case MT2063_SRO_FREQ:
3236 pInfo->AS_Data.f_ref = nValue;
3237 pInfo->AS_Data.f_LO1_FracN_Avoid = 0;
3238 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
3239 pInfo->AS_Data.f_LO1_Step = nValue / 64;
3240 pInfo->AS_Data.f_if1_Center =
3241 (pInfo->AS_Data.f_ref / 8) *
3242 (pInfo->reg[MT2063_REG_FIFFC] + 640);
3243 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003244
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003245 /* minimum tuning step size */
3246 case MT2063_STEPSIZE:
3247 pInfo->AS_Data.f_LO2_Step = nValue;
3248 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003249
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003250 /* LO1 frequency */
3251 case MT2063_LO1_FREQ:
3252 {
3253 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3254 /* Capture the Divider and Numerator portions of other LO */
3255 u8 tempLO2CQ[3];
3256 u8 tempLO2C[3];
3257 u8 tmpOneShot;
3258 u32 Div, FracN;
3259 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003260
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003261 /* Buffer the queue for restoration later and get actual LO2 values. */
3262 status |=
3263 MT2063_ReadSub(pInfo->hUserData,
3264 pInfo->address,
3265 MT2063_REG_LO2CQ_1,
3266 &(tempLO2CQ[0]), 3);
3267 status |=
3268 MT2063_ReadSub(pInfo->hUserData,
3269 pInfo->address,
3270 MT2063_REG_LO2C_1,
3271 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003272
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003273 /* clear the one-shot bits */
3274 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
3275 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003276
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003277 /* only write the queue values if they are different from the actual. */
3278 if ((tempLO2CQ[0] != tempLO2C[0]) ||
3279 (tempLO2CQ[1] != tempLO2C[1]) ||
3280 (tempLO2CQ[2] != tempLO2C[2])) {
3281 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003282 status |=
3283 MT2063_WriteSub(pInfo->hUserData,
3284 pInfo->address,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003285 MT2063_REG_LO2CQ_1,
3286 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003287
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003288 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003289 /* cache the bytes just written. */
3290 pInfo->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003291 tempLO2C[0];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003292 pInfo->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003293 tempLO2C[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003294 pInfo->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003295 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003296 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003297 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003298 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003299
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003300 /* Calculate the Divider and Numberator components of LO1 */
3301 status =
3302 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
3303 pInfo->AS_Data.f_ref /
3304 64,
3305 pInfo->AS_Data.f_ref);
3306 pInfo->reg[MT2063_REG_LO1CQ_1] =
3307 (u8) (Div & 0x00FF);
3308 pInfo->reg[MT2063_REG_LO1CQ_2] =
3309 (u8) (FracN);
3310 status |=
3311 MT2063_WriteSub(pInfo->hUserData,
3312 pInfo->address,
3313 MT2063_REG_LO1CQ_1,
3314 &pInfo->
3315 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003316
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003317 /* set the one-shot bit to load the pair of LO values */
3318 tmpOneShot = tempLO2CQ[2] | 0xE0;
3319 status |=
3320 MT2063_WriteSub(pInfo->hUserData,
3321 pInfo->address,
3322 MT2063_REG_LO2CQ_3,
3323 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003324
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003325 /* only restore the queue values if they were different from the actual. */
3326 if (restore) {
3327 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003328 status |=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003329 MT2063_WriteSub(pInfo->hUserData,
3330 pInfo->address,
3331 MT2063_REG_LO2CQ_1,
3332 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003333
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003334 /* cache the bytes just written. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003335 pInfo->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003336 tempLO2CQ[0];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003337 pInfo->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003338 tempLO2CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003339 pInfo->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003340 tempLO2CQ[2];
3341 }
3342
3343 MT2063_GetParam(pInfo->hUserData,
3344 MT2063_LO1_FREQ,
3345 &pInfo->AS_Data.f_LO1);
3346 }
3347 break;
3348
3349 /* LO1 minimum step size */
3350 case MT2063_LO1_STEPSIZE:
3351 pInfo->AS_Data.f_LO1_Step = nValue;
3352 break;
3353
3354 /* LO1 FracN keep-out region */
3355 case MT2063_LO1_FRACN_AVOID_PARAM:
3356 pInfo->AS_Data.f_LO1_FracN_Avoid = nValue;
3357 break;
3358
3359 /* Requested 1st IF */
3360 case MT2063_IF1_REQUEST:
3361 pInfo->AS_Data.f_if1_Request = nValue;
3362 break;
3363
3364 /* zero-IF bandwidth */
3365 case MT2063_ZIF_BW:
3366 pInfo->AS_Data.f_zif_bw = nValue;
3367 break;
3368
3369 /* LO2 frequency */
3370 case MT2063_LO2_FREQ:
3371 {
3372 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3373 /* Capture the Divider and Numerator portions of other LO */
3374 u8 tempLO1CQ[2];
3375 u8 tempLO1C[2];
3376 u32 Div2;
3377 u32 FracN2;
3378 u8 tmpOneShot;
3379 u8 restore = 0;
3380
3381 /* Buffer the queue for restoration later and get actual LO2 values. */
3382 status |=
3383 MT2063_ReadSub(pInfo->hUserData,
3384 pInfo->address,
3385 MT2063_REG_LO1CQ_1,
3386 &(tempLO1CQ[0]), 2);
3387 status |=
3388 MT2063_ReadSub(pInfo->hUserData,
3389 pInfo->address,
3390 MT2063_REG_LO1C_1,
3391 &(tempLO1C[0]), 2);
3392
3393 /* only write the queue values if they are different from the actual. */
3394 if ((tempLO1CQ[0] != tempLO1C[0])
3395 || (tempLO1CQ[1] != tempLO1C[1])) {
3396 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003397 status |=
3398 MT2063_WriteSub(pInfo->hUserData,
3399 pInfo->address,
3400 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003401 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003402
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003403 /* cache the bytes just written. */
3404 pInfo->reg[MT2063_REG_LO1CQ_1] =
3405 tempLO1C[0];
3406 pInfo->reg[MT2063_REG_LO1CQ_2] =
3407 tempLO1C[1];
3408 restore = 1;
3409 }
3410
3411 /* Calculate the Divider and Numberator components of LO2 */
3412 status =
3413 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
3414 pInfo->AS_Data.f_ref /
3415 8191,
3416 pInfo->AS_Data.f_ref);
3417 pInfo->reg[MT2063_REG_LO2CQ_1] =
3418 (u8) ((Div2 << 1) |
3419 ((FracN2 >> 12) & 0x01)) & 0xFF;
3420 pInfo->reg[MT2063_REG_LO2CQ_2] =
3421 (u8) ((FracN2 >> 4) & 0xFF);
3422 pInfo->reg[MT2063_REG_LO2CQ_3] =
3423 (u8) ((FracN2 & 0x0F));
3424 status |=
3425 MT2063_WriteSub(pInfo->hUserData,
3426 pInfo->address,
3427 MT2063_REG_LO1CQ_1,
3428 &pInfo->
3429 reg[MT2063_REG_LO1CQ_1], 3);
3430
3431 /* set the one-shot bit to load the LO values */
3432 tmpOneShot =
3433 pInfo->reg[MT2063_REG_LO2CQ_3] | 0xE0;
3434 status |=
3435 MT2063_WriteSub(pInfo->hUserData,
3436 pInfo->address,
3437 MT2063_REG_LO2CQ_3,
3438 &tmpOneShot, 1);
3439
3440 /* only restore LO1 queue value if they were different from the actual. */
3441 if (restore) {
3442 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003443 status |=
3444 MT2063_WriteSub(pInfo->hUserData,
3445 pInfo->address,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003446 MT2063_REG_LO1CQ_1,
3447 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003448
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003449 /* cache the bytes just written. */
3450 pInfo->reg[MT2063_REG_LO1CQ_1] =
3451 tempLO1CQ[0];
3452 pInfo->reg[MT2063_REG_LO1CQ_2] =
3453 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003454 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003455
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003456 MT2063_GetParam(pInfo->hUserData,
3457 MT2063_LO2_FREQ,
3458 &pInfo->AS_Data.f_LO2);
3459 }
3460 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003461
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003462 /* LO2 minimum step size */
3463 case MT2063_LO2_STEPSIZE:
3464 pInfo->AS_Data.f_LO2_Step = nValue;
3465 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003466
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003467 /* LO2 FracN keep-out region */
3468 case MT2063_LO2_FRACN_AVOID:
3469 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue;
3470 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003471
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003472 /* output center frequency */
3473 case MT2063_OUTPUT_FREQ:
3474 pInfo->AS_Data.f_out = nValue;
3475 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003476
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003477 /* output bandwidth */
3478 case MT2063_OUTPUT_BW:
3479 pInfo->AS_Data.f_out_bw = nValue + 750000;
3480 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003481
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003482 /* min inter-tuner LO separation */
3483 case MT2063_LO_SEPARATION:
3484 pInfo->AS_Data.f_min_LO_Separation = nValue;
3485 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003486
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003487 /* max # of intra-tuner harmonics */
3488 case MT2063_MAX_HARM1:
3489 pInfo->AS_Data.maxH1 = nValue;
3490 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003491
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003492 /* max # of inter-tuner harmonics */
3493 case MT2063_MAX_HARM2:
3494 pInfo->AS_Data.maxH2 = nValue;
3495 break;
3496
3497 case MT2063_RCVR_MODE:
3498 status |=
3499 MT2063_SetReceiverMode(pInfo,
3500 (enum MT2063_RCVR_MODES)
3501 nValue);
3502 break;
3503
3504 /* Set LNA Rin -- nValue is desired value */
3505 case MT2063_LNA_RIN:
3506 val =
3507 (pInfo->
3508 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
3509 (nValue & 0x03);
3510 if (pInfo->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003511 status |=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003512 MT2063_SetReg(pInfo, MT2063_REG_CTRL_2C,
3513 val);
3514 }
3515 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003516
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003517 /* Set target power level at LNA -- nValue is desired value */
3518 case MT2063_LNA_TGT:
3519 val =
3520 (pInfo->
3521 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
3522 (nValue & 0x3F);
3523 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
3524 status |=
3525 MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT,
3526 val);
3527 }
3528 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003529
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003530 /* Set target power level at PD1 -- nValue is desired value */
3531 case MT2063_PD1_TGT:
3532 val =
3533 (pInfo->
3534 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
3535 (nValue & 0x3F);
3536 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
3537 status |=
3538 MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT,
3539 val);
3540 }
3541 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003542
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003543 /* Set target power level at PD2 -- nValue is desired value */
3544 case MT2063_PD2_TGT:
3545 val =
3546 (pInfo->
3547 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
3548 (nValue & 0x3F);
3549 if (pInfo->reg[MT2063_REG_PD2_TGT] != val) {
3550 status |=
3551 MT2063_SetReg(pInfo, MT2063_REG_PD2_TGT,
3552 val);
3553 }
3554 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003555
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003556 /* Set LNA atten limit -- nValue is desired value */
3557 case MT2063_ACLNA_MAX:
3558 val =
3559 (pInfo->
3560 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
3561 &
3562 0x1F);
3563 if (pInfo->reg[MT2063_REG_LNA_OV] != val) {
3564 status |=
3565 MT2063_SetReg(pInfo, MT2063_REG_LNA_OV,
3566 val);
3567 }
3568 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003569
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003570 /* Set RF atten limit -- nValue is desired value */
3571 case MT2063_ACRF_MAX:
3572 val =
3573 (pInfo->
3574 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
3575 &
3576 0x1F);
3577 if (pInfo->reg[MT2063_REG_RF_OV] != val) {
3578 status |=
3579 MT2063_SetReg(pInfo, MT2063_REG_RF_OV, val);
3580 }
3581 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003582
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003583 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
3584 case MT2063_ACFIF_MAX:
3585 if (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3
3586 && nValue > 5)
3587 nValue = 5;
3588 val =
3589 (pInfo->
3590 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
3591 &
3592 0x1F);
3593 if (pInfo->reg[MT2063_REG_FIF_OV] != val) {
3594 status |=
3595 MT2063_SetReg(pInfo, MT2063_REG_FIF_OV,
3596 val);
3597 }
3598 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003599
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003600 case MT2063_DNC_OUTPUT_ENABLE:
3601 /* selects, which DNC output is used */
3602 switch ((enum MT2063_DNC_Output_Enable)nValue) {
3603 case MT2063_DNC_NONE:
3604 {
3605 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3606 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3607 val)
3608 status |=
3609 MT2063_SetReg(pInfo,
3610 MT2063_REG_DNC_GAIN,
3611 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003612
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003613 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3614 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3615 val)
3616 status |=
3617 MT2063_SetReg(pInfo,
3618 MT2063_REG_VGA_GAIN,
3619 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003620
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003621 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3622 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3623 val)
3624 status |=
3625 MT2063_SetReg(pInfo,
3626 MT2063_REG_RSVD_20,
3627 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003628
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003629 break;
3630 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003631 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003632 {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003633 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3634 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3635 val)
3636 status |=
3637 MT2063_SetReg(pInfo,
3638 MT2063_REG_DNC_GAIN,
3639 val);
3640
3641 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3642 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3643 val)
3644 status |=
3645 MT2063_SetReg(pInfo,
3646 MT2063_REG_VGA_GAIN,
3647 val);
3648
3649 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3650 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3651 val)
3652 status |=
3653 MT2063_SetReg(pInfo,
3654 MT2063_REG_RSVD_20,
3655 val);
3656
3657 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003658 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003659 case MT2063_DNC_2:
3660 {
3661 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3662 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3663 val)
3664 status |=
3665 MT2063_SetReg(pInfo,
3666 MT2063_REG_DNC_GAIN,
3667 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003668
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003669 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3670 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3671 val)
3672 status |=
3673 MT2063_SetReg(pInfo,
3674 MT2063_REG_VGA_GAIN,
3675 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003676
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003677 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3678 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3679 val)
3680 status |=
3681 MT2063_SetReg(pInfo,
3682 MT2063_REG_RSVD_20,
3683 val);
3684
3685 break;
3686 }
3687 case MT2063_DNC_BOTH:
3688 {
3689 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3690 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3691 val)
3692 status |=
3693 MT2063_SetReg(pInfo,
3694 MT2063_REG_DNC_GAIN,
3695 val);
3696
3697 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3698 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3699 val)
3700 status |=
3701 MT2063_SetReg(pInfo,
3702 MT2063_REG_VGA_GAIN,
3703 val);
3704
3705 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3706 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3707 val)
3708 status |=
3709 MT2063_SetReg(pInfo,
3710 MT2063_REG_RSVD_20,
3711 val);
3712
3713 break;
3714 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003715 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003716 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003717 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003718 break;
3719
3720 case MT2063_VGAGC:
3721 /* Set VGA gain code */
3722 val =
3723 (pInfo->
3724 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
3725 ((nValue & 0x03) << 2);
3726 if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) {
3727 status |=
3728 MT2063_SetReg(pInfo, MT2063_REG_VGA_GAIN,
3729 val);
3730 }
3731 break;
3732
3733 case MT2063_VGAOI:
3734 /* Set VGA bias current */
3735 val =
3736 (pInfo->
3737 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
3738 (nValue & 0x07);
3739 if (pInfo->reg[MT2063_REG_RSVD_31] != val) {
3740 status |=
3741 MT2063_SetReg(pInfo, MT2063_REG_RSVD_31,
3742 val);
3743 }
3744 break;
3745
3746 case MT2063_TAGC:
3747 /* Set TAGC */
3748 val =
3749 (pInfo->
3750 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
3751 (nValue & 0x03);
3752 if (pInfo->reg[MT2063_REG_RSVD_1E] != val) {
3753 status |=
3754 MT2063_SetReg(pInfo, MT2063_REG_RSVD_1E,
3755 val);
3756 }
3757 break;
3758
3759 case MT2063_AMPGC:
3760 /* Set Amp gain code */
3761 val =
3762 (pInfo->
3763 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
3764 (nValue & 0x03);
3765 if (pInfo->reg[MT2063_REG_TEMP_SEL] != val) {
3766 status |=
3767 MT2063_SetReg(pInfo, MT2063_REG_TEMP_SEL,
3768 val);
3769 }
3770 break;
3771
3772 /* Avoid DECT Frequencies */
3773 case MT2063_AVOID_DECT:
3774 {
3775 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3776 (enum MT2063_DECT_Avoid_Type)nValue;
3777 if ((newAvoidSetting >=
3778 MT2063_NO_DECT_AVOIDANCE)
3779 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
3780 pInfo->AS_Data.avoidDECT =
3781 newAvoidSetting;
3782 }
3783 }
3784 break;
3785
3786 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3787 case MT2063_CTFILT_SW:
3788 pInfo->ctfilt_sw = (nValue & 0x01);
3789 break;
3790
3791 /* These parameters are read-only */
3792 case MT2063_IC_ADDR:
3793 case MT2063_MAX_OPEN:
3794 case MT2063_NUM_OPEN:
3795 case MT2063_INPUT_FREQ:
3796 case MT2063_IF1_ACTUAL:
3797 case MT2063_IF1_CENTER:
3798 case MT2063_IF1_BW:
3799 case MT2063_AS_ALG:
3800 case MT2063_EXCL_ZONES:
3801 case MT2063_SPUR_AVOIDED:
3802 case MT2063_NUM_SPURS:
3803 case MT2063_SPUR_PRESENT:
3804 case MT2063_ACLNA:
3805 case MT2063_ACRF:
3806 case MT2063_ACFIF:
3807 case MT2063_EOP:
3808 default:
3809 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003810 }
3811 return (status);
3812}
3813
3814/****************************************************************************
3815**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003816** Name: MT2063_ClearPowerMaskBits
3817**
3818** Description: Clears the power-down mask bits for various sections of
3819** the MT2063
3820**
3821** Parameters: h - Tuner handle (returned by MT2063_Open)
3822** Bits - Mask bits to be cleared.
3823**
3824** See definition of MT2063_Mask_Bits type for description
3825** of each of the power bits.
3826**
3827** Returns: status:
3828** MT_OK - No errors
3829** MT_INV_HANDLE - Invalid tuner handle
3830** MT_COMM_ERR - Serial bus communications error
3831**
3832** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3833**
3834** Revision History:
3835**
3836** SCR Date Author Description
3837** -------------------------------------------------------------------------
3838** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3839**
3840****************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03003841static u32 MT2063_ClearPowerMaskBits(struct MT2063_Info_t *pInfo, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003842{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003843 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003844
3845 /* Verify that the handle passed points to a valid tuner */
3846 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003847 return -ENODEV;
3848 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3849 if ((Bits & 0xFF00) != 0) {
3850 pInfo->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
3851 status |=
3852 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3853 MT2063_REG_PWR_2,
3854 &pInfo->reg[MT2063_REG_PWR_2], 1);
3855 }
3856 if ((Bits & 0xFF) != 0) {
3857 pInfo->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
3858 status |=
3859 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3860 MT2063_REG_PWR_1,
3861 &pInfo->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003862 }
3863
3864 return (status);
3865}
3866
3867/****************************************************************************
3868**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003869** Name: MT2063_SoftwareShutdown
3870**
3871** Description: Enables or disables software shutdown function. When
3872** Shutdown==1, any section whose power mask is set will be
3873** shutdown.
3874**
3875** Parameters: h - Tuner handle (returned by MT2063_Open)
3876** Shutdown - 1 = shutdown the masked sections, otherwise
3877** power all sections on
3878**
3879** Returns: status:
3880** MT_OK - No errors
3881** MT_INV_HANDLE - Invalid tuner handle
3882** MT_COMM_ERR - Serial bus communications error
3883**
3884** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3885**
3886** Revision History:
3887**
3888** SCR Date Author Description
3889** -------------------------------------------------------------------------
3890** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3891** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3892** correct wakeup of the LNA
3893**
3894****************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03003895static u32 MT2063_SoftwareShutdown(struct MT2063_Info_t *pInfo, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003896{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003897 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003898
3899 /* Verify that the handle passed points to a valid tuner */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003900 if (MT2063_IsValidHandle(pInfo) == 0)
3901 return -ENODEV;
3902 if (Shutdown == 1)
3903 pInfo->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
3904 else
3905 pInfo->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003906
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003907 status |=
3908 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3909 MT2063_REG_PWR_1,
3910 &pInfo->reg[MT2063_REG_PWR_1], 1);
3911
3912 if (Shutdown != 1) {
3913 pInfo->reg[MT2063_REG_BYP_CTRL] =
3914 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003915 status |=
3916 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003917 MT2063_REG_BYP_CTRL,
3918 &pInfo->reg[MT2063_REG_BYP_CTRL],
3919 1);
3920 pInfo->reg[MT2063_REG_BYP_CTRL] =
3921 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F);
3922 status |=
3923 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3924 MT2063_REG_BYP_CTRL,
3925 &pInfo->reg[MT2063_REG_BYP_CTRL],
3926 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003927 }
3928
3929 return (status);
3930}
3931
3932/****************************************************************************
3933**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003934** Name: MT2063_SetReg
3935**
3936** Description: Sets an MT2063 register.
3937**
3938** Parameters: h - Tuner handle (returned by MT2063_Open)
3939** reg - MT2063 register/subaddress location
3940** val - MT2063 register/subaddress value
3941**
3942** Returns: status:
3943** MT_OK - No errors
3944** MT_COMM_ERR - Serial bus communications error
3945** MT_INV_HANDLE - Invalid tuner handle
3946** MT_ARG_RANGE - Argument out of range
3947**
3948** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3949**
3950** Use this function if you need to override a default
3951** register value
3952**
3953** Revision History:
3954**
3955** SCR Date Author Description
3956** -------------------------------------------------------------------------
3957** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3958**
3959****************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003960static u32 MT2063_SetReg(struct MT2063_Info_t *pInfo, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003961{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003962 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003963
3964 /* Verify that the handle passed points to a valid tuner */
3965 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003966 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003967
3968 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003969 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003970
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003971 status = MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
3972 1);
3973 if (status >= 0)
3974 pInfo->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003975
3976 return (status);
3977}
3978
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003979static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003980{
3981 return f_ref * (f_LO / f_ref)
3982 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
3983}
3984
3985/****************************************************************************
3986**
3987** Name: fLO_FractionalTerm
3988**
3989** Description: Calculates the portion contributed by FracN / denom.
3990**
3991** This function preserves maximum precision without
3992** risk of overflow. It accurately calculates
3993** f_ref * num / denom to within 1 HZ with fixed math.
3994**
3995** Parameters: num - Fractional portion of the multiplier
3996** denom - denominator portion of the ratio
3997** This routine successfully handles denom values
3998** up to and including 2^18.
3999** f_Ref - SRO frequency. This calculation handles
4000** f_ref as two separate 14-bit fields.
4001** Therefore, a maximum value of 2^28-1
4002** may safely be used for f_ref. This is
4003** the genesis of the magic number "14" and the
4004** magic mask value of 0x03FFF.
4005**
4006** Returns: f_ref * num / denom
4007**
4008** Revision History:
4009**
4010** SCR Date Author Description
4011** -------------------------------------------------------------------------
4012** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4013**
4014****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004015static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
4016 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004017{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004018 u32 t1 = (f_ref >> 14) * num;
4019 u32 term1 = t1 / denom;
4020 u32 loss = t1 % denom;
4021 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004022 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
4023 return ((term1 << 14) + term2);
4024}
4025
4026/****************************************************************************
4027**
4028** Name: CalcLO1Mult
4029**
4030** Description: Calculates Integer divider value and the numerator
4031** value for a FracN PLL.
4032**
4033** This function assumes that the f_LO and f_Ref are
4034** evenly divisible by f_LO_Step.
4035**
4036** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4037** FracN - OUTPUT: Fractional portion of the multiplier
4038** f_LO - desired LO frequency.
4039** f_LO_Step - Minimum step size for the LO (in Hz).
4040** f_Ref - SRO frequency.
4041** f_Avoid - Range of PLL frequencies to avoid near
4042** integer multiples of f_Ref (in Hz).
4043**
4044** Returns: Recalculated LO frequency.
4045**
4046** Revision History:
4047**
4048** SCR Date Author Description
4049** -------------------------------------------------------------------------
4050** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4051**
4052****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004053static u32 MT2063_CalcLO1Mult(u32 * Div,
4054 u32 * FracN,
4055 u32 f_LO,
4056 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004057{
4058 /* Calculate the whole number portion of the divider */
4059 *Div = f_LO / f_Ref;
4060
4061 /* Calculate the numerator value (round to nearest f_LO_Step) */
4062 *FracN =
4063 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4064 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4065
4066 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
4067}
4068
4069/****************************************************************************
4070**
4071** Name: CalcLO2Mult
4072**
4073** Description: Calculates Integer divider value and the numerator
4074** value for a FracN PLL.
4075**
4076** This function assumes that the f_LO and f_Ref are
4077** evenly divisible by f_LO_Step.
4078**
4079** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4080** FracN - OUTPUT: Fractional portion of the multiplier
4081** f_LO - desired LO frequency.
4082** f_LO_Step - Minimum step size for the LO (in Hz).
4083** f_Ref - SRO frequency.
4084** f_Avoid - Range of PLL frequencies to avoid near
4085** integer multiples of f_Ref (in Hz).
4086**
4087** Returns: Recalculated LO frequency.
4088**
4089** Revision History:
4090**
4091** SCR Date Author Description
4092** -------------------------------------------------------------------------
4093** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4094**
4095****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004096static u32 MT2063_CalcLO2Mult(u32 * Div,
4097 u32 * FracN,
4098 u32 f_LO,
4099 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004100{
4101 /* Calculate the whole number portion of the divider */
4102 *Div = f_LO / f_Ref;
4103
4104 /* Calculate the numerator value (round to nearest f_LO_Step) */
4105 *FracN =
4106 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4107 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4108
4109 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
4110 8191);
4111}
4112
4113/****************************************************************************
4114**
4115** Name: FindClearTuneFilter
4116**
4117** Description: Calculate the corrrect ClearTune filter to be used for
4118** a given input frequency.
4119**
4120** Parameters: pInfo - ptr to tuner data structure
4121** f_in - RF input center frequency (in Hz).
4122**
4123** Returns: ClearTune filter number (0-31)
4124**
4125** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
4126**
4127** Revision History:
4128**
4129** SCR Date Author Description
4130** -------------------------------------------------------------------------
4131** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
4132** cross-over frequency values.
4133**
4134****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004135static u32 FindClearTuneFilter(struct MT2063_Info_t *pInfo, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004136{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004137 u32 RFBand;
4138 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004139
4140 /*
4141 ** Find RF Band setting
4142 */
4143 RFBand = 31; /* def when f_in > all */
4144 for (idx = 0; idx < 31; ++idx) {
4145 if (pInfo->CTFiltMax[idx] >= f_in) {
4146 RFBand = idx;
4147 break;
4148 }
4149 }
4150 return (RFBand);
4151}
4152
4153/****************************************************************************
4154**
4155** Name: MT2063_Tune
4156**
4157** Description: Change the tuner's tuned frequency to RFin.
4158**
4159** Parameters: h - Open handle to the tuner (from MT2063_Open).
4160** f_in - RF input center frequency (in Hz).
4161**
4162** Returns: status:
4163** MT_OK - No errors
4164** MT_INV_HANDLE - Invalid tuner handle
4165** MT_UPC_UNLOCK - Upconverter PLL unlocked
4166** MT_DNC_UNLOCK - Downconverter PLL unlocked
4167** MT_COMM_ERR - Serial bus communications error
4168** MT_SPUR_CNT_MASK - Count of avoided LO spurs
4169** MT_SPUR_PRESENT - LO spur possible in output
4170** MT_FIN_RANGE - Input freq out of range
4171** MT_FOUT_RANGE - Output freq out of range
4172** MT_UPC_RANGE - Upconverter freq out of range
4173** MT_DNC_RANGE - Downconverter freq out of range
4174**
4175** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
4176**
4177** MT_ReadSub - Read data from the two-wire serial bus
4178** MT_WriteSub - Write data to the two-wire serial bus
4179** MT_Sleep - Delay execution for x milliseconds
4180** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
4181**
4182** Revision History:
4183**
4184** SCR Date Author Description
4185** -------------------------------------------------------------------------
4186** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4187** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
4188** cross-over frequency values.
4189** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
4190** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
4191** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
4192**
4193****************************************************************************/
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004194static u32 MT2063_Tune(struct MT2063_Info_t *pInfo, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004195{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004196
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004197 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004198 u32 LO1; /* 1st LO register value */
4199 u32 Num1; /* Numerator for LO1 reg. value */
4200 u32 f_IF1; /* 1st IF requested */
4201 u32 LO2; /* 2nd LO register value */
4202 u32 Num2; /* Numerator for LO2 reg. value */
4203 u32 ofLO1, ofLO2; /* last time's LO frequencies */
4204 u32 ofin, ofout; /* last time's I/O frequencies */
4205 u8 fiffc = 0x80; /* FIFF center freq from tuner */
4206 u32 fiffof; /* Offset from FIFF center freq */
4207 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
4208 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
4209 u8 val;
4210 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004211
4212 /* Verify that the handle passed points to a valid tuner */
4213 if (MT2063_IsValidHandle(pInfo) == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004214 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004215
4216 /* Check the input and output frequency ranges */
4217 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004218 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004219
4220 if ((pInfo->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
4221 || (pInfo->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004222 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004223
4224 /*
4225 ** Save original LO1 and LO2 register values
4226 */
4227 ofLO1 = pInfo->AS_Data.f_LO1;
4228 ofLO2 = pInfo->AS_Data.f_LO2;
4229 ofin = pInfo->AS_Data.f_in;
4230 ofout = pInfo->AS_Data.f_out;
4231
4232 /*
4233 ** Find and set RF Band setting
4234 */
4235 if (pInfo->ctfilt_sw == 1) {
4236 val = (pInfo->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
4237 if (pInfo->reg[MT2063_REG_CTUNE_CTRL] != val) {
4238 status |=
4239 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_CTRL, val);
4240 }
4241 val = pInfo->reg[MT2063_REG_CTUNE_OV];
4242 RFBand = FindClearTuneFilter(pInfo, f_in);
4243 pInfo->reg[MT2063_REG_CTUNE_OV] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004244 (u8) ((pInfo->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004245 | RFBand);
4246 if (pInfo->reg[MT2063_REG_CTUNE_OV] != val) {
4247 status |=
4248 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_OV, val);
4249 }
4250 }
4251
4252 /*
4253 ** Read the FIFF Center Frequency from the tuner
4254 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004255 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004256 status |=
4257 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
4258 MT2063_REG_FIFFC,
4259 &pInfo->reg[MT2063_REG_FIFFC], 1);
4260 fiffc = pInfo->reg[MT2063_REG_FIFFC];
4261 }
4262 /*
4263 ** Assign in the requested values
4264 */
4265 pInfo->AS_Data.f_in = f_in;
4266 /* Request a 1st IF such that LO1 is on a step size */
4267 pInfo->AS_Data.f_if1_Request =
4268 MT2063_Round_fLO(pInfo->AS_Data.f_if1_Request + f_in,
4269 pInfo->AS_Data.f_LO1_Step,
4270 pInfo->AS_Data.f_ref) - f_in;
4271
4272 /*
4273 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
4274 ** desired LO1 frequency
4275 */
4276 MT2063_ResetExclZones(&pInfo->AS_Data);
4277
4278 f_IF1 = MT2063_ChooseFirstIF(&pInfo->AS_Data);
4279
4280 pInfo->AS_Data.f_LO1 =
4281 MT2063_Round_fLO(f_IF1 + f_in, pInfo->AS_Data.f_LO1_Step,
4282 pInfo->AS_Data.f_ref);
4283
4284 pInfo->AS_Data.f_LO2 =
4285 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4286 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4287
4288 /*
4289 ** Check for any LO spurs in the output bandwidth and adjust
4290 ** the LO settings to avoid them if needed
4291 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004292 status |= MT2063_AvoidSpurs(pInfo, &pInfo->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004293 /*
4294 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
4295 ** Recalculate the LO frequencies and the values to be placed
4296 ** in the tuning registers.
4297 */
4298 pInfo->AS_Data.f_LO1 =
4299 MT2063_CalcLO1Mult(&LO1, &Num1, pInfo->AS_Data.f_LO1,
4300 pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref);
4301 pInfo->AS_Data.f_LO2 =
4302 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4303 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4304 pInfo->AS_Data.f_LO2 =
4305 MT2063_CalcLO2Mult(&LO2, &Num2, pInfo->AS_Data.f_LO2,
4306 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4307
4308 /*
4309 ** Check the upconverter and downconverter frequency ranges
4310 */
4311 if ((pInfo->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
4312 || (pInfo->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
4313 status |= MT2063_UPC_RANGE;
4314 if ((pInfo->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
4315 || (pInfo->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
4316 status |= MT2063_DNC_RANGE;
4317 /* LO2 Lock bit was in a different place for B0 version */
4318 if (pInfo->tuner_id == MT2063_B0)
4319 LO2LK = 0x40;
4320
4321 /*
4322 ** If we have the same LO frequencies and we're already locked,
4323 ** then skip re-programming the LO registers.
4324 */
4325 if ((ofLO1 != pInfo->AS_Data.f_LO1)
4326 || (ofLO2 != pInfo->AS_Data.f_LO2)
4327 || ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
4328 (LO1LK | LO2LK))) {
4329 /*
4330 ** Calculate the FIFFOF register value
4331 **
4332 ** IF1_Actual
4333 ** FIFFOF = ------------ - 8 * FIFFC - 4992
4334 ** f_ref/64
4335 */
4336 fiffof =
4337 (pInfo->AS_Data.f_LO1 -
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004338 f_in) / (pInfo->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004339 4992;
4340 if (fiffof > 0xFF)
4341 fiffof = 0xFF;
4342
4343 /*
4344 ** Place all of the calculated values into the local tuner
4345 ** register fields.
4346 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004347 if (status >= 0) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004348 pInfo->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
4349 pInfo->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
4350 pInfo->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004351 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004352 pInfo->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
4353 pInfo->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004354
4355 /*
4356 ** Now write out the computed register values
4357 ** IMPORTANT: There is a required order for writing
4358 ** (0x05 must follow all the others).
4359 */
4360 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
4361 if (pInfo->tuner_id == MT2063_B0) {
4362 /* Re-write the one-shot bits to trigger the tune operation */
4363 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &pInfo->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
4364 }
4365 /* Write out the FIFF offset only if it's changing */
4366 if (pInfo->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004367 (u8) fiffof) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004368 pInfo->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004369 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004370 status |=
4371 MT2063_WriteSub(pInfo->hUserData,
4372 pInfo->address,
4373 MT2063_REG_FIFF_OFFSET,
4374 &pInfo->
4375 reg[MT2063_REG_FIFF_OFFSET],
4376 1);
4377 }
4378 }
4379
4380 /*
4381 ** Check for LO's locking
4382 */
4383
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004384 if (status >= 0) {
4385 status |= MT2063_GetLocked(pInfo);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004386 }
4387 /*
4388 ** If we locked OK, assign calculated data to MT2063_Info_t structure
4389 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004390 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004391 pInfo->f_IF1_actual = pInfo->AS_Data.f_LO1 - f_in;
4392 }
4393 }
4394
4395 return (status);
4396}
4397
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03004398static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004399 enum MTTune_atv_standard tv_type)
4400{
4401
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004402 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004403
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004404 s32 pict_car = 0;
4405 s32 pict2chanb_vsb = 0;
4406 s32 pict2chanb_snd = 0;
4407 s32 pict2snd1 = 0;
4408 s32 pict2snd2 = 0;
4409 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004410
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004411 s32 if_mid = 0;
4412 s32 rcvr_mode = 0;
4413 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004414
4415 switch (tv_type) {
4416 case MTTUNEA_PAL_B:{
4417 pict_car = 38900000;
4418 ch_bw = 8000000;
4419 pict2chanb_vsb = -1250000;
4420 pict2snd1 = 5500000;
4421 pict2snd2 = 5742000;
4422 rcvr_mode = 1;
4423 break;
4424 }
4425 case MTTUNEA_PAL_G:{
4426 pict_car = 38900000;
4427 ch_bw = 7000000;
4428 pict2chanb_vsb = -1250000;
4429 pict2snd1 = 5500000;
4430 pict2snd2 = 0;
4431 rcvr_mode = 1;
4432 break;
4433 }
4434 case MTTUNEA_PAL_I:{
4435 pict_car = 38900000;
4436 ch_bw = 8000000;
4437 pict2chanb_vsb = -1250000;
4438 pict2snd1 = 6000000;
4439 pict2snd2 = 0;
4440 rcvr_mode = 1;
4441 break;
4442 }
4443 case MTTUNEA_PAL_L:{
4444 pict_car = 38900000;
4445 ch_bw = 8000000;
4446 pict2chanb_vsb = -1250000;
4447 pict2snd1 = 6500000;
4448 pict2snd2 = 0;
4449 rcvr_mode = 1;
4450 break;
4451 }
4452 case MTTUNEA_PAL_MN:{
4453 pict_car = 38900000;
4454 ch_bw = 6000000;
4455 pict2chanb_vsb = -1250000;
4456 pict2snd1 = 4500000;
4457 pict2snd2 = 0;
4458 rcvr_mode = 1;
4459 break;
4460 }
4461 case MTTUNEA_PAL_DK:{
4462 pict_car = 38900000;
4463 ch_bw = 8000000;
4464 pict2chanb_vsb = -1250000;
4465 pict2snd1 = 6500000;
4466 pict2snd2 = 0;
4467 rcvr_mode = 1;
4468 break;
4469 }
4470 case MTTUNEA_DIGITAL:{
4471 pict_car = 36125000;
4472 ch_bw = 8000000;
4473 pict2chanb_vsb = -(ch_bw / 2);
4474 pict2snd1 = 0;
4475 pict2snd2 = 0;
4476 rcvr_mode = 2;
4477 break;
4478 }
4479 case MTTUNEA_FMRADIO:{
4480 pict_car = 38900000;
4481 ch_bw = 8000000;
4482 pict2chanb_vsb = -(ch_bw / 2);
4483 pict2snd1 = 0;
4484 pict2snd2 = 0;
4485 rcvr_mode = 4;
4486 //f_in -= 2900000;
4487 break;
4488 }
4489 case MTTUNEA_DVBC:{
4490 pict_car = 36125000;
4491 ch_bw = 8000000;
4492 pict2chanb_vsb = -(ch_bw / 2);
4493 pict2snd1 = 0;
4494 pict2snd2 = 0;
4495 rcvr_mode = MT2063_CABLE_QAM;
4496 break;
4497 }
4498 case MTTUNEA_DVBT:{
4499 pict_car = 36125000;
4500 ch_bw = bw_in; //8000000
4501 pict2chanb_vsb = -(ch_bw / 2);
4502 pict2snd1 = 0;
4503 pict2snd2 = 0;
4504 rcvr_mode = MT2063_OFFAIR_COFDM;
4505 break;
4506 }
4507 case MTTUNEA_UNKNOWN:
4508 break;
4509 default:
4510 break;
4511 }
4512
4513 pict2chanb_snd = pict2chanb_vsb - ch_bw;
4514 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
4515
4516 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
4517 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
4518 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
4519 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4520
4521 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
4522 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
4523 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4524
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004525 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004526}
4527
4528static int mt2063_init(struct dvb_frontend *fe)
4529{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004530 u32 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004531 struct mt2063_state *state = fe->tuner_priv;
4532
4533 status = MT2063_Open(0xC0, &(state->MT2063_ht), fe);
4534 status |= MT2063_SoftwareShutdown(state->MT2063_ht, 1);
4535 status |= MT2063_ClearPowerMaskBits(state->MT2063_ht, MT2063_ALL_SD);
4536
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004537 if (0 != status) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004538 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
4539 status);
4540 return -1;
4541 }
4542
4543 return 0;
4544}
4545
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004546static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
4547{
4548 int rc = 0;
4549
4550 //get tuner lock status
4551
4552 return rc;
4553}
4554
4555static int mt2063_get_state(struct dvb_frontend *fe,
4556 enum tuner_param param, struct tuner_state *state)
4557{
4558 struct mt2063_state *mt2063State = fe->tuner_priv;
4559
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004560 switch (param) {
4561 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004562 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004563 break;
4564 case DVBFE_TUNER_TUNERSTEP:
4565 break;
4566 case DVBFE_TUNER_IFFREQ:
4567 break;
4568 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004569 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004570 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004571 case DVBFE_TUNER_REFCLOCK:
4572 state->refclock =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004573 (u32)
4574 MT2063_GetLocked((void *) (mt2063State->MT2063_ht));
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004575 break;
4576 default:
4577 break;
4578 }
4579
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004580 return (int)state->refclock;
4581}
4582
4583static int mt2063_set_state(struct dvb_frontend *fe,
4584 enum tuner_param param, struct tuner_state *state)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004585{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004586 struct mt2063_state *mt2063State = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004587 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004588
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004589 switch (param) {
4590 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004591 //set frequency
4592
4593 status =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004594 MT_Tune_atv((void *) (mt2063State->MT2063_ht),
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004595 state->frequency, state->bandwidth,
4596 mt2063State->tv_type);
4597
4598 mt2063State->frequency = state->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004599 break;
4600 case DVBFE_TUNER_TUNERSTEP:
4601 break;
4602 case DVBFE_TUNER_IFFREQ:
4603 break;
4604 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004605 //set bandwidth
4606 mt2063State->bandwidth = state->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004607 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004608 case DVBFE_TUNER_REFCLOCK:
4609
4610 break;
4611 case DVBFE_TUNER_OPEN:
4612 status = MT2063_Open(MT2063_I2C, &(mt2063State->MT2063_ht), fe);
4613 break;
4614 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
4615 status = MT2063_SoftwareShutdown(mt2063State->MT2063_ht, 1);
4616 break;
4617 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
4618 status =
4619 MT2063_ClearPowerMaskBits(mt2063State->MT2063_ht,
4620 MT2063_ALL_SD);
4621 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004622 default:
4623 break;
4624 }
4625
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004626 return (int)status;
4627}
4628
4629static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004630{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004631 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004632
4633 fe->tuner_priv = NULL;
4634 kfree(state);
4635
4636 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004637}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004638
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004639static struct dvb_tuner_ops mt2063_ops = {
4640 .info = {
4641 .name = "MT2063 Silicon Tuner",
4642 .frequency_min = 45000000,
4643 .frequency_max = 850000000,
4644 .frequency_step = 0,
4645 },
4646
4647 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03004648 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004649 .get_status = mt2063_get_status,
4650 .get_state = mt2063_get_state,
4651 .set_state = mt2063_set_state,
4652 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004653};
4654
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004655struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4656 struct mt2063_config *config,
4657 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004658{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004659 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004660
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004661 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004662 if (state == NULL)
4663 goto error;
4664
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004665 state->config = config;
4666 state->i2c = i2c;
4667 state->frontend = fe;
4668 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004669 state->MT2063_init = false;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004670 fe->tuner_priv = state;
4671 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004672
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004673 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004674 return fe;
4675
4676error:
4677 kfree(state);
4678 return NULL;
4679}
4680
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004681EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004682MODULE_PARM_DESC(verbose, "Set Verbosity level");
4683
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004684MODULE_AUTHOR("Henry");
4685MODULE_DESCRIPTION("MT2063 Silicon tuner");
4686MODULE_LICENSE("GPL");