blob: 534e970efaaa905d4841d456e2ad672978f038d6 [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 Chehab29a0a4f2011-07-20 23:44:10 -030019/* FIXME: Those two 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 Chehab29a0a4f2011-07-20 23:44:10 -030024
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030025/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030026#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030027
28/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
29#define MT2063_SPUR_CNT_MASK (0x001f0000)
30#define MT2063_SPUR_SHIFT (16)
31
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030032/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
33#define MT2063_UPC_RANGE (0x04000000)
34
35/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
36#define MT2063_DNC_RANGE (0x08000000)
37
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030038/*
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030039 * Data Types
40 */
41
42/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030043 * Constant defining the version of the following structure
44 * and therefore the API for this code.
45 *
46 * When compiling the tuner driver, the preprocessor will
47 * check against this version number to make sure that
48 * it matches the version that the tuner driver knows about.
49 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030050
51/* DECT Frequency Avoidance */
52#define MT2063_DECT_AVOID_US_FREQS 0x00000001
53
54#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
55
56#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
57
58#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
59
60enum MT2063_DECT_Avoid_Type {
61 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
62 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
63 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
64 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
65};
66
67#define MT2063_MAX_ZONES 48
68
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030069struct MT2063_ExclZone_t {
70 u32 min_;
71 u32 max_;
72 struct MT2063_ExclZone_t *next_;
73};
74
75/*
76 * Structure of data needed for Spur Avoidance
77 */
78struct MT2063_AvoidSpursData_t {
79 u32 nAS_Algorithm;
80 u32 f_ref;
81 u32 f_in;
82 u32 f_LO1;
83 u32 f_if1_Center;
84 u32 f_if1_Request;
85 u32 f_if1_bw;
86 u32 f_LO2;
87 u32 f_out;
88 u32 f_out_bw;
89 u32 f_LO1_Step;
90 u32 f_LO2_Step;
91 u32 f_LO1_FracN_Avoid;
92 u32 f_LO2_FracN_Avoid;
93 u32 f_zif_bw;
94 u32 f_min_LO_Separation;
95 u32 maxH1;
96 u32 maxH2;
97 enum MT2063_DECT_Avoid_Type avoidDECT;
98 u32 bSpurPresent;
99 u32 bSpurAvoided;
100 u32 nSpursFound;
101 u32 nZones;
102 struct MT2063_ExclZone_t *freeZones;
103 struct MT2063_ExclZone_t *usedZones;
104 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
105};
106
107/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300108 * Parameter for function MT2063_SetPowerMask that specifies the power down
109 * of various sections of the MT2063.
110 */
111enum MT2063_Mask_Bits {
112 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
113 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
114 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
115 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
116 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
117 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
118 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
119 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
120 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
121 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
122 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
123 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
124 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
125 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
126 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
127};
128
129/*
130 * Parameter for function MT2063_GetParam & MT2063_SetParam that
131 * specifies the tuning algorithm parameter to be read/written.
132 */
133enum MT2063_Param {
134 /* tuner address set by MT2063_Open() */
135 MT2063_IC_ADDR,
136
137 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
138 MT2063_MAX_OPEN,
139
140 /* current number of open MT2063 tuners set by MT2063_Open() */
141 MT2063_NUM_OPEN,
142
143 /* crystal frequency (default: 16000000 Hz) */
144 MT2063_SRO_FREQ,
145
146 /* min tuning step size (default: 50000 Hz) */
147 MT2063_STEPSIZE,
148
149 /* input center frequency set by MT2063_Tune() */
150 MT2063_INPUT_FREQ,
151
152 /* LO1 Frequency set by MT2063_Tune() */
153 MT2063_LO1_FREQ,
154
155 /* LO1 minimum step size (default: 250000 Hz) */
156 MT2063_LO1_STEPSIZE,
157
158 /* LO1 FracN keep-out region (default: 999999 Hz) */
159 MT2063_LO1_FRACN_AVOID_PARAM,
160
161 /* Current 1st IF in use set by MT2063_Tune() */
162 MT2063_IF1_ACTUAL,
163
164 /* Requested 1st IF set by MT2063_Tune() */
165 MT2063_IF1_REQUEST,
166
167 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
168 MT2063_IF1_CENTER,
169
170 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
171 MT2063_IF1_BW,
172
173 /* zero-IF bandwidth (default: 2000000 Hz) */
174 MT2063_ZIF_BW,
175
176 /* LO2 Frequency set by MT2063_Tune() */
177 MT2063_LO2_FREQ,
178
179 /* LO2 minimum step size (default: 50000 Hz) */
180 MT2063_LO2_STEPSIZE,
181
182 /* LO2 FracN keep-out region (default: 374999 Hz) */
183 MT2063_LO2_FRACN_AVOID,
184
185 /* output center frequency set by MT2063_Tune() */
186 MT2063_OUTPUT_FREQ,
187
188 /* output bandwidth set by MT2063_Tune() */
189 MT2063_OUTPUT_BW,
190
191 /* min inter-tuner LO separation (default: 1000000 Hz) */
192 MT2063_LO_SEPARATION,
193
194 /* ID of avoid-spurs algorithm in use compile-time constant */
195 MT2063_AS_ALG,
196
197 /* max # of intra-tuner harmonics (default: 15) */
198 MT2063_MAX_HARM1,
199
200 /* max # of inter-tuner harmonics (default: 7) */
201 MT2063_MAX_HARM2,
202
203 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
204 MT2063_EXCL_ZONES,
205
206 /* # of spurs found/avoided set by MT2063_Tune() */
207 MT2063_NUM_SPURS,
208
209 /* >0 spurs avoided set by MT2063_Tune() */
210 MT2063_SPUR_AVOIDED,
211
212 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
213 MT2063_SPUR_PRESENT,
214
215 /* Receiver Mode for some parameters. 1 is DVB-T */
216 MT2063_RCVR_MODE,
217
218 /* directly set LNA attenuation, parameter is value to set */
219 MT2063_ACLNA,
220
221 /* maximum LNA attenuation, parameter is value to set */
222 MT2063_ACLNA_MAX,
223
224 /* directly set ATN attenuation. Paremeter is value to set. */
225 MT2063_ACRF,
226
227 /* maxium ATN attenuation. Paremeter is value to set. */
228 MT2063_ACRF_MAX,
229
230 /* directly set FIF attenuation. Paremeter is value to set. */
231 MT2063_ACFIF,
232
233 /* maxium FIF attenuation. Paremeter is value to set. */
234 MT2063_ACFIF_MAX,
235
236 /* LNA Rin */
237 MT2063_LNA_RIN,
238
239 /* Power Detector LNA level target */
240 MT2063_LNA_TGT,
241
242 /* Power Detector 1 level */
243 MT2063_PD1,
244
245 /* Power Detector 1 level target */
246 MT2063_PD1_TGT,
247
248 /* Power Detector 2 level */
249 MT2063_PD2,
250
251 /* Power Detector 2 level target */
252 MT2063_PD2_TGT,
253
254 /* Selects, which DNC is activ */
255 MT2063_DNC_OUTPUT_ENABLE,
256
257 /* VGA gain code */
258 MT2063_VGAGC,
259
260 /* VGA bias current */
261 MT2063_VGAOI,
262
263 /* TAGC, determins the speed of the AGC */
264 MT2063_TAGC,
265
266 /* AMP gain code */
267 MT2063_AMPGC,
268
269 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
270 MT2063_AVOID_DECT,
271
272 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
273 MT2063_CTFILT_SW,
274
275 MT2063_EOP /* last entry in enumerated list */
276};
277
278/*
279 * Parameter for selecting tuner mode
280 */
281enum MT2063_RCVR_MODES {
282 MT2063_CABLE_QAM = 0, /* Digital cable */
283 MT2063_CABLE_ANALOG, /* Analog cable */
284 MT2063_OFFAIR_COFDM, /* Digital offair */
285 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
286 MT2063_OFFAIR_ANALOG, /* Analog offair */
287 MT2063_OFFAIR_8VSB, /* Analog offair */
288 MT2063_NUM_RCVR_MODES
289};
290
291/*
292 * Possible values for MT2063_DNC_OUTPUT
293 */
294enum MT2063_DNC_Output_Enable {
295 MT2063_DNC_NONE = 0,
296 MT2063_DNC_1,
297 MT2063_DNC_2,
298 MT2063_DNC_BOTH
299};
300
301/*
302** Two-wire serial bus subaddresses of the tuner registers.
303** Also known as the tuner's register addresses.
304*/
305enum MT2063_Register_Offsets {
306 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
307 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
308 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
309 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
310 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
311 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
312 MT2063_REG_RSVD_06, /* 0x06: Reserved */
313 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
314 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
315 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
316 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
317 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
318 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
319 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
320 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
321 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
322 MT2063_REG_RSVD_10, /* 0x10: Reserved */
323 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
324 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
325 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
326 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
327 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
328 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
329 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
330 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
331 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
332 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
333 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
334 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
335 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
336 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
337 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
338 MT2063_REG_RSVD_20, /* 0x20: Reserved */
339 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
340 MT2063_REG_RSVD_22, /* 0x22: Reserved */
341 MT2063_REG_RSVD_23, /* 0x23: Reserved */
342 MT2063_REG_RSVD_24, /* 0x24: Reserved */
343 MT2063_REG_RSVD_25, /* 0x25: Reserved */
344 MT2063_REG_RSVD_26, /* 0x26: Reserved */
345 MT2063_REG_RSVD_27, /* 0x27: Reserved */
346 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
347 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
348 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
349 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
350 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
351 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
352 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
353 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
354 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
355 MT2063_REG_RSVD_31, /* 0x31: Reserved */
356 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
357 MT2063_REG_RSVD_33, /* 0x33: Reserved */
358 MT2063_REG_RSVD_34, /* 0x34: Reserved */
359 MT2063_REG_RSVD_35, /* 0x35: Reserved */
360 MT2063_REG_RSVD_36, /* 0x36: Reserved */
361 MT2063_REG_RSVD_37, /* 0x37: Reserved */
362 MT2063_REG_RSVD_38, /* 0x38: Reserved */
363 MT2063_REG_RSVD_39, /* 0x39: Reserved */
364 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
365 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
366 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
367 MT2063_REG_END_REGS
368};
369
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300370enum MTTune_atv_standard {
371 MTTUNEA_UNKNOWN = 0,
372 MTTUNEA_PAL_B,
373 MTTUNEA_PAL_G,
374 MTTUNEA_PAL_I,
375 MTTUNEA_PAL_L,
376 MTTUNEA_PAL_MN,
377 MTTUNEA_PAL_DK,
378 MTTUNEA_DIGITAL,
379 MTTUNEA_FMRADIO,
380 MTTUNEA_DVBC,
381 MTTUNEA_DVBT
382};
383
384
385struct mt2063_state {
386 struct i2c_adapter *i2c;
387
388 const struct mt2063_config *config;
389 struct dvb_tuner_ops ops;
390 struct dvb_frontend *frontend;
391 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300392 bool MT2063_init;
393
394 enum MTTune_atv_standard tv_type;
395 u32 frequency;
396 u32 srate;
397 u32 bandwidth;
398 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300399
400 u32 tuner_id;
401 struct MT2063_AvoidSpursData_t AS_Data;
402 u32 f_IF1_actual;
403 u32 rcvr_mode;
404 u32 ctfilt_sw;
405 u32 CTFiltMax[31];
406 u32 num_regs;
407 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300408};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300409
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300410/* Prototypes */
411static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
412 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300413static u32 MT2063_ReInit(struct mt2063_state *state);
414static u32 MT2063_Close(struct mt2063_state *state);
415static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
416static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
417static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
418static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300419 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300420
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300421/*****************/
422/* From drivers/media/common/tuners/mt2063_cfg.h */
423
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300424unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300425 u32 bw_in,
426 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300427{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300428 struct dvb_frontend_ops *frontend_ops = NULL;
429 struct dvb_tuner_ops *tuner_ops = NULL;
430 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300431 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300432 int err = 0;
433
434 t_state.frequency = f_in;
435 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300436 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300437 if (&fe->ops)
438 frontend_ops = &fe->ops;
439 if (&frontend_ops->tuner_ops)
440 tuner_ops = &frontend_ops->tuner_ops;
441 if (tuner_ops->set_state) {
442 if ((err =
443 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
444 &t_state)) < 0) {
445 printk("%s: Invalid parameter\n", __func__);
446 return err;
447 }
448 }
449
450 return err;
451}
452
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300453unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300454{
455 struct dvb_frontend_ops *frontend_ops = &fe->ops;
456 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
457 struct tuner_state t_state;
458 int err = 0;
459
460 if (&fe->ops)
461 frontend_ops = &fe->ops;
462 if (&frontend_ops->tuner_ops)
463 tuner_ops = &frontend_ops->tuner_ops;
464 if (tuner_ops->get_state) {
465 if ((err =
466 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
467 &t_state)) < 0) {
468 printk("%s: Invalid parameter\n", __func__);
469 return err;
470 }
471 }
472 return err;
473}
474
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300475unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300476{
477 struct dvb_frontend_ops *frontend_ops = &fe->ops;
478 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
479 struct tuner_state t_state;
480 int err = 0;
481
482 if (&fe->ops)
483 frontend_ops = &fe->ops;
484 if (&frontend_ops->tuner_ops)
485 tuner_ops = &frontend_ops->tuner_ops;
486 if (tuner_ops->set_state) {
487 if ((err =
488 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
489 &t_state)) < 0) {
490 printk("%s: Invalid parameter\n", __func__);
491 return err;
492 }
493 }
494
495 return err;
496}
497
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300498unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300499{
500 struct dvb_frontend_ops *frontend_ops = &fe->ops;
501 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
502 struct tuner_state t_state;
503 int err = 0;
504
505 if (&fe->ops)
506 frontend_ops = &fe->ops;
507 if (&frontend_ops->tuner_ops)
508 tuner_ops = &frontend_ops->tuner_ops;
509 if (tuner_ops->set_state) {
510 if ((err =
511 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
512 &t_state)) < 0) {
513 printk("%s: Invalid parameter\n", __func__);
514 return err;
515 }
516 }
517
518 return err;
519}
520
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300521unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300522{
523 struct dvb_frontend_ops *frontend_ops = &fe->ops;
524 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
525 struct tuner_state t_state;
526 int err = 0;
527
528 if (&fe->ops)
529 frontend_ops = &fe->ops;
530 if (&frontend_ops->tuner_ops)
531 tuner_ops = &frontend_ops->tuner_ops;
532 if (tuner_ops->set_state) {
533 if ((err =
534 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
535 &t_state)) < 0) {
536 printk("%s: Invalid parameter\n", __func__);
537 return err;
538 }
539 }
540
541 return err;
542}
543
544/*****************/
545
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300546//i2c operation
547static int mt2063_writeregs(struct mt2063_state *state, u8 reg1,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300548 u8 *data, int len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300549{
550 int ret;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300551 u8 buf[60]; /* = { reg1, data }; */
552
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300553 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300554 .addr = state->config->tuner_address,
555 .flags = 0,
556 .buf = buf,
557 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300558 };
559
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300560 msg.buf[0] = reg1;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300561 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300562
563 //printk("mt2063_writeregs state->i2c=%p\n", state->i2c);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300564 ret = i2c_transfer(state->i2c, &msg, 1);
565
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300566 if (ret < 0)
567 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300568
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300569 return ret;
570}
571
572static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 * b, u8 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300573{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300574 int ret;
575 u8 b0[] = { reg1 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300576 struct i2c_msg msg[] = {
577 {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300578 .addr = state->config->tuner_address,
579 .flags = I2C_M_RD,
580 .buf = b0,
581 .len = 1}, {
582 .addr = state->config->tuner_address,
583 .flags = I2C_M_RD,
584 .buf = b,
585 .len = len}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300586 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300587
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300588 //printk("mt2063_read_regs state->i2c=%p\n", state->i2c);
589 ret = i2c_transfer(state->i2c, msg, 2);
590 if (ret < 0)
591 printk("mt2063_readregs error ret=%d\n", ret);
592
593 return ret;
594}
595
596//context of mt2063_userdef.c <Henry> ======================================
597//#################################################################
598//=================================================================
599/*****************************************************************************
600**
601** Name: MT_WriteSub
602**
603** Description: Write values to device using a two-wire serial bus.
604**
605** Parameters: hUserData - User-specific I/O parameter that was
606** passed to tuner's Open function.
607** addr - device serial bus address (value passed
608** as parameter to MTxxxx_Open)
609** subAddress - serial bus sub-address (Register Address)
610** pData - pointer to the Data to be written to the
611** device
612** cnt - number of bytes/registers to be written
613**
614** Returns: status:
615** MT_OK - No errors
616** MT_COMM_ERR - Serial bus communications error
617** user-defined
618**
619** Notes: This is a callback function that is called from the
620** the tuning algorithm. You MUST provide code for this
621** function to write data using the tuner's 2-wire serial
622** bus.
623**
624** The hUserData parameter is a user-specific argument.
625** If additional arguments are needed for the user's
626** serial bus read/write functions, this argument can be
627** used to supply the necessary information.
628** The hUserData parameter is initialized in the tuner's Open
629** function.
630**
631** Revision History:
632**
633** SCR Date Author Description
634** -------------------------------------------------------------------------
635** N/A 03-25-2004 DAD Original
636**
637*****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300638static u32 MT2063_WriteSub(struct mt2063_state *state,
639 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300640{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300641 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300642 struct dvb_frontend *fe = state->frontend;
643
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300644 /*
645 ** ToDo: Add code here to implement a serial-bus write
646 ** operation to the MTxxxx tuner. If successful,
647 ** return MT_OK.
648 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300649
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300650 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300651
652 if (mt2063_writeregs(state, subAddress, pData, cnt) < 0) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300653 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300654 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300655 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300656
657 return (status);
658}
659
660/*****************************************************************************
661**
662** Name: MT_ReadSub
663**
664** Description: Read values from device using a two-wire serial bus.
665**
666** Parameters: hUserData - User-specific I/O parameter that was
667** passed to tuner's Open function.
668** addr - device serial bus address (value passed
669** as parameter to MTxxxx_Open)
670** subAddress - serial bus sub-address (Register Address)
671** pData - pointer to the Data to be written to the
672** device
673** cnt - number of bytes/registers to be written
674**
675** Returns: status:
676** MT_OK - No errors
677** MT_COMM_ERR - Serial bus communications error
678** user-defined
679**
680** Notes: This is a callback function that is called from the
681** the tuning algorithm. You MUST provide code for this
682** function to read data using the tuner's 2-wire serial
683** bus.
684**
685** The hUserData parameter is a user-specific argument.
686** If additional arguments are needed for the user's
687** serial bus read/write functions, this argument can be
688** used to supply the necessary information.
689** The hUserData parameter is initialized in the tuner's Open
690** function.
691**
692** Revision History:
693**
694** SCR Date Author Description
695** -------------------------------------------------------------------------
696** N/A 03-25-2004 DAD Original
697**
698*****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300699static u32 MT2063_ReadSub(struct mt2063_state *state,
700 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300701{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300702 u32 status = 0; /* Status to be returned */
703 struct dvb_frontend *fe = state->frontend;
704 u32 i = 0;
705
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300706 /*
707 ** ToDo: Add code here to implement a serial-bus read
708 ** operation to the MTxxxx tuner. If successful,
709 ** return MT_OK.
710 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300711 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300712
713 for (i = 0; i < cnt; i++) {
714 if (mt2063_read_regs(state, subAddress + i, pData + i, 1) < 0) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300715 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300716 break;
717 }
718 }
719
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300720 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300721
722 return (status);
723}
724
725/*****************************************************************************
726**
727** Name: MT_Sleep
728**
729** Description: Delay execution for "nMinDelayTime" milliseconds
730**
731** Parameters: hUserData - User-specific I/O parameter that was
732** passed to tuner's Open function.
733** nMinDelayTime - Delay time in milliseconds
734**
735** Returns: None.
736**
737** Notes: This is a callback function that is called from the
738** the tuning algorithm. You MUST provide code that
739** blocks execution for the specified period of time.
740**
741** Revision History:
742**
743** SCR Date Author Description
744** -------------------------------------------------------------------------
745** N/A 03-25-2004 DAD Original
746**
747*****************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300748static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300749{
750 /*
751 ** ToDo: Add code here to implement a OS blocking
752 ** for a period of "nMinDelayTime" milliseconds.
753 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300754 msleep(10);
755
756 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300757}
758
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300759//end of mt2063_userdef.c
760//=================================================================
761//#################################################################
762//=================================================================
763
764//context of mt2063_spuravoid.c <Henry> ======================================
765//#################################################################
766//=================================================================
767
768/*****************************************************************************
769**
770** Name: mt_spuravoid.c
771**
772** Description: Microtune spur avoidance software module.
773** Supports Microtune tuner drivers.
774**
775** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
776** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
777**
778** Revision History:
779**
780** SCR Date Author Description
781** -------------------------------------------------------------------------
782** 082 03-25-2005 JWS Original multi-tuner support - requires
783** MTxxxx_CNT declarations
784** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
785** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
786** of compiler warnings
787** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
788** avoidance into a single module.
789** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
790** (f_min, f_max) < 0, ignore the entry.
791** 115 03-23-2007 DAD Fix declaration of spur due to truncation
792** errors.
793** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
794** tuner DLL.
795** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
796** multi-tuners that have
797** (delta IF1) > (f_out-f_outbw/2).
798** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
799** Added logic to force f_Center within 1/2 f_Step.
800** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
801** Type casts added to preserve correct sign.
802** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
803** frequencies into MT_ResetExclZones().
804** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
805**
806*****************************************************************************/
807
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300808
809/* Implement ceiling, floor functions. */
810#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
811#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
812#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
813#define ufloor(n, d) ((n)/(d))
814
815struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300816 s32 min_;
817 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300818};
819
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300820
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300821static u32 MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300822{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300823 pAS_Info->nAS_Algorithm = 1;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300824 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300825}
826
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300827static void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300828{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300829}
830
831/*
832** Reset all exclusion zones.
833** Add zones to protect the PLL FracN regions near zero
834**
835** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
836** frequencies into MT_ResetExclZones().
837*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300838static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300839{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300840 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300841
842 pAS_Info->nZones = 0; /* this clears the used list */
843 pAS_Info->usedZones = NULL; /* reset ptr */
844 pAS_Info->freeZones = NULL; /* reset ptr */
845
846 center =
847 pAS_Info->f_ref *
848 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
849 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
850 while (center <
851 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
852 pAS_Info->f_LO1_FracN_Avoid) {
853 /* Exclude LO1 FracN */
854 MT2063_AddExclZone(pAS_Info,
855 center - pAS_Info->f_LO1_FracN_Avoid,
856 center - 1);
857 MT2063_AddExclZone(pAS_Info, center + 1,
858 center + pAS_Info->f_LO1_FracN_Avoid);
859 center += pAS_Info->f_ref;
860 }
861
862 center =
863 pAS_Info->f_ref *
864 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
865 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
866 while (center <
867 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
868 pAS_Info->f_LO2_FracN_Avoid) {
869 /* Exclude LO2 FracN */
870 MT2063_AddExclZone(pAS_Info,
871 center - pAS_Info->f_LO2_FracN_Avoid,
872 center - 1);
873 MT2063_AddExclZone(pAS_Info, center + 1,
874 center + pAS_Info->f_LO2_FracN_Avoid);
875 center += pAS_Info->f_ref;
876 }
877
878 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
879 /* Exclude LO1 values that conflict with DECT channels */
880 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
881 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
882 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
883 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
884 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
885 }
886
887 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
888 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
889 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
890 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
891 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
892 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
893 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
894 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
895 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
896 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
897 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
898 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300899}
900
901static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
902 *pAS_Info,
903 struct MT2063_ExclZone_t *pPrevNode)
904{
905 struct MT2063_ExclZone_t *pNode;
906 /* Check for a node in the free list */
907 if (pAS_Info->freeZones != NULL) {
908 /* Use one from the free list */
909 pNode = pAS_Info->freeZones;
910 pAS_Info->freeZones = pNode->next_;
911 } else {
912 /* Grab a node from the array */
913 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
914 }
915
916 if (pPrevNode != NULL) {
917 pNode->next_ = pPrevNode->next_;
918 pPrevNode->next_ = pNode;
919 } else { /* insert at the beginning of the list */
920
921 pNode->next_ = pAS_Info->usedZones;
922 pAS_Info->usedZones = pNode;
923 }
924
925 pAS_Info->nZones++;
926 return pNode;
927}
928
929static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
930 *pAS_Info,
931 struct MT2063_ExclZone_t *pPrevNode,
932 struct MT2063_ExclZone_t
933 *pNodeToRemove)
934{
935 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
936
937 /* Make previous node point to the subsequent node */
938 if (pPrevNode != NULL)
939 pPrevNode->next_ = pNext;
940
941 /* Add pNodeToRemove to the beginning of the freeZones */
942 pNodeToRemove->next_ = pAS_Info->freeZones;
943 pAS_Info->freeZones = pNodeToRemove;
944
945 /* Decrement node count */
946 pAS_Info->nZones--;
947
948 return pNext;
949}
950
951/*****************************************************************************
952**
953** Name: MT_AddExclZone
954**
955** Description: Add (and merge) an exclusion zone into the list.
956** If the range (f_min, f_max) is totally outside the
957** 1st IF BW, ignore the entry.
958** If the range (f_min, f_max) is negative, ignore the entry.
959**
960** Revision History:
961**
962** SCR Date Author Description
963** -------------------------------------------------------------------------
964** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
965** (f_min, f_max) < 0, ignore the entry.
966**
967*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300968static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300969 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300970{
971 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
972 struct MT2063_ExclZone_t *pPrev = NULL;
973 struct MT2063_ExclZone_t *pNext = NULL;
974
975 /* Check to see if this overlaps the 1st IF filter */
976 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
977 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
978 && (f_min < f_max)) {
979 /*
980 ** 1 2 3 4 5 6
981 **
982 ** New entry: |---| |--| |--| |-| |---| |--|
983 ** or or or or or
984 ** Existing: |--| |--| |--| |---| |-| |--|
985 */
986
987 /* Check for our place in the list */
988 while ((pNode != NULL) && (pNode->max_ < f_min)) {
989 pPrev = pNode;
990 pNode = pNode->next_;
991 }
992
993 if ((pNode != NULL) && (pNode->min_ < f_max)) {
994 /* Combine me with pNode */
995 if (f_min < pNode->min_)
996 pNode->min_ = f_min;
997 if (f_max > pNode->max_)
998 pNode->max_ = f_max;
999 } else {
1000 pNode = InsertNode(pAS_Info, pPrev);
1001 pNode->min_ = f_min;
1002 pNode->max_ = f_max;
1003 }
1004
1005 /* Look for merging possibilities */
1006 pNext = pNode->next_;
1007 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
1008 if (pNext->max_ > pNode->max_)
1009 pNode->max_ = pNext->max_;
1010 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
1011 }
1012 }
1013}
1014
1015/*****************************************************************************
1016**
1017** Name: MT_ChooseFirstIF
1018**
1019** Description: Choose the best available 1st IF
1020** If f_Desired is not excluded, choose that first.
1021** Otherwise, return the value closest to f_Center that is
1022** not excluded
1023**
1024** Revision History:
1025**
1026** SCR Date Author Description
1027** -------------------------------------------------------------------------
1028** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
1029** tuner DLL.
1030** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
1031** Added logic to force f_Center within 1/2 f_Step.
1032**
1033*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001034static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001035{
1036 /*
1037 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
1038 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
1039 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
1040 ** However, the sum must be.
1041 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001042 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001043 pAS_Info->f_LO1_Step *
1044 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
1045 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
1046 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001047 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001048 (pAS_Info->f_LO1_Step >
1049 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
1050 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001051 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001052
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001053 s32 i;
1054 s32 j = 0;
1055 u32 bDesiredExcluded = 0;
1056 u32 bZeroExcluded = 0;
1057 s32 tmpMin, tmpMax;
1058 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001059 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
1060 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
1061
1062 if (pAS_Info->nZones == 0)
1063 return f_Desired;
1064
1065 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
1066 if (pAS_Info->f_if1_Center > f_Desired)
1067 f_Center =
1068 f_Desired +
1069 f_Step *
1070 ((pAS_Info->f_if1_Center - f_Desired +
1071 f_Step / 2) / f_Step);
1072 else
1073 f_Center =
1074 f_Desired -
1075 f_Step *
1076 ((f_Desired - pAS_Info->f_if1_Center +
1077 f_Step / 2) / f_Step);
1078
1079 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001080 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001081 // return 0;
1082
1083 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
1084 while (pNode != NULL) {
1085 /* floor function */
1086 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001087 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001088
1089 /* ceil function */
1090 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001091 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001092
1093 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
1094 bDesiredExcluded = 1;
1095
1096 if ((tmpMin < 0) && (tmpMax > 0))
1097 bZeroExcluded = 1;
1098
1099 /* See if this zone overlaps the previous */
1100 if ((j > 0) && (tmpMin < zones[j - 1].max_))
1101 zones[j - 1].max_ = tmpMax;
1102 else {
1103 /* Add new zone */
1104 //assert(j<MT2063_MAX_ZONES);
1105 //if (j>=MT2063_MAX_ZONES)
1106 //break;
1107
1108 zones[j].min_ = tmpMin;
1109 zones[j].max_ = tmpMax;
1110 j++;
1111 }
1112 pNode = pNode->next_;
1113 }
1114
1115 /*
1116 ** If the desired is okay, return with it
1117 */
1118 if (bDesiredExcluded == 0)
1119 return f_Desired;
1120
1121 /*
1122 ** If the desired is excluded and the center is okay, return with it
1123 */
1124 if (bZeroExcluded == 0)
1125 return f_Center;
1126
1127 /* Find the value closest to 0 (f_Center) */
1128 bestDiff = zones[0].min_;
1129 for (i = 0; i < j; i++) {
1130 if (abs(zones[i].min_) < abs(bestDiff))
1131 bestDiff = zones[i].min_;
1132 if (abs(zones[i].max_) < abs(bestDiff))
1133 bestDiff = zones[i].max_;
1134 }
1135
1136 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001137 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001138
1139 return f_Center + (bestDiff * f_Step);
1140}
1141
1142/****************************************************************************
1143**
1144** Name: gcd
1145**
1146** Description: Uses Euclid's algorithm
1147**
1148** Parameters: u, v - unsigned values whose GCD is desired.
1149**
1150** Global: None
1151**
1152** Returns: greatest common divisor of u and v, if either value
1153** is 0, the other value is returned as the result.
1154**
1155** Dependencies: None.
1156**
1157** Revision History:
1158**
1159** SCR Date Author Description
1160** -------------------------------------------------------------------------
1161** N/A 06-01-2004 JWS Original
1162** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
1163** unsigned numbers.
1164**
1165****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001166static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001167{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001168 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001169
1170 while (v != 0) {
1171 r = u % v;
1172 u = v;
1173 v = r;
1174 }
1175
1176 return u;
1177}
1178
1179/****************************************************************************
1180**
1181** Name: umax
1182**
1183** Description: Implements a simple maximum function for unsigned numbers.
1184** Implemented as a function rather than a macro to avoid
1185** multiple evaluation of the calling parameters.
1186**
1187** Parameters: a, b - Values to be compared
1188**
1189** Global: None
1190**
1191** Returns: larger of the input values.
1192**
1193** Dependencies: None.
1194**
1195** Revision History:
1196**
1197** SCR Date Author Description
1198** -------------------------------------------------------------------------
1199** N/A 06-02-2004 JWS Original
1200**
1201****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001202static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001203{
1204 return (a >= b) ? a : b;
1205}
1206
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001207/****************************************************************************
1208**
1209** Name: IsSpurInBand
1210**
1211** Description: Checks to see if a spur will be present within the IF's
1212** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1213**
1214** ma mb mc md
1215** <--+-+-+-------------------+-------------------+-+-+-->
1216** | ^ 0 ^ |
1217** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1218** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1219**
1220** Note that some equations are doubled to prevent round-off
1221** problems when calculating fIFBW/2
1222**
1223** Parameters: pAS_Info - Avoid Spurs information block
1224** fm - If spur, amount f_IF1 has to move negative
1225** fp - If spur, amount f_IF1 has to move positive
1226**
1227** Global: None
1228**
1229** Returns: 1 if an LO spur would be present, otherwise 0.
1230**
1231** Dependencies: None.
1232**
1233** Revision History:
1234**
1235** SCR Date Author Description
1236** -------------------------------------------------------------------------
1237** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1238**
1239****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001240static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1241 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001242{
1243 /*
1244 ** Calculate LO frequency settings.
1245 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001246 u32 n, n0;
1247 const u32 f_LO1 = pAS_Info->f_LO1;
1248 const u32 f_LO2 = pAS_Info->f_LO2;
1249 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1250 const u32 c = d - pAS_Info->f_out_bw;
1251 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -03001252 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001253 s32 f_nsLO1, f_nsLO2;
1254 s32 f_Spur;
1255 u32 ma, mb, mc, md, me, mf;
1256 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001257 *fm = 0;
1258
1259 /*
1260 ** For each edge (d, c & f), calculate a scale, based on the gcd
1261 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1262 ** gcd-based scale factor or f_Scale.
1263 */
1264 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001265 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001266 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001267 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001268 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001269 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001270 hgfs = gf_Scale / 2;
1271
1272 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1273
1274 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1275 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1276 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1277 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1278
1279 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1280 if (md >= pAS_Info->maxH1)
1281 break;
1282
1283 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1284 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1285
1286 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1287 if (md == ma)
1288 continue;
1289
1290 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1291 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1292 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001293 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1294 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001295 f_Spur =
1296 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1297 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1298
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001299 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1300 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001301 return 1;
1302 }
1303
1304 /* Location of Zero-IF-spur to be checked */
1305 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1306 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1307 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1308 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1309 if (me != mf) {
1310 f_nsLO1 = n * (f_LO1 / gf_Scale);
1311 f_nsLO2 = me * (f_LO2 / gf_Scale);
1312 f_Spur =
1313 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1314 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1315
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001316 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1317 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001318 return 1;
1319 }
1320
1321 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1322 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1323 if (ma != mb) {
1324 f_nsLO1 = n * (f_LO1 / gc_Scale);
1325 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1326 f_Spur =
1327 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1328 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1329
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001330 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1331 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001332 return 1;
1333 }
1334 }
1335
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001336 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001337 return 0;
1338}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001339
1340/*****************************************************************************
1341**
1342** Name: MT_AvoidSpurs
1343**
1344** Description: Main entry point to avoid spurs.
1345** Checks for existing spurs in present LO1, LO2 freqs
1346** and if present, chooses spur-free LO1, LO2 combination
1347** that tunes the same input/output frequencies.
1348**
1349** Revision History:
1350**
1351** SCR Date Author Description
1352** -------------------------------------------------------------------------
1353** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1354**
1355*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001356static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001357{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001358 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001359 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001360 pAS_Info->bSpurAvoided = 0;
1361 pAS_Info->nSpursFound = 0;
1362
1363 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001364 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001365
1366 /*
1367 ** Avoid LO Generated Spurs
1368 **
1369 ** Make sure that have no LO-related spurs within the IF output
1370 ** bandwidth.
1371 **
1372 ** If there is an LO spur in this band, start at the current IF1 frequency
1373 ** and work out until we find a spur-free frequency or run up against the
1374 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1375 ** will be unchanged if a spur-free setting is not found.
1376 */
1377 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1378 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001379 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1380 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1381 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1382 u32 delta_IF1;
1383 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001384
1385 /*
1386 ** Spur was found, attempt to find a spur-free 1st IF
1387 */
1388 do {
1389 pAS_Info->nSpursFound++;
1390
1391 /* Raise f_IF1_upper, if needed */
1392 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1393
1394 /* Choose next IF1 that is closest to f_IF1_CENTER */
1395 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1396
1397 if (new_IF1 > zfIF1) {
1398 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1399 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1400 } else {
1401 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1402 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1403 }
1404 zfIF1 = new_IF1;
1405
1406 if (zfIF1 > pAS_Info->f_if1_Center)
1407 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1408 else
1409 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1410 }
1411 /*
1412 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1413 ** and there is a spur in the band (again)
1414 */
1415 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1416 pAS_Info->f_if1_bw)
1417 && (pAS_Info->bSpurPresent =
1418 IsSpurInBand(pAS_Info, &fm, &fp)));
1419
1420 /*
1421 ** Use the LO-spur free values found. If the search went all the way to
1422 ** the 1st IF band edge and always found spurs, just leave the original
1423 ** choice. It's as "good" as any other.
1424 */
1425 if (pAS_Info->bSpurPresent == 1) {
1426 status |= MT2063_SPUR_PRESENT_ERR;
1427 pAS_Info->f_LO1 = zfLO1;
1428 pAS_Info->f_LO2 = zfLO2;
1429 } else
1430 pAS_Info->bSpurAvoided = 1;
1431 }
1432
1433 status |=
1434 ((pAS_Info->
1435 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1436
1437 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001438}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001439
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001440//end of mt2063_spuravoid.c
1441//=================================================================
1442//#################################################################
1443//=================================================================
1444
1445/*
1446** The expected version of MT_AvoidSpursData_t
1447** If the version is different, an updated file is needed from Microtune
1448*/
1449/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001450
1451typedef enum {
1452 MT2063_SET_ATTEN,
1453 MT2063_INCR_ATTEN,
1454 MT2063_DECR_ATTEN
1455} MT2063_ATTEN_CNTL_MODE;
1456
1457//#define TUNER_MT2063_OPTIMIZATION
1458/*
1459** Constants used by the tuning algorithm
1460*/
1461#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1462#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1463#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1464#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1465#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1466#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1467#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1468#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1469#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1470#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1471#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1472#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1473#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1474#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1475#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1476#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1477#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1478#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1479
1480/*
1481** Define the supported Part/Rev codes for the MT2063
1482*/
1483#define MT2063_B0 (0x9B)
1484#define MT2063_B1 (0x9C)
1485#define MT2063_B2 (0x9D)
1486#define MT2063_B3 (0x9E)
1487
1488/*
1489** The number of Tuner Registers
1490*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001491static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001492
1493#define USE_GLOBAL_TUNER 0
1494
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001495static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001496static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001497
1498/*
1499** Constants for setting receiver modes.
1500** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1501** (DNC1GC & DNC2GC are the values, which are used, when the specific
1502** DNC Output is selected, the other is always off)
1503**
1504** If PAL-L or L' is received, set:
1505** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1506**
1507** --------------+----------------------------------------------
1508** Mode 0 : | MT2063_CABLE_QAM
1509** Mode 1 : | MT2063_CABLE_ANALOG
1510** Mode 2 : | MT2063_OFFAIR_COFDM
1511** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1512** Mode 4 : | MT2063_OFFAIR_ANALOG
1513** Mode 5 : | MT2063_OFFAIR_8VSB
1514** --------------+----+----+----+----+-----+-----+--------------
1515** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1516** --------------+----+----+----+----+-----+-----+
1517**
1518**
1519*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001520static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1521static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1522static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1523static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1524static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1525static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1526static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1527static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1528static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1529static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1530static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1531static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1532static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1533static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001534
1535/*
1536** Local Function Prototypes - not available for external access.
1537*/
1538
1539/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001540static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1541 u32 f_LO_Step, u32 f_Ref);
1542static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1543 u32 f_LO_Step, u32 f_Ref);
1544static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1545 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001546
1547/******************************************************************************
1548**
1549** Name: MT2063_Open
1550**
1551** Description: Initialize the tuner's register values.
1552**
1553** Parameters: MT2063_Addr - Serial bus address of the tuner.
1554** hMT2063 - Tuner handle passed back.
1555** hUserData - User-defined data, if needed for the
1556** MT_ReadSub() & MT_WriteSub functions.
1557**
1558** Returns: status:
1559** MT_OK - No errors
1560** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1561** MT_TUNER_INIT_ERR - Tuner initialization failed
1562** MT_COMM_ERR - Serial bus communications error
1563** MT_ARG_NULL - Null pointer argument passed
1564** MT_TUNER_CNT_ERR - Too many tuners open
1565**
1566** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1567** MT_WriteSub - Write byte(s) of data to the two-wire bus
1568**
1569** Revision History:
1570**
1571** SCR Date Author Description
1572** -------------------------------------------------------------------------
1573** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1574**
1575******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001576static u32 MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001577{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001578 u32 status; /* Status to be returned. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001579 struct mt2063_state *state = fe->tuner_priv;
1580
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001581 /* Default tuner handle to NULL. If successful, it will be reassigned */
1582
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001583 if (state->MT2063_init == false)
1584 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001585
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001586 status = MT2063_RegisterTuner(&state->AS_Data);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001587 if (status >= 0) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001588 state->rcvr_mode = MT2063_CABLE_QAM;
1589 status = MT2063_ReInit(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001590 }
1591
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001592 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001593 /* MT2063_Close handles the un-registration of the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001594 MT2063_Close(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001595 else {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001596 state->MT2063_init = true;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001597 }
1598
1599 return (status);
1600}
1601
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001602/******************************************************************************
1603**
1604** Name: MT2063_Close
1605**
1606** Description: Release the handle to the tuner.
1607**
1608** Parameters: hMT2063 - Handle to the MT2063 tuner
1609**
1610** Returns: status:
1611** MT_OK - No errors
1612** MT_INV_HANDLE - Invalid tuner handle
1613**
1614** Dependencies: mt_errordef.h - definition of error codes
1615**
1616** Revision History:
1617**
1618** SCR Date Author Description
1619** -------------------------------------------------------------------------
1620** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1621**
1622******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001623static u32 MT2063_Close(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001624{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001625 /* Unregister tuner with SpurAvoidance routines (if needed) */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001626 MT2063_UnRegisterTuner(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001627 /* Now remove the tuner from our own list of tuners */
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001628
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001629 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001630}
1631
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001632/****************************************************************************
1633**
1634** Name: MT2063_GetLocked
1635**
1636** Description: Checks to see if LO1 and LO2 are locked.
1637**
1638** Parameters: h - Open handle to the tuner (from MT2063_Open).
1639**
1640** Returns: status:
1641** MT_OK - No errors
1642** MT_UPC_UNLOCK - Upconverter PLL unlocked
1643** MT_DNC_UNLOCK - Downconverter PLL unlocked
1644** MT_COMM_ERR - Serial bus communications error
1645** MT_INV_HANDLE - Invalid tuner handle
1646**
1647** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1648** MT_Sleep - Delay execution for x milliseconds
1649**
1650** Revision History:
1651**
1652** SCR Date Author Description
1653** -------------------------------------------------------------------------
1654** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1655**
1656****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001657static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001658{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001659 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1660 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1661 const u32 nMaxLoops = nMaxWait / nPollRate;
1662 const u8 LO1LK = 0x80;
1663 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001664 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001665 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001666
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001667 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001668 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001669 LO2LK = 0x40;
1670
1671 do {
1672 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001673 MT2063_ReadSub(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001674 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001675 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001676
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001677 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001678 return (status);
1679
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001680 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001681 (LO1LK | LO2LK)) {
1682 return (status);
1683 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001684 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001685 }
1686 while (++nDelays < nMaxLoops);
1687
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001688 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001689 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001690 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001691 status |= MT2063_DNC_UNLOCK;
1692
1693 return (status);
1694}
1695
1696/****************************************************************************
1697**
1698** Name: MT2063_GetParam
1699**
1700** Description: Gets a tuning algorithm parameter.
1701**
1702** This function provides access to the internals of the
1703** tuning algorithm - mostly for testing purposes.
1704**
1705** Parameters: h - Tuner handle (returned by MT2063_Open)
1706** param - Tuning algorithm parameter
1707** (see enum MT2063_Param)
1708** pValue - ptr to returned value
1709**
1710** param Description
1711** ---------------------- --------------------------------
1712** MT2063_IC_ADDR Serial Bus address of this tuner
1713** MT2063_MAX_OPEN Max # of MT2063's allowed open
1714** MT2063_NUM_OPEN # of MT2063's open
1715** MT2063_SRO_FREQ crystal frequency
1716** MT2063_STEPSIZE minimum tuning step size
1717** MT2063_INPUT_FREQ input center frequency
1718** MT2063_LO1_FREQ LO1 Frequency
1719** MT2063_LO1_STEPSIZE LO1 minimum step size
1720** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1721** MT2063_IF1_ACTUAL Current 1st IF in use
1722** MT2063_IF1_REQUEST Requested 1st IF
1723** MT2063_IF1_CENTER Center of 1st IF SAW filter
1724** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1725** MT2063_ZIF_BW zero-IF bandwidth
1726** MT2063_LO2_FREQ LO2 Frequency
1727** MT2063_LO2_STEPSIZE LO2 minimum step size
1728** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1729** MT2063_OUTPUT_FREQ output center frequency
1730** MT2063_OUTPUT_BW output bandwidth
1731** MT2063_LO_SEPARATION min inter-tuner LO separation
1732** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1733** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1734** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1735** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1736** MT2063_NUM_SPURS # of spurs found/avoided
1737** MT2063_SPUR_AVOIDED >0 spurs avoided
1738** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1739** MT2063_RCVR_MODE Predefined modes.
1740** MT2063_ACLNA LNA attenuator gain code
1741** MT2063_ACRF RF attenuator gain code
1742** MT2063_ACFIF FIF attenuator gain code
1743** MT2063_ACLNA_MAX LNA attenuator limit
1744** MT2063_ACRF_MAX RF attenuator limit
1745** MT2063_ACFIF_MAX FIF attenuator limit
1746** MT2063_PD1 Actual value of PD1
1747** MT2063_PD2 Actual value of PD2
1748** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1749** MT2063_VGAGC VGA gain code
1750** MT2063_VGAOI VGA output current
1751** MT2063_TAGC TAGC setting
1752** MT2063_AMPGC AMP gain code
1753** MT2063_AVOID_DECT Avoid DECT Frequencies
1754** MT2063_CTFILT_SW Cleartune filter selection
1755**
1756** Usage: status |= MT2063_GetParam(hMT2063,
1757** MT2063_IF1_ACTUAL,
1758** &f_IF1_Actual);
1759**
1760** Returns: status:
1761** MT_OK - No errors
1762** MT_INV_HANDLE - Invalid tuner handle
1763** MT_ARG_NULL - Null pointer argument passed
1764** MT_ARG_RANGE - Invalid parameter requested
1765**
1766** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1767**
1768** See Also: MT2063_SetParam, MT2063_Open
1769**
1770** Revision History:
1771**
1772** SCR Date Author Description
1773** -------------------------------------------------------------------------
1774** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1775** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1776** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1777** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1778** in GetParam.
1779** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1780** Split SetParam up to ACLNA / ACLNA_MAX
1781** removed ACLNA_INRC/DECR (+RF & FIF)
1782** removed GCUAUTO / BYPATNDN/UP
1783** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1784** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1785** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1786**
1787****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001788static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001789{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001790 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001791 u32 Div;
1792 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001793
1794 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001795 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001796
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001797 switch (param) {
1798 /* Serial Bus address of this tuner */
1799 case MT2063_IC_ADDR:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001800 *pValue = state->config->tuner_address;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001801 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001802
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001803 /* Max # of MT2063's allowed to be open */
1804 case MT2063_MAX_OPEN:
1805 *pValue = nMT2063MaxTuners;
1806 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001807
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001808 /* # of MT2063's open */
1809 case MT2063_NUM_OPEN:
1810 *pValue = nMT2063OpenTuners;
1811 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001812
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001813 /* crystal frequency */
1814 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001815 *pValue = state->AS_Data.f_ref;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001816 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001817
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001818 /* minimum tuning step size */
1819 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001820 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001821 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001822
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001823 /* input center frequency */
1824 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001825 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001826 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001827
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001828 /* LO1 Frequency */
1829 case MT2063_LO1_FREQ:
1830 {
1831 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1832 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001833 MT2063_ReadSub(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001834 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001835 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001836 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001837 Div = state->reg[MT2063_REG_LO1C_1];
1838 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1839 state->AS_Data.f_LO1 =
1840 (state->AS_Data.f_ref * Div) +
1841 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001842 f_ref, Num, 64);
1843 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001844 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001845 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001846
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001847 /* LO1 minimum step size */
1848 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001849 *pValue = state->AS_Data.f_LO1_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001850 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001851
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001852 /* LO1 FracN keep-out region */
1853 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001854 *pValue = state->AS_Data.f_LO1_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001855 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001856
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001857 /* Current 1st IF in use */
1858 case MT2063_IF1_ACTUAL:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001859 *pValue = state->f_IF1_actual;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001860 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001861
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001862 /* Requested 1st IF */
1863 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001864 *pValue = state->AS_Data.f_if1_Request;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001865 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001866
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001867 /* Center of 1st IF SAW filter */
1868 case MT2063_IF1_CENTER:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001869 *pValue = state->AS_Data.f_if1_Center;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001870 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001871
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001872 /* Bandwidth of 1st IF SAW filter */
1873 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001874 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001875 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001876
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001877 /* zero-IF bandwidth */
1878 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001879 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001880 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001881
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001882 /* LO2 Frequency */
1883 case MT2063_LO2_FREQ:
1884 {
1885 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1886 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001887 MT2063_ReadSub(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001888 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001889 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001890 reg[MT2063_REG_LO2C_1], 3);
1891 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001892 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001893 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001894 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001895 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001896 (state->
1897 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001898 reg
1899 [MT2063_REG_LO2C_3]
1900 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001901 state->AS_Data.f_LO2 =
1902 (state->AS_Data.f_ref * Div) +
1903 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001904 f_ref, Num, 8191);
1905 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001906 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001907 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001908
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001909 /* LO2 minimum step size */
1910 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001911 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001912 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001913
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001914 /* LO2 FracN keep-out region */
1915 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001916 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001917 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001918
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001919 /* output center frequency */
1920 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001921 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001922 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001923
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001924 /* output bandwidth */
1925 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001926 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001927 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001928
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001929 /* min inter-tuner LO separation */
1930 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001931 *pValue = state->AS_Data.f_min_LO_Separation;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001932 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001933
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001934 /* ID of avoid-spurs algorithm in use */
1935 case MT2063_AS_ALG:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001936 *pValue = state->AS_Data.nAS_Algorithm;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001937 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001938
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001939 /* max # of intra-tuner harmonics */
1940 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001941 *pValue = state->AS_Data.maxH1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001942 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001943
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001944 /* max # of inter-tuner harmonics */
1945 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001946 *pValue = state->AS_Data.maxH2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001947 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001948
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001949 /* # of 1st IF exclusion zones */
1950 case MT2063_EXCL_ZONES:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001951 *pValue = state->AS_Data.nZones;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001952 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001953
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001954 /* # of spurs found/avoided */
1955 case MT2063_NUM_SPURS:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001956 *pValue = state->AS_Data.nSpursFound;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001957 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001958
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001959 /* >0 spurs avoided */
1960 case MT2063_SPUR_AVOIDED:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001961 *pValue = state->AS_Data.bSpurAvoided;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001962 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001963
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001964 /* >0 spurs in output (mathematically) */
1965 case MT2063_SPUR_PRESENT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001966 *pValue = state->AS_Data.bSpurPresent;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001967 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001968
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001969 /* Predefined receiver setup combination */
1970 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001971 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001972 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001973
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001974 case MT2063_PD1:
1975 case MT2063_PD2: {
1976 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001977 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001978 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1979 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001980
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001981 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001982
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001983 /* Initiate ADC output to reg 0x0A */
1984 if (reg != orig)
1985 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001986 MT2063_WriteSub(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001987 MT2063_REG_BYP_CTRL,
1988 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001989
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001990 if (status < 0)
1991 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001992
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001993 for (i = 0; i < 8; i++) {
1994 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001995 MT2063_ReadSub(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001996 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001997 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001998 reg
1999 [MT2063_REG_ADC_OUT],
2000 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002001
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002002 if (status >= 0)
2003 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002004 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002005 reg[MT2063_REG_ADC_OUT];
2006 else {
2007 if (i)
2008 *pValue /= i;
2009 return (status);
2010 }
2011 }
2012 *pValue /= 8; /* divide by number of reads */
2013 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002014
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002015 /* Restore value of Register BYP_CTRL */
2016 if (reg != orig)
2017 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002018 MT2063_WriteSub(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002019 MT2063_REG_BYP_CTRL,
2020 &orig, 1);
2021 }
2022 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002023
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002024 /* Get LNA attenuator code */
2025 case MT2063_ACLNA:
2026 {
2027 u8 val;
2028 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002029 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002030 &val);
2031 *pValue = val & 0x1f;
2032 }
2033 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002034
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002035 /* Get RF attenuator code */
2036 case MT2063_ACRF:
2037 {
2038 u8 val;
2039 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002040 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002041 &val);
2042 *pValue = val & 0x1f;
2043 }
2044 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002045
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002046 /* Get FIF attenuator code */
2047 case MT2063_ACFIF:
2048 {
2049 u8 val;
2050 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002051 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002052 &val);
2053 *pValue = val & 0x1f;
2054 }
2055 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002056
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002057 /* Get LNA attenuator limit */
2058 case MT2063_ACLNA_MAX:
2059 {
2060 u8 val;
2061 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002062 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002063 &val);
2064 *pValue = val & 0x1f;
2065 }
2066 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002067
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002068 /* Get RF attenuator limit */
2069 case MT2063_ACRF_MAX:
2070 {
2071 u8 val;
2072 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002073 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002074 &val);
2075 *pValue = val & 0x1f;
2076 }
2077 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002078
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002079 /* Get FIF attenuator limit */
2080 case MT2063_ACFIF_MAX:
2081 {
2082 u8 val;
2083 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002084 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002085 &val);
2086 *pValue = val & 0x1f;
2087 }
2088 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002089
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002090 /* Get current used DNC output */
2091 case MT2063_DNC_OUTPUT_ENABLE:
2092 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002093 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
2094 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002095 *pValue =
2096 (u32) MT2063_DNC_NONE;
2097 else
2098 *pValue =
2099 (u32) MT2063_DNC_2;
2100 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002101
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002102 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002103 *pValue =
2104 (u32) MT2063_DNC_1;
2105 else
2106 *pValue =
2107 (u32) MT2063_DNC_BOTH;
2108 }
2109 }
2110 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002111
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002112 /* Get VGA Gain Code */
2113 case MT2063_VGAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002114 *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002115 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002116
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002117 /* Get VGA bias current */
2118 case MT2063_VGAOI:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002119 *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002120 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002121
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002122 /* Get TAGC setting */
2123 case MT2063_TAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002124 *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002125 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002126
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002127 /* Get AMP Gain Code */
2128 case MT2063_AMPGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002129 *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002130 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002131
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002132 /* Avoid DECT Frequencies */
2133 case MT2063_AVOID_DECT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002134 *pValue = state->AS_Data.avoidDECT;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002135 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002136
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002137 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2138 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002139 *pValue = state->ctfilt_sw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002140 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002141
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002142 case MT2063_EOP:
2143 default:
2144 status |= -ERANGE;
2145 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002146 return (status);
2147}
2148
2149/****************************************************************************
2150**
2151** Name: MT2063_GetReg
2152**
2153** Description: Gets an MT2063 register.
2154**
2155** Parameters: h - Tuner handle (returned by MT2063_Open)
2156** reg - MT2063 register/subaddress location
2157** *val - MT2063 register/subaddress value
2158**
2159** Returns: status:
2160** MT_OK - No errors
2161** MT_COMM_ERR - Serial bus communications error
2162** MT_INV_HANDLE - Invalid tuner handle
2163** MT_ARG_NULL - Null pointer argument passed
2164** MT_ARG_RANGE - Argument out of range
2165**
2166** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2167**
2168** Use this function if you need to read a register from
2169** the MT2063.
2170**
2171** Revision History:
2172**
2173** SCR Date Author Description
2174** -------------------------------------------------------------------------
2175** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2176**
2177****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002178static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002179{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002180 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002181
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002182 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002183 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002184
2185 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002186 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002187
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002188 status = MT2063_ReadSub(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002189
2190 return (status);
2191}
2192
2193/******************************************************************************
2194**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002195** Name: MT2063_SetReceiverMode
2196**
2197** Description: Set the MT2063 receiver mode
2198**
2199** --------------+----------------------------------------------
2200** Mode 0 : | MT2063_CABLE_QAM
2201** Mode 1 : | MT2063_CABLE_ANALOG
2202** Mode 2 : | MT2063_OFFAIR_COFDM
2203** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2204** Mode 4 : | MT2063_OFFAIR_ANALOG
2205** Mode 5 : | MT2063_OFFAIR_8VSB
2206** --------------+----+----+----+----+-----+--------------------
2207** (DNC1GC & DNC2GC are the values, which are used, when the specific
2208** DNC Output is selected, the other is always off)
2209**
2210** |<---------- Mode -------------->|
2211** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2212** ------------+-----+-----+-----+-----+-----+-----+
2213** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2214** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2215** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2216** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2217** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2218** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2219** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2220** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2221** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2222** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2223** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2224** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2225** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2226** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2227** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2228**
2229**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002230** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002231** Mode - desired reciever mode
2232**
2233** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2234**
2235** Returns: status:
2236** MT_OK - No errors
2237** MT_COMM_ERR - Serial bus communications error
2238**
2239** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2240** Assumes that the tuner cache is valid.
2241**
2242** Revision History:
2243**
2244** SCR Date Author Description
2245** -------------------------------------------------------------------------
2246** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2247** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2248** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2249** modulation
2250** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2251** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2252** the same settings as with MT Launcher
2253** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2254** Add SetParam DNC_OUTPUT_ENABLE
2255** Removed VGAGC from receiver mode,
2256** default now 1
2257** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2258** Add SetParam AMPGC, removed from rcvr-mode
2259** Corrected names of GCU values
2260** reorganized receiver modes, removed,
2261** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2262** Actualized Receiver-Mode values
2263** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2264** N/A 11-27-2007 PINZ Improved buffered writing
2265** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2266** correct wakeup of the LNA after shutdown
2267** Set AFCsd = 1 as default
2268** Changed CAP1sel default
2269** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2270** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2271** Split SetParam up to ACLNA / ACLNA_MAX
2272** removed ACLNA_INRC/DECR (+RF & FIF)
2273** removed GCUAUTO / BYPATNDN/UP
2274**
2275******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002276static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002277 enum MT2063_RCVR_MODES Mode)
2278{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002279 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002280 u8 val;
2281 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002282
2283 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002284 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002285
2286 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002287 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002288 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002289 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002290 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002291 ? 0x40 :
2292 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002293 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2294 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002295 }
2296 }
2297
2298 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002299 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002300 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002301 }
2302
2303 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002304 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002305 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002306 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002307 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002308 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002309 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002310 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002311 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002312 /* trigger FIFF calibration, needed after changing FIFFQ */
2313 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002314 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002315 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002316 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002317 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002318 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002319 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002320 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002321 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002322 }
2323 }
2324
2325 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002326 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
2327 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002328
2329 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002330 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002331 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002332 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002333 }
2334
2335 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002336 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002337 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002338 }
2339
2340 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002341 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002342 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002343 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002344 }
2345
2346 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002347 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002348 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002349 }
2350
2351 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002352 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002353 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002354 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002355 }
2356
2357 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002358 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002359 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002360 }
2361
2362 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002363 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002364 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002365 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002366 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002367 ? 0x80 :
2368 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002369 if (state->reg[MT2063_REG_LNA_TGT] != val) {
2370 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002371 }
2372 }
2373
2374 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002375 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002376 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002377 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002378 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002379 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002380 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2381 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002382 }
2383 }
2384
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002385 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002386 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002387
2388 return (status);
2389}
2390
2391/******************************************************************************
2392**
2393** Name: MT2063_ReInit
2394**
2395** Description: Initialize the tuner's register values.
2396**
2397** Parameters: h - Tuner handle (returned by MT2063_Open)
2398**
2399** Returns: status:
2400** MT_OK - No errors
2401** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2402** MT_INV_HANDLE - Invalid tuner handle
2403** MT_COMM_ERR - Serial bus communications error
2404**
2405** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2406** MT_WriteSub - Write byte(s) of data to the two-wire bus
2407**
2408** Revision History:
2409**
2410** SCR Date Author Description
2411** -------------------------------------------------------------------------
2412** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2413** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2414** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2415** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2416** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2417** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2418** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2419** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2420** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2421** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2422** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2423**
2424******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002425static u32 MT2063_ReInit(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002426{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002427 u8 all_resets = 0xF0; /* reset/load bits */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002428 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03002429 u8 *def = NULL;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002430 u32 FCRUN;
2431 s32 maxReads;
2432 u32 fcu_osc;
2433 u32 i;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002434 u8 MT2063B0_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002435 0x19, 0x05,
2436 0x1B, 0x1D,
2437 0x1C, 0x1F,
2438 0x1D, 0x0F,
2439 0x1E, 0x3F,
2440 0x1F, 0x0F,
2441 0x20, 0x3F,
2442 0x22, 0x21,
2443 0x23, 0x3F,
2444 0x24, 0x20,
2445 0x25, 0x3F,
2446 0x27, 0xEE,
2447 0x2C, 0x27, /* bit at 0x20 is cleared below */
2448 0x30, 0x03,
2449 0x2C, 0x07, /* bit at 0x20 is cleared here */
2450 0x2D, 0x87,
2451 0x2E, 0xAA,
2452 0x28, 0xE1, /* Set the FIFCrst bit here */
2453 0x28, 0xE0, /* Clear the FIFCrst bit here */
2454 0x00
2455 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002456 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002457 u8 MT2063B1_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002458 0x05, 0xF0,
2459 0x11, 0x10, /* New Enable AFCsd */
2460 0x19, 0x05,
2461 0x1A, 0x6C,
2462 0x1B, 0x24,
2463 0x1C, 0x28,
2464 0x1D, 0x8F,
2465 0x1E, 0x14,
2466 0x1F, 0x8F,
2467 0x20, 0x57,
2468 0x22, 0x21, /* New - ver 1.03 */
2469 0x23, 0x3C, /* New - ver 1.10 */
2470 0x24, 0x20, /* New - ver 1.03 */
2471 0x2C, 0x24, /* bit at 0x20 is cleared below */
2472 0x2D, 0x87, /* FIFFQ=0 */
2473 0x2F, 0xF3,
2474 0x30, 0x0C, /* New - ver 1.11 */
2475 0x31, 0x1B, /* New - ver 1.11 */
2476 0x2C, 0x04, /* bit at 0x20 is cleared here */
2477 0x28, 0xE1, /* Set the FIFCrst bit here */
2478 0x28, 0xE0, /* Clear the FIFCrst bit here */
2479 0x00
2480 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002481 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002482 u8 MT2063B3_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002483 0x05, 0xF0,
2484 0x19, 0x3D,
2485 0x2C, 0x24, /* bit at 0x20 is cleared below */
2486 0x2C, 0x04, /* bit at 0x20 is cleared here */
2487 0x28, 0xE1, /* Set the FIFCrst bit here */
2488 0x28, 0xE0, /* Clear the FIFCrst bit here */
2489 0x00
2490 };
2491
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002492 /* Read the Part/Rev code from the tuner */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002493 status = MT2063_ReadSub(state, MT2063_REG_PART_REV, state->reg, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002494 if (status < 0)
2495 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002496
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002497 /* Check the part/rev code */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002498 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2499 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2500 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002501 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002502
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002503 /* Check the 2nd byte of the Part/Rev code from the tuner */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002504 status = MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002505 MT2063_REG_RSVD_3B,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002506 &state->reg[MT2063_REG_RSVD_3B], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002507
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002508 if (status >= 0
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002509 &&((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002510 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002511
2512 /* Reset the tuner */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002513 status = MT2063_WriteSub(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002514 if (status < 0)
2515 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002516
2517 /* change all of the default values that vary from the HW reset values */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002518 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2519 switch (state->reg[MT2063_REG_PART_REV]) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002520 case MT2063_B3:
2521 def = MT2063B3_defaults;
2522 break;
2523
2524 case MT2063_B1:
2525 def = MT2063B1_defaults;
2526 break;
2527
2528 case MT2063_B0:
2529 def = MT2063B0_defaults;
2530 break;
2531
2532 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002533 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002534 break;
2535 }
2536
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002537 while (status >= 0 && *def) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002538 u8 reg = *def++;
2539 u8 val = *def++;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002540 status = MT2063_WriteSub(state, reg, &val, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002541 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002542 if (status < 0)
2543 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002544
2545 /* Wait for FIFF location to complete. */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002546 FCRUN = 1;
2547 maxReads = 10;
2548 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
2549 msleep(2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002550 status = MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002551 MT2063_REG_XO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002552 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002553 reg[MT2063_REG_XO_STATUS], 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002554 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002555 }
2556
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002557 if (FCRUN != 0)
2558 return -ENODEV;
2559
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002560 status = MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002561 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002562 &state->reg[MT2063_REG_FIFFC], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002563 if (status < 0)
2564 return status;
2565
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002566 /* Read back all the registers from the tuner */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002567 status = MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002568 MT2063_REG_PART_REV,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002569 state->reg, MT2063_REG_END_REGS);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002570 if (status < 0)
2571 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002572
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002573 /* Initialize the tuner state. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002574 state->tuner_id = state->reg[MT2063_REG_PART_REV];
2575 state->AS_Data.f_ref = MT2063_REF_FREQ;
2576 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
2577 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
2578 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
2579 state->AS_Data.f_out = 43750000UL;
2580 state->AS_Data.f_out_bw = 6750000UL;
2581 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2582 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
2583 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2584 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2585 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2586 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2587 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
2588 state->AS_Data.f_LO1 = 2181000000UL;
2589 state->AS_Data.f_LO2 = 1486249786UL;
2590 state->f_IF1_actual = state->AS_Data.f_if1_Center;
2591 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
2592 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2593 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2594 state->num_regs = MT2063_REG_END_REGS;
2595 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2596 state->ctfilt_sw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002597
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002598 state->CTFiltMax[0] = 69230000;
2599 state->CTFiltMax[1] = 105770000;
2600 state->CTFiltMax[2] = 140350000;
2601 state->CTFiltMax[3] = 177110000;
2602 state->CTFiltMax[4] = 212860000;
2603 state->CTFiltMax[5] = 241130000;
2604 state->CTFiltMax[6] = 274370000;
2605 state->CTFiltMax[7] = 309820000;
2606 state->CTFiltMax[8] = 342450000;
2607 state->CTFiltMax[9] = 378870000;
2608 state->CTFiltMax[10] = 416210000;
2609 state->CTFiltMax[11] = 456500000;
2610 state->CTFiltMax[12] = 495790000;
2611 state->CTFiltMax[13] = 534530000;
2612 state->CTFiltMax[14] = 572610000;
2613 state->CTFiltMax[15] = 598970000;
2614 state->CTFiltMax[16] = 635910000;
2615 state->CTFiltMax[17] = 672130000;
2616 state->CTFiltMax[18] = 714840000;
2617 state->CTFiltMax[19] = 739660000;
2618 state->CTFiltMax[20] = 770410000;
2619 state->CTFiltMax[21] = 814660000;
2620 state->CTFiltMax[22] = 846950000;
2621 state->CTFiltMax[23] = 867820000;
2622 state->CTFiltMax[24] = 915980000;
2623 state->CTFiltMax[25] = 947450000;
2624 state->CTFiltMax[26] = 983110000;
2625 state->CTFiltMax[27] = 1021630000;
2626 state->CTFiltMax[28] = 1061870000;
2627 state->CTFiltMax[29] = 1098330000;
2628 state->CTFiltMax[30] = 1138990000;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002629
2630 /*
2631 ** Fetch the FCU osc value and use it and the fRef value to
2632 ** scale all of the Band Max values
2633 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002634
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002635 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
2636 status = MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002637 MT2063_REG_CTUNE_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002638 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002639 if (status < 0)
2640 return status;
2641 /* Read the ClearTune filter calibration value */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002642 status = MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002643 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002644 &state->reg[MT2063_REG_FIFFC], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002645 if (status < 0)
2646 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002647
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002648 fcu_osc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002649
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002650 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
2651 status = MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002652 MT2063_REG_CTUNE_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002653 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002654 if (status < 0)
2655 return status;
2656
2657 /* Adjust each of the values in the ClearTune filter cross-over table */
2658 for (i = 0; i < 31; i++)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002659 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002660
2661 return (status);
2662}
2663
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002664/****************************************************************************
2665**
2666** Name: MT2063_SetParam
2667**
2668** Description: Sets a tuning algorithm parameter.
2669**
2670** This function provides access to the internals of the
2671** tuning algorithm. You can override many of the tuning
2672** algorithm defaults using this function.
2673**
2674** Parameters: h - Tuner handle (returned by MT2063_Open)
2675** param - Tuning algorithm parameter
2676** (see enum MT2063_Param)
2677** nValue - value to be set
2678**
2679** param Description
2680** ---------------------- --------------------------------
2681** MT2063_SRO_FREQ crystal frequency
2682** MT2063_STEPSIZE minimum tuning step size
2683** MT2063_LO1_FREQ LO1 frequency
2684** MT2063_LO1_STEPSIZE LO1 minimum step size
2685** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2686** MT2063_IF1_REQUEST Requested 1st IF
2687** MT2063_ZIF_BW zero-IF bandwidth
2688** MT2063_LO2_FREQ LO2 frequency
2689** MT2063_LO2_STEPSIZE LO2 minimum step size
2690** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2691** MT2063_OUTPUT_FREQ output center frequency
2692** MT2063_OUTPUT_BW output bandwidth
2693** MT2063_LO_SEPARATION min inter-tuner LO separation
2694** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2695** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2696** MT2063_RCVR_MODE Predefined modes
2697** MT2063_LNA_RIN Set LNA Rin (*)
2698** MT2063_LNA_TGT Set target power level at LNA (*)
2699** MT2063_PD1_TGT Set target power level at PD1 (*)
2700** MT2063_PD2_TGT Set target power level at PD2 (*)
2701** MT2063_ACLNA_MAX LNA attenuator limit (*)
2702** MT2063_ACRF_MAX RF attenuator limit (*)
2703** MT2063_ACFIF_MAX FIF attenuator limit (*)
2704** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2705** MT2063_VGAGC VGA gain code
2706** MT2063_VGAOI VGA output current
2707** MT2063_TAGC TAGC setting
2708** MT2063_AMPGC AMP gain code
2709** MT2063_AVOID_DECT Avoid DECT Frequencies
2710** MT2063_CTFILT_SW Cleartune filter selection
2711**
2712** (*) This parameter is set by MT2063_RCVR_MODE, do not call
2713** additionally.
2714**
2715** Usage: status |= MT2063_SetParam(hMT2063,
2716** MT2063_STEPSIZE,
2717** 50000);
2718**
2719** Returns: status:
2720** MT_OK - No errors
2721** MT_INV_HANDLE - Invalid tuner handle
2722** MT_ARG_NULL - Null pointer argument passed
2723** MT_ARG_RANGE - Invalid parameter requested
2724** or set value out of range
2725** or non-writable parameter
2726**
2727** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2728**
2729** See Also: MT2063_GetParam, MT2063_Open
2730**
2731** Revision History:
2732**
2733** SCR Date Author Description
2734** -------------------------------------------------------------------------
2735** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2736** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2737** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2738** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2739** Split SetParam up to ACLNA / ACLNA_MAX
2740** removed ACLNA_INRC/DECR (+RF & FIF)
2741** removed GCUAUTO / BYPATNDN/UP
2742** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2743** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2744** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2745**
2746****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002747static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002748 enum MT2063_Param param,
2749 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002750{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002751 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002752 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002753
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002754 switch (param) {
2755 /* crystal frequency */
2756 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002757 state->AS_Data.f_ref = nValue;
2758 state->AS_Data.f_LO1_FracN_Avoid = 0;
2759 state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
2760 state->AS_Data.f_LO1_Step = nValue / 64;
2761 state->AS_Data.f_if1_Center =
2762 (state->AS_Data.f_ref / 8) *
2763 (state->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002764 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002765
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002766 /* minimum tuning step size */
2767 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002768 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002769 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002770
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002771 /* LO1 frequency */
2772 case MT2063_LO1_FREQ:
2773 {
2774 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2775 /* Capture the Divider and Numerator portions of other LO */
2776 u8 tempLO2CQ[3];
2777 u8 tempLO2C[3];
2778 u8 tmpOneShot;
2779 u32 Div, FracN;
2780 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002781
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002782 /* Buffer the queue for restoration later and get actual LO2 values. */
2783 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002784 MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002785 MT2063_REG_LO2CQ_1,
2786 &(tempLO2CQ[0]), 3);
2787 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002788 MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002789 MT2063_REG_LO2C_1,
2790 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002791
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002792 /* clear the one-shot bits */
2793 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
2794 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002795
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002796 /* only write the queue values if they are different from the actual. */
2797 if ((tempLO2CQ[0] != tempLO2C[0]) ||
2798 (tempLO2CQ[1] != tempLO2C[1]) ||
2799 (tempLO2CQ[2] != tempLO2C[2])) {
2800 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002801 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002802 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002803 MT2063_REG_LO2CQ_1,
2804 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002805
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002806 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002807 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002808 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002809 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002810 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002811 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002812 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002813 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002814 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002815 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002816 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002817
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002818 /* Calculate the Divider and Numberator components of LO1 */
2819 status =
2820 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002821 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002822 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002823 state->AS_Data.f_ref);
2824 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002825 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002826 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002827 (u8) (FracN);
2828 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002829 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002830 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002831 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002832 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002833
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002834 /* set the one-shot bit to load the pair of LO values */
2835 tmpOneShot = tempLO2CQ[2] | 0xE0;
2836 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002837 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002838 MT2063_REG_LO2CQ_3,
2839 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002840
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002841 /* only restore the queue values if they were different from the actual. */
2842 if (restore) {
2843 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002844 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002845 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002846 MT2063_REG_LO2CQ_1,
2847 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002848
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002849 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002850 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002851 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002852 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002853 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002854 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002855 tempLO2CQ[2];
2856 }
2857
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002858 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002859 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002860 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002861 }
2862 break;
2863
2864 /* LO1 minimum step size */
2865 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002866 state->AS_Data.f_LO1_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002867 break;
2868
2869 /* LO1 FracN keep-out region */
2870 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002871 state->AS_Data.f_LO1_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002872 break;
2873
2874 /* Requested 1st IF */
2875 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002876 state->AS_Data.f_if1_Request = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002877 break;
2878
2879 /* zero-IF bandwidth */
2880 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002881 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002882 break;
2883
2884 /* LO2 frequency */
2885 case MT2063_LO2_FREQ:
2886 {
2887 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2888 /* Capture the Divider and Numerator portions of other LO */
2889 u8 tempLO1CQ[2];
2890 u8 tempLO1C[2];
2891 u32 Div2;
2892 u32 FracN2;
2893 u8 tmpOneShot;
2894 u8 restore = 0;
2895
2896 /* Buffer the queue for restoration later and get actual LO2 values. */
2897 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002898 MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002899 MT2063_REG_LO1CQ_1,
2900 &(tempLO1CQ[0]), 2);
2901 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002902 MT2063_ReadSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002903 MT2063_REG_LO1C_1,
2904 &(tempLO1C[0]), 2);
2905
2906 /* only write the queue values if they are different from the actual. */
2907 if ((tempLO1CQ[0] != tempLO1C[0])
2908 || (tempLO1CQ[1] != tempLO1C[1])) {
2909 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002910 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002911 MT2063_WriteSub(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002912 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002913 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002914
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002915 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002916 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002917 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002918 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002919 tempLO1C[1];
2920 restore = 1;
2921 }
2922
2923 /* Calculate the Divider and Numberator components of LO2 */
2924 status =
2925 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002926 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002927 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002928 state->AS_Data.f_ref);
2929 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002930 (u8) ((Div2 << 1) |
2931 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002932 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002933 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002934 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002935 (u8) ((FracN2 & 0x0F));
2936 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002937 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002938 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002939 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002940 reg[MT2063_REG_LO1CQ_1], 3);
2941
2942 /* set the one-shot bit to load the LO values */
2943 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002944 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002945 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002946 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002947 MT2063_REG_LO2CQ_3,
2948 &tmpOneShot, 1);
2949
2950 /* only restore LO1 queue value if they were different from the actual. */
2951 if (restore) {
2952 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002953 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002954 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002955 MT2063_REG_LO1CQ_1,
2956 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002957
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002958 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002959 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002960 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002961 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002962 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002963 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002964
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002965 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002966 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002967 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002968 }
2969 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002970
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002971 /* LO2 minimum step size */
2972 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002973 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002974 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002975
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002976 /* LO2 FracN keep-out region */
2977 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002978 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002979 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002980
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002981 /* output center frequency */
2982 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002983 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002984 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002985
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002986 /* output bandwidth */
2987 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002988 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002989 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002990
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002991 /* min inter-tuner LO separation */
2992 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002993 state->AS_Data.f_min_LO_Separation = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002994 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002995
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002996 /* max # of intra-tuner harmonics */
2997 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002998 state->AS_Data.maxH1 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002999 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003000
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003001 /* max # of inter-tuner harmonics */
3002 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003003 state->AS_Data.maxH2 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003004 break;
3005
3006 case MT2063_RCVR_MODE:
3007 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003008 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003009 (enum MT2063_RCVR_MODES)
3010 nValue);
3011 break;
3012
3013 /* Set LNA Rin -- nValue is desired value */
3014 case MT2063_LNA_RIN:
3015 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003016 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003017 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
3018 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003019 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003020 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003021 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003022 val);
3023 }
3024 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003025
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003026 /* Set target power level at LNA -- nValue is desired value */
3027 case MT2063_LNA_TGT:
3028 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003029 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003030 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
3031 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003032 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003033 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003034 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003035 val);
3036 }
3037 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003038
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003039 /* Set target power level at PD1 -- nValue is desired value */
3040 case MT2063_PD1_TGT:
3041 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003042 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003043 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
3044 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003045 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003046 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003047 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003048 val);
3049 }
3050 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003051
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003052 /* Set target power level at PD2 -- nValue is desired value */
3053 case MT2063_PD2_TGT:
3054 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003055 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003056 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
3057 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003058 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003059 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003060 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003061 val);
3062 }
3063 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003064
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003065 /* Set LNA atten limit -- nValue is desired value */
3066 case MT2063_ACLNA_MAX:
3067 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003068 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003069 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
3070 &
3071 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003072 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003073 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003074 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003075 val);
3076 }
3077 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003078
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003079 /* Set RF atten limit -- nValue is desired value */
3080 case MT2063_ACRF_MAX:
3081 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003082 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003083 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
3084 &
3085 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003086 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003087 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003088 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003089 }
3090 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003091
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003092 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
3093 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003094 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003095 && nValue > 5)
3096 nValue = 5;
3097 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003098 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003099 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
3100 &
3101 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003102 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003103 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003104 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003105 val);
3106 }
3107 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003108
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003109 case MT2063_DNC_OUTPUT_ENABLE:
3110 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03003111 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003112 case MT2063_DNC_NONE:
3113 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003114 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3115 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003116 val)
3117 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003118 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003119 MT2063_REG_DNC_GAIN,
3120 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003121
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003122 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3123 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003124 val)
3125 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003126 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003127 MT2063_REG_VGA_GAIN,
3128 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003129
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003130 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3131 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003132 val)
3133 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003134 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003135 MT2063_REG_RSVD_20,
3136 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003137
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003138 break;
3139 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003140 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003141 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003142 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3143 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003144 val)
3145 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003146 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003147 MT2063_REG_DNC_GAIN,
3148 val);
3149
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003150 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3151 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003152 val)
3153 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003154 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003155 MT2063_REG_VGA_GAIN,
3156 val);
3157
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003158 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3159 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003160 val)
3161 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003162 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003163 MT2063_REG_RSVD_20,
3164 val);
3165
3166 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003167 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003168 case MT2063_DNC_2:
3169 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003170 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3171 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003172 val)
3173 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003174 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003175 MT2063_REG_DNC_GAIN,
3176 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003177
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003178 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3179 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003180 val)
3181 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003182 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003183 MT2063_REG_VGA_GAIN,
3184 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003185
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003186 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3187 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003188 val)
3189 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003190 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003191 MT2063_REG_RSVD_20,
3192 val);
3193
3194 break;
3195 }
3196 case MT2063_DNC_BOTH:
3197 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003198 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3199 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003200 val)
3201 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003202 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003203 MT2063_REG_DNC_GAIN,
3204 val);
3205
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003206 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3207 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003208 val)
3209 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003210 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003211 MT2063_REG_VGA_GAIN,
3212 val);
3213
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003214 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3215 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003216 val)
3217 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003218 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003219 MT2063_REG_RSVD_20,
3220 val);
3221
3222 break;
3223 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003224 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003225 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003226 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003227 break;
3228
3229 case MT2063_VGAGC:
3230 /* Set VGA gain code */
3231 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003232 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003233 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
3234 ((nValue & 0x03) << 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003235 if (state->reg[MT2063_REG_VGA_GAIN] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003236 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003237 MT2063_SetReg(state, MT2063_REG_VGA_GAIN,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003238 val);
3239 }
3240 break;
3241
3242 case MT2063_VGAOI:
3243 /* Set VGA bias current */
3244 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003245 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003246 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
3247 (nValue & 0x07);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003248 if (state->reg[MT2063_REG_RSVD_31] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003249 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003250 MT2063_SetReg(state, MT2063_REG_RSVD_31,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003251 val);
3252 }
3253 break;
3254
3255 case MT2063_TAGC:
3256 /* Set TAGC */
3257 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003258 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003259 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
3260 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003261 if (state->reg[MT2063_REG_RSVD_1E] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003262 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003263 MT2063_SetReg(state, MT2063_REG_RSVD_1E,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003264 val);
3265 }
3266 break;
3267
3268 case MT2063_AMPGC:
3269 /* Set Amp gain code */
3270 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003271 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003272 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
3273 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003274 if (state->reg[MT2063_REG_TEMP_SEL] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003275 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003276 MT2063_SetReg(state, MT2063_REG_TEMP_SEL,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003277 val);
3278 }
3279 break;
3280
3281 /* Avoid DECT Frequencies */
3282 case MT2063_AVOID_DECT:
3283 {
3284 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3285 (enum MT2063_DECT_Avoid_Type)nValue;
3286 if ((newAvoidSetting >=
3287 MT2063_NO_DECT_AVOIDANCE)
3288 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003289 state->AS_Data.avoidDECT =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003290 newAvoidSetting;
3291 }
3292 }
3293 break;
3294
3295 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3296 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003297 state->ctfilt_sw = (nValue & 0x01);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003298 break;
3299
3300 /* These parameters are read-only */
3301 case MT2063_IC_ADDR:
3302 case MT2063_MAX_OPEN:
3303 case MT2063_NUM_OPEN:
3304 case MT2063_INPUT_FREQ:
3305 case MT2063_IF1_ACTUAL:
3306 case MT2063_IF1_CENTER:
3307 case MT2063_IF1_BW:
3308 case MT2063_AS_ALG:
3309 case MT2063_EXCL_ZONES:
3310 case MT2063_SPUR_AVOIDED:
3311 case MT2063_NUM_SPURS:
3312 case MT2063_SPUR_PRESENT:
3313 case MT2063_ACLNA:
3314 case MT2063_ACRF:
3315 case MT2063_ACFIF:
3316 case MT2063_EOP:
3317 default:
3318 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003319 }
3320 return (status);
3321}
3322
3323/****************************************************************************
3324**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003325** Name: MT2063_ClearPowerMaskBits
3326**
3327** Description: Clears the power-down mask bits for various sections of
3328** the MT2063
3329**
3330** Parameters: h - Tuner handle (returned by MT2063_Open)
3331** Bits - Mask bits to be cleared.
3332**
3333** See definition of MT2063_Mask_Bits type for description
3334** of each of the power bits.
3335**
3336** Returns: status:
3337** MT_OK - No errors
3338** MT_INV_HANDLE - Invalid tuner handle
3339** MT_COMM_ERR - Serial bus communications error
3340**
3341** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3342**
3343** Revision History:
3344**
3345** SCR Date Author Description
3346** -------------------------------------------------------------------------
3347** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3348**
3349****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003350static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003351{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003352 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003353
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003354 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3355 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003356 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003357 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003358 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003359 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003360 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003361 }
3362 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003363 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003364 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003365 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003366 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003367 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003368 }
3369
3370 return (status);
3371}
3372
3373/****************************************************************************
3374**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003375** Name: MT2063_SoftwareShutdown
3376**
3377** Description: Enables or disables software shutdown function. When
3378** Shutdown==1, any section whose power mask is set will be
3379** shutdown.
3380**
3381** Parameters: h - Tuner handle (returned by MT2063_Open)
3382** Shutdown - 1 = shutdown the masked sections, otherwise
3383** power all sections on
3384**
3385** Returns: status:
3386** MT_OK - No errors
3387** MT_INV_HANDLE - Invalid tuner handle
3388** MT_COMM_ERR - Serial bus communications error
3389**
3390** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3391**
3392** Revision History:
3393**
3394** SCR Date Author Description
3395** -------------------------------------------------------------------------
3396** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3397** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3398** correct wakeup of the LNA
3399**
3400****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003401static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003402{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003403 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003404
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003405 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003406 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003407 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003408 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003409
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003410 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003411 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003412 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003413 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003414
3415 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003416 state->reg[MT2063_REG_BYP_CTRL] =
3417 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003418 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003419 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003420 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003421 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003422 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003423 state->reg[MT2063_REG_BYP_CTRL] =
3424 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003425 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003426 MT2063_WriteSub(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003427 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003428 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003429 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003430 }
3431
3432 return (status);
3433}
3434
3435/****************************************************************************
3436**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003437** Name: MT2063_SetReg
3438**
3439** Description: Sets an MT2063 register.
3440**
3441** Parameters: h - Tuner handle (returned by MT2063_Open)
3442** reg - MT2063 register/subaddress location
3443** val - MT2063 register/subaddress value
3444**
3445** Returns: status:
3446** MT_OK - No errors
3447** MT_COMM_ERR - Serial bus communications error
3448** MT_INV_HANDLE - Invalid tuner handle
3449** MT_ARG_RANGE - Argument out of range
3450**
3451** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3452**
3453** Use this function if you need to override a default
3454** register value
3455**
3456** Revision History:
3457**
3458** SCR Date Author Description
3459** -------------------------------------------------------------------------
3460** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3461**
3462****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003463static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003464{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003465 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003466
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003467 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003468 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003469
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003470 status = MT2063_WriteSub(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003471 1);
3472 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003473 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003474
3475 return (status);
3476}
3477
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003478static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003479{
3480 return f_ref * (f_LO / f_ref)
3481 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
3482}
3483
3484/****************************************************************************
3485**
3486** Name: fLO_FractionalTerm
3487**
3488** Description: Calculates the portion contributed by FracN / denom.
3489**
3490** This function preserves maximum precision without
3491** risk of overflow. It accurately calculates
3492** f_ref * num / denom to within 1 HZ with fixed math.
3493**
3494** Parameters: num - Fractional portion of the multiplier
3495** denom - denominator portion of the ratio
3496** This routine successfully handles denom values
3497** up to and including 2^18.
3498** f_Ref - SRO frequency. This calculation handles
3499** f_ref as two separate 14-bit fields.
3500** Therefore, a maximum value of 2^28-1
3501** may safely be used for f_ref. This is
3502** the genesis of the magic number "14" and the
3503** magic mask value of 0x03FFF.
3504**
3505** Returns: f_ref * num / denom
3506**
3507** Revision History:
3508**
3509** SCR Date Author Description
3510** -------------------------------------------------------------------------
3511** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3512**
3513****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003514static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
3515 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003516{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003517 u32 t1 = (f_ref >> 14) * num;
3518 u32 term1 = t1 / denom;
3519 u32 loss = t1 % denom;
3520 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003521 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
3522 return ((term1 << 14) + term2);
3523}
3524
3525/****************************************************************************
3526**
3527** Name: CalcLO1Mult
3528**
3529** Description: Calculates Integer divider value and the numerator
3530** value for a FracN PLL.
3531**
3532** This function assumes that the f_LO and f_Ref are
3533** evenly divisible by f_LO_Step.
3534**
3535** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3536** FracN - OUTPUT: Fractional portion of the multiplier
3537** f_LO - desired LO frequency.
3538** f_LO_Step - Minimum step size for the LO (in Hz).
3539** f_Ref - SRO frequency.
3540** f_Avoid - Range of PLL frequencies to avoid near
3541** integer multiples of f_Ref (in Hz).
3542**
3543** Returns: Recalculated LO frequency.
3544**
3545** Revision History:
3546**
3547** SCR Date Author Description
3548** -------------------------------------------------------------------------
3549** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3550**
3551****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003552static u32 MT2063_CalcLO1Mult(u32 * Div,
3553 u32 * FracN,
3554 u32 f_LO,
3555 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003556{
3557 /* Calculate the whole number portion of the divider */
3558 *Div = f_LO / f_Ref;
3559
3560 /* Calculate the numerator value (round to nearest f_LO_Step) */
3561 *FracN =
3562 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3563 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3564
3565 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
3566}
3567
3568/****************************************************************************
3569**
3570** Name: CalcLO2Mult
3571**
3572** Description: Calculates Integer divider value and the numerator
3573** value for a FracN PLL.
3574**
3575** This function assumes that the f_LO and f_Ref are
3576** evenly divisible by f_LO_Step.
3577**
3578** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3579** FracN - OUTPUT: Fractional portion of the multiplier
3580** f_LO - desired LO frequency.
3581** f_LO_Step - Minimum step size for the LO (in Hz).
3582** f_Ref - SRO frequency.
3583** f_Avoid - Range of PLL frequencies to avoid near
3584** integer multiples of f_Ref (in Hz).
3585**
3586** Returns: Recalculated LO frequency.
3587**
3588** Revision History:
3589**
3590** SCR Date Author Description
3591** -------------------------------------------------------------------------
3592** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3593**
3594****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003595static u32 MT2063_CalcLO2Mult(u32 * Div,
3596 u32 * FracN,
3597 u32 f_LO,
3598 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003599{
3600 /* Calculate the whole number portion of the divider */
3601 *Div = f_LO / f_Ref;
3602
3603 /* Calculate the numerator value (round to nearest f_LO_Step) */
3604 *FracN =
3605 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3606 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3607
3608 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
3609 8191);
3610}
3611
3612/****************************************************************************
3613**
3614** Name: FindClearTuneFilter
3615**
3616** Description: Calculate the corrrect ClearTune filter to be used for
3617** a given input frequency.
3618**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003619** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003620** f_in - RF input center frequency (in Hz).
3621**
3622** Returns: ClearTune filter number (0-31)
3623**
3624** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3625**
3626** Revision History:
3627**
3628** SCR Date Author Description
3629** -------------------------------------------------------------------------
3630** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3631** cross-over frequency values.
3632**
3633****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003634static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003635{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003636 u32 RFBand;
3637 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003638
3639 /*
3640 ** Find RF Band setting
3641 */
3642 RFBand = 31; /* def when f_in > all */
3643 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003644 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003645 RFBand = idx;
3646 break;
3647 }
3648 }
3649 return (RFBand);
3650}
3651
3652/****************************************************************************
3653**
3654** Name: MT2063_Tune
3655**
3656** Description: Change the tuner's tuned frequency to RFin.
3657**
3658** Parameters: h - Open handle to the tuner (from MT2063_Open).
3659** f_in - RF input center frequency (in Hz).
3660**
3661** Returns: status:
3662** MT_OK - No errors
3663** MT_INV_HANDLE - Invalid tuner handle
3664** MT_UPC_UNLOCK - Upconverter PLL unlocked
3665** MT_DNC_UNLOCK - Downconverter PLL unlocked
3666** MT_COMM_ERR - Serial bus communications error
3667** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3668** MT_SPUR_PRESENT - LO spur possible in output
3669** MT_FIN_RANGE - Input freq out of range
3670** MT_FOUT_RANGE - Output freq out of range
3671** MT_UPC_RANGE - Upconverter freq out of range
3672** MT_DNC_RANGE - Downconverter freq out of range
3673**
3674** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
3675**
3676** MT_ReadSub - Read data from the two-wire serial bus
3677** MT_WriteSub - Write data to the two-wire serial bus
3678** MT_Sleep - Delay execution for x milliseconds
3679** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
3680**
3681** Revision History:
3682**
3683** SCR Date Author Description
3684** -------------------------------------------------------------------------
3685** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3686** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
3687** cross-over frequency values.
3688** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3689** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3690** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3691**
3692****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003693static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003694{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003695
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003696 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003697 u32 LO1; /* 1st LO register value */
3698 u32 Num1; /* Numerator for LO1 reg. value */
3699 u32 f_IF1; /* 1st IF requested */
3700 u32 LO2; /* 2nd LO register value */
3701 u32 Num2; /* Numerator for LO2 reg. value */
3702 u32 ofLO1, ofLO2; /* last time's LO frequencies */
3703 u32 ofin, ofout; /* last time's I/O frequencies */
3704 u8 fiffc = 0x80; /* FIFF center freq from tuner */
3705 u32 fiffof; /* Offset from FIFF center freq */
3706 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
3707 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
3708 u8 val;
3709 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003710
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003711 /* Check the input and output frequency ranges */
3712 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003713 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003714
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003715 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
3716 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003717 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003718
3719 /*
3720 ** Save original LO1 and LO2 register values
3721 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003722 ofLO1 = state->AS_Data.f_LO1;
3723 ofLO2 = state->AS_Data.f_LO2;
3724 ofin = state->AS_Data.f_in;
3725 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003726
3727 /*
3728 ** Find and set RF Band setting
3729 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003730 if (state->ctfilt_sw == 1) {
3731 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
3732 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003733 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003734 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003735 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003736 val = state->reg[MT2063_REG_CTUNE_OV];
3737 RFBand = FindClearTuneFilter(state, f_in);
3738 state->reg[MT2063_REG_CTUNE_OV] =
3739 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003740 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003741 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003742 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003743 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003744 }
3745 }
3746
3747 /*
3748 ** Read the FIFF Center Frequency from the tuner
3749 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003750 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003751 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003752 MT2063_ReadSub(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003753 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003754 &state->reg[MT2063_REG_FIFFC], 1);
3755 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003756 }
3757 /*
3758 ** Assign in the requested values
3759 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003760 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003761 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003762 state->AS_Data.f_if1_Request =
3763 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
3764 state->AS_Data.f_LO1_Step,
3765 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003766
3767 /*
3768 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
3769 ** desired LO1 frequency
3770 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003771 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003772
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003773 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003774
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003775 state->AS_Data.f_LO1 =
3776 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
3777 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003778
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003779 state->AS_Data.f_LO2 =
3780 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3781 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003782
3783 /*
3784 ** Check for any LO spurs in the output bandwidth and adjust
3785 ** the LO settings to avoid them if needed
3786 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003787 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003788 /*
3789 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
3790 ** Recalculate the LO frequencies and the values to be placed
3791 ** in the tuning registers.
3792 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003793 state->AS_Data.f_LO1 =
3794 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
3795 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
3796 state->AS_Data.f_LO2 =
3797 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3798 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
3799 state->AS_Data.f_LO2 =
3800 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
3801 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003802
3803 /*
3804 ** Check the upconverter and downconverter frequency ranges
3805 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003806 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
3807 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003808 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003809 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
3810 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003811 status |= MT2063_DNC_RANGE;
3812 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003813 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003814 LO2LK = 0x40;
3815
3816 /*
3817 ** If we have the same LO frequencies and we're already locked,
3818 ** then skip re-programming the LO registers.
3819 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003820 if ((ofLO1 != state->AS_Data.f_LO1)
3821 || (ofLO2 != state->AS_Data.f_LO2)
3822 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003823 (LO1LK | LO2LK))) {
3824 /*
3825 ** Calculate the FIFFOF register value
3826 **
3827 ** IF1_Actual
3828 ** FIFFOF = ------------ - 8 * FIFFC - 4992
3829 ** f_ref/64
3830 */
3831 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003832 (state->AS_Data.f_LO1 -
3833 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003834 4992;
3835 if (fiffof > 0xFF)
3836 fiffof = 0xFF;
3837
3838 /*
3839 ** Place all of the calculated values into the local tuner
3840 ** register fields.
3841 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003842 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003843 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
3844 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
3845 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003846 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003847 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
3848 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003849
3850 /*
3851 ** Now write out the computed register values
3852 ** IMPORTANT: There is a required order for writing
3853 ** (0x05 must follow all the others).
3854 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003855 status |= MT2063_WriteSub(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
3856 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003857 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003858 status |= MT2063_WriteSub(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003859 }
3860 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003861 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003862 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003863 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003864 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003865 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003866 MT2063_WriteSub(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003867 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003868 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003869 reg[MT2063_REG_FIFF_OFFSET],
3870 1);
3871 }
3872 }
3873
3874 /*
3875 ** Check for LO's locking
3876 */
3877
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003878 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003879 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003880 }
3881 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003882 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003883 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003884 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003885 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003886 }
3887 }
3888
3889 return (status);
3890}
3891
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003892static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003893 enum MTTune_atv_standard tv_type)
3894{
3895
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003896 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003897
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003898 s32 pict_car = 0;
3899 s32 pict2chanb_vsb = 0;
3900 s32 pict2chanb_snd = 0;
3901 s32 pict2snd1 = 0;
3902 s32 pict2snd2 = 0;
3903 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003904
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003905 s32 if_mid = 0;
3906 s32 rcvr_mode = 0;
3907 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003908
3909 switch (tv_type) {
3910 case MTTUNEA_PAL_B:{
3911 pict_car = 38900000;
3912 ch_bw = 8000000;
3913 pict2chanb_vsb = -1250000;
3914 pict2snd1 = 5500000;
3915 pict2snd2 = 5742000;
3916 rcvr_mode = 1;
3917 break;
3918 }
3919 case MTTUNEA_PAL_G:{
3920 pict_car = 38900000;
3921 ch_bw = 7000000;
3922 pict2chanb_vsb = -1250000;
3923 pict2snd1 = 5500000;
3924 pict2snd2 = 0;
3925 rcvr_mode = 1;
3926 break;
3927 }
3928 case MTTUNEA_PAL_I:{
3929 pict_car = 38900000;
3930 ch_bw = 8000000;
3931 pict2chanb_vsb = -1250000;
3932 pict2snd1 = 6000000;
3933 pict2snd2 = 0;
3934 rcvr_mode = 1;
3935 break;
3936 }
3937 case MTTUNEA_PAL_L:{
3938 pict_car = 38900000;
3939 ch_bw = 8000000;
3940 pict2chanb_vsb = -1250000;
3941 pict2snd1 = 6500000;
3942 pict2snd2 = 0;
3943 rcvr_mode = 1;
3944 break;
3945 }
3946 case MTTUNEA_PAL_MN:{
3947 pict_car = 38900000;
3948 ch_bw = 6000000;
3949 pict2chanb_vsb = -1250000;
3950 pict2snd1 = 4500000;
3951 pict2snd2 = 0;
3952 rcvr_mode = 1;
3953 break;
3954 }
3955 case MTTUNEA_PAL_DK:{
3956 pict_car = 38900000;
3957 ch_bw = 8000000;
3958 pict2chanb_vsb = -1250000;
3959 pict2snd1 = 6500000;
3960 pict2snd2 = 0;
3961 rcvr_mode = 1;
3962 break;
3963 }
3964 case MTTUNEA_DIGITAL:{
3965 pict_car = 36125000;
3966 ch_bw = 8000000;
3967 pict2chanb_vsb = -(ch_bw / 2);
3968 pict2snd1 = 0;
3969 pict2snd2 = 0;
3970 rcvr_mode = 2;
3971 break;
3972 }
3973 case MTTUNEA_FMRADIO:{
3974 pict_car = 38900000;
3975 ch_bw = 8000000;
3976 pict2chanb_vsb = -(ch_bw / 2);
3977 pict2snd1 = 0;
3978 pict2snd2 = 0;
3979 rcvr_mode = 4;
3980 //f_in -= 2900000;
3981 break;
3982 }
3983 case MTTUNEA_DVBC:{
3984 pict_car = 36125000;
3985 ch_bw = 8000000;
3986 pict2chanb_vsb = -(ch_bw / 2);
3987 pict2snd1 = 0;
3988 pict2snd2 = 0;
3989 rcvr_mode = MT2063_CABLE_QAM;
3990 break;
3991 }
3992 case MTTUNEA_DVBT:{
3993 pict_car = 36125000;
3994 ch_bw = bw_in; //8000000
3995 pict2chanb_vsb = -(ch_bw / 2);
3996 pict2snd1 = 0;
3997 pict2snd2 = 0;
3998 rcvr_mode = MT2063_OFFAIR_COFDM;
3999 break;
4000 }
4001 case MTTUNEA_UNKNOWN:
4002 break;
4003 default:
4004 break;
4005 }
4006
4007 pict2chanb_snd = pict2chanb_vsb - ch_bw;
4008 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
4009
4010 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
4011 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
4012 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
4013 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4014
4015 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
4016 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
4017 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4018
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004019 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004020}
4021
4022static int mt2063_init(struct dvb_frontend *fe)
4023{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004024 u32 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004025 struct mt2063_state *state = fe->tuner_priv;
4026
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004027 status = MT2063_Open(fe);
4028 status |= MT2063_SoftwareShutdown(state, 1);
4029 status |= MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004030
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004031 if (0 != status) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004032 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
4033 status);
4034 return -1;
4035 }
4036
4037 return 0;
4038}
4039
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004040static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
4041{
4042 int rc = 0;
4043
4044 //get tuner lock status
4045
4046 return rc;
4047}
4048
4049static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004050 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004051{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004052 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004053
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004054 switch (param) {
4055 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004056 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004057 break;
4058 case DVBFE_TUNER_TUNERSTEP:
4059 break;
4060 case DVBFE_TUNER_IFFREQ:
4061 break;
4062 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004063 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004064 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004065 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004066 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004067 break;
4068 default:
4069 break;
4070 }
4071
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004072 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004073}
4074
4075static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004076 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004077{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004078 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004079 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004080
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004081 switch (param) {
4082 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004083 //set frequency
4084
4085 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004086 MT_Tune_atv(state,
4087 tunstate->frequency, tunstate->bandwidth,
4088 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004089
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004090 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004091 break;
4092 case DVBFE_TUNER_TUNERSTEP:
4093 break;
4094 case DVBFE_TUNER_IFFREQ:
4095 break;
4096 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004097 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004098 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004099 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004100 case DVBFE_TUNER_REFCLOCK:
4101
4102 break;
4103 case DVBFE_TUNER_OPEN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004104 status = MT2063_Open(fe);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004105 break;
4106 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004107 status = MT2063_SoftwareShutdown(state, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004108 break;
4109 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
4110 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004111 MT2063_ClearPowerMaskBits(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004112 MT2063_ALL_SD);
4113 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004114 default:
4115 break;
4116 }
4117
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004118 return (int)status;
4119}
4120
4121static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004122{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004123 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004124
4125 fe->tuner_priv = NULL;
4126 kfree(state);
4127
4128 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004129}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004130
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004131static struct dvb_tuner_ops mt2063_ops = {
4132 .info = {
4133 .name = "MT2063 Silicon Tuner",
4134 .frequency_min = 45000000,
4135 .frequency_max = 850000000,
4136 .frequency_step = 0,
4137 },
4138
4139 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03004140 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004141 .get_status = mt2063_get_status,
4142 .get_state = mt2063_get_state,
4143 .set_state = mt2063_set_state,
4144 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004145};
4146
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004147struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4148 struct mt2063_config *config,
4149 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004150{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004151 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004152
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004153 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004154 if (state == NULL)
4155 goto error;
4156
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004157 state->config = config;
4158 state->i2c = i2c;
4159 state->frontend = fe;
4160 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004161 state->MT2063_init = false;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004162 fe->tuner_priv = state;
4163 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004164
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004165 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004166 return fe;
4167
4168error:
4169 kfree(state);
4170 return NULL;
4171}
4172
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004173EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004174MODULE_PARM_DESC(verbose, "Set Verbosity level");
4175
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004176MODULE_AUTHOR("Henry");
4177MODULE_DESCRIPTION("MT2063 Silicon tuner");
4178MODULE_LICENSE("GPL");