blob: 0ae6c154477167697fe8ea7a75f36f071cfed17e [file] [log] [blame]
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03005
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006#include "mt2063.h"
7
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03008static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03009module_param(verbose, int, 0644);
10
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030011/* Internal structures and types */
12
Mauro Carvalho Chehab065719a2011-07-20 22:45:06 -030013/* FIXME: we probably don't need these new FE get/set property types for tuner */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030014#define DVBFE_TUNER_OPEN 99
15#define DVBFE_TUNER_SOFTWARE_SHUTDOWN 100
16#define DVBFE_TUNER_CLEAR_POWER_MASKBITS 101
17
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030018/* FIXME: Those two error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030019/* Error: Upconverter PLL is not locked */
20#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030021/* Error: Downconverter PLL is not locked */
22#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030023
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030024/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030025#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026
27/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
28#define MT2063_SPUR_CNT_MASK (0x001f0000)
29#define MT2063_SPUR_SHIFT (16)
30
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030031/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
32#define MT2063_UPC_RANGE (0x04000000)
33
34/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
35#define MT2063_DNC_RANGE (0x08000000)
36
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030037/*
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030038 * Data Types
39 */
40
41/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030042 * Constant defining the version of the following structure
43 * and therefore the API for this code.
44 *
45 * When compiling the tuner driver, the preprocessor will
46 * check against this version number to make sure that
47 * it matches the version that the tuner driver knows about.
48 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030049
50/* DECT Frequency Avoidance */
51#define MT2063_DECT_AVOID_US_FREQS 0x00000001
52
53#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
54
55#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
56
57#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
58
59enum MT2063_DECT_Avoid_Type {
60 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
61 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
62 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
63 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
64};
65
66#define MT2063_MAX_ZONES 48
67
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030068struct MT2063_ExclZone_t {
69 u32 min_;
70 u32 max_;
71 struct MT2063_ExclZone_t *next_;
72};
73
74/*
75 * Structure of data needed for Spur Avoidance
76 */
77struct MT2063_AvoidSpursData_t {
78 u32 nAS_Algorithm;
79 u32 f_ref;
80 u32 f_in;
81 u32 f_LO1;
82 u32 f_if1_Center;
83 u32 f_if1_Request;
84 u32 f_if1_bw;
85 u32 f_LO2;
86 u32 f_out;
87 u32 f_out_bw;
88 u32 f_LO1_Step;
89 u32 f_LO2_Step;
90 u32 f_LO1_FracN_Avoid;
91 u32 f_LO2_FracN_Avoid;
92 u32 f_zif_bw;
93 u32 f_min_LO_Separation;
94 u32 maxH1;
95 u32 maxH2;
96 enum MT2063_DECT_Avoid_Type avoidDECT;
97 u32 bSpurPresent;
98 u32 bSpurAvoided;
99 u32 nSpursFound;
100 u32 nZones;
101 struct MT2063_ExclZone_t *freeZones;
102 struct MT2063_ExclZone_t *usedZones;
103 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
104};
105
106/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300107 * Parameter for function MT2063_SetPowerMask that specifies the power down
108 * of various sections of the MT2063.
109 */
110enum MT2063_Mask_Bits {
111 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
112 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
113 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
114 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
115 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
116 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
117 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
118 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
119 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
120 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
121 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
122 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
123 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
124 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
125 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
126};
127
128/*
129 * Parameter for function MT2063_GetParam & MT2063_SetParam that
130 * specifies the tuning algorithm parameter to be read/written.
131 */
132enum MT2063_Param {
133 /* tuner address set by MT2063_Open() */
134 MT2063_IC_ADDR,
135
136 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
137 MT2063_MAX_OPEN,
138
139 /* current number of open MT2063 tuners set by MT2063_Open() */
140 MT2063_NUM_OPEN,
141
142 /* crystal frequency (default: 16000000 Hz) */
143 MT2063_SRO_FREQ,
144
145 /* min tuning step size (default: 50000 Hz) */
146 MT2063_STEPSIZE,
147
148 /* input center frequency set by MT2063_Tune() */
149 MT2063_INPUT_FREQ,
150
151 /* LO1 Frequency set by MT2063_Tune() */
152 MT2063_LO1_FREQ,
153
154 /* LO1 minimum step size (default: 250000 Hz) */
155 MT2063_LO1_STEPSIZE,
156
157 /* LO1 FracN keep-out region (default: 999999 Hz) */
158 MT2063_LO1_FRACN_AVOID_PARAM,
159
160 /* Current 1st IF in use set by MT2063_Tune() */
161 MT2063_IF1_ACTUAL,
162
163 /* Requested 1st IF set by MT2063_Tune() */
164 MT2063_IF1_REQUEST,
165
166 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
167 MT2063_IF1_CENTER,
168
169 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
170 MT2063_IF1_BW,
171
172 /* zero-IF bandwidth (default: 2000000 Hz) */
173 MT2063_ZIF_BW,
174
175 /* LO2 Frequency set by MT2063_Tune() */
176 MT2063_LO2_FREQ,
177
178 /* LO2 minimum step size (default: 50000 Hz) */
179 MT2063_LO2_STEPSIZE,
180
181 /* LO2 FracN keep-out region (default: 374999 Hz) */
182 MT2063_LO2_FRACN_AVOID,
183
184 /* output center frequency set by MT2063_Tune() */
185 MT2063_OUTPUT_FREQ,
186
187 /* output bandwidth set by MT2063_Tune() */
188 MT2063_OUTPUT_BW,
189
190 /* min inter-tuner LO separation (default: 1000000 Hz) */
191 MT2063_LO_SEPARATION,
192
193 /* ID of avoid-spurs algorithm in use compile-time constant */
194 MT2063_AS_ALG,
195
196 /* max # of intra-tuner harmonics (default: 15) */
197 MT2063_MAX_HARM1,
198
199 /* max # of inter-tuner harmonics (default: 7) */
200 MT2063_MAX_HARM2,
201
202 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
203 MT2063_EXCL_ZONES,
204
205 /* # of spurs found/avoided set by MT2063_Tune() */
206 MT2063_NUM_SPURS,
207
208 /* >0 spurs avoided set by MT2063_Tune() */
209 MT2063_SPUR_AVOIDED,
210
211 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
212 MT2063_SPUR_PRESENT,
213
214 /* Receiver Mode for some parameters. 1 is DVB-T */
215 MT2063_RCVR_MODE,
216
217 /* directly set LNA attenuation, parameter is value to set */
218 MT2063_ACLNA,
219
220 /* maximum LNA attenuation, parameter is value to set */
221 MT2063_ACLNA_MAX,
222
223 /* directly set ATN attenuation. Paremeter is value to set. */
224 MT2063_ACRF,
225
226 /* maxium ATN attenuation. Paremeter is value to set. */
227 MT2063_ACRF_MAX,
228
229 /* directly set FIF attenuation. Paremeter is value to set. */
230 MT2063_ACFIF,
231
232 /* maxium FIF attenuation. Paremeter is value to set. */
233 MT2063_ACFIF_MAX,
234
235 /* LNA Rin */
236 MT2063_LNA_RIN,
237
238 /* Power Detector LNA level target */
239 MT2063_LNA_TGT,
240
241 /* Power Detector 1 level */
242 MT2063_PD1,
243
244 /* Power Detector 1 level target */
245 MT2063_PD1_TGT,
246
247 /* Power Detector 2 level */
248 MT2063_PD2,
249
250 /* Power Detector 2 level target */
251 MT2063_PD2_TGT,
252
253 /* Selects, which DNC is activ */
254 MT2063_DNC_OUTPUT_ENABLE,
255
256 /* VGA gain code */
257 MT2063_VGAGC,
258
259 /* VGA bias current */
260 MT2063_VGAOI,
261
262 /* TAGC, determins the speed of the AGC */
263 MT2063_TAGC,
264
265 /* AMP gain code */
266 MT2063_AMPGC,
267
268 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
269 MT2063_AVOID_DECT,
270
271 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
272 MT2063_CTFILT_SW,
273
274 MT2063_EOP /* last entry in enumerated list */
275};
276
277/*
278 * Parameter for selecting tuner mode
279 */
280enum MT2063_RCVR_MODES {
281 MT2063_CABLE_QAM = 0, /* Digital cable */
282 MT2063_CABLE_ANALOG, /* Analog cable */
283 MT2063_OFFAIR_COFDM, /* Digital offair */
284 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
285 MT2063_OFFAIR_ANALOG, /* Analog offair */
286 MT2063_OFFAIR_8VSB, /* Analog offair */
287 MT2063_NUM_RCVR_MODES
288};
289
290/*
291 * Possible values for MT2063_DNC_OUTPUT
292 */
293enum MT2063_DNC_Output_Enable {
294 MT2063_DNC_NONE = 0,
295 MT2063_DNC_1,
296 MT2063_DNC_2,
297 MT2063_DNC_BOTH
298};
299
300/*
301** Two-wire serial bus subaddresses of the tuner registers.
302** Also known as the tuner's register addresses.
303*/
304enum MT2063_Register_Offsets {
305 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
306 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
307 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
308 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
309 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
310 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
311 MT2063_REG_RSVD_06, /* 0x06: Reserved */
312 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
313 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
314 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
315 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
316 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
317 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
318 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
319 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
320 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
321 MT2063_REG_RSVD_10, /* 0x10: Reserved */
322 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
323 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
324 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
325 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
326 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
327 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
328 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
329 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
330 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
331 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
332 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
333 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
334 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
335 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
336 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
337 MT2063_REG_RSVD_20, /* 0x20: Reserved */
338 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
339 MT2063_REG_RSVD_22, /* 0x22: Reserved */
340 MT2063_REG_RSVD_23, /* 0x23: Reserved */
341 MT2063_REG_RSVD_24, /* 0x24: Reserved */
342 MT2063_REG_RSVD_25, /* 0x25: Reserved */
343 MT2063_REG_RSVD_26, /* 0x26: Reserved */
344 MT2063_REG_RSVD_27, /* 0x27: Reserved */
345 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
346 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
347 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
348 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
349 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
350 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
351 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
352 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
353 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
354 MT2063_REG_RSVD_31, /* 0x31: Reserved */
355 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
356 MT2063_REG_RSVD_33, /* 0x33: Reserved */
357 MT2063_REG_RSVD_34, /* 0x34: Reserved */
358 MT2063_REG_RSVD_35, /* 0x35: Reserved */
359 MT2063_REG_RSVD_36, /* 0x36: Reserved */
360 MT2063_REG_RSVD_37, /* 0x37: Reserved */
361 MT2063_REG_RSVD_38, /* 0x38: Reserved */
362 MT2063_REG_RSVD_39, /* 0x39: Reserved */
363 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
364 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
365 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
366 MT2063_REG_END_REGS
367};
368
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300369enum MTTune_atv_standard {
370 MTTUNEA_UNKNOWN = 0,
371 MTTUNEA_PAL_B,
372 MTTUNEA_PAL_G,
373 MTTUNEA_PAL_I,
374 MTTUNEA_PAL_L,
375 MTTUNEA_PAL_MN,
376 MTTUNEA_PAL_DK,
377 MTTUNEA_DIGITAL,
378 MTTUNEA_FMRADIO,
379 MTTUNEA_DVBC,
380 MTTUNEA_DVBT
381};
382
383
384struct mt2063_state {
385 struct i2c_adapter *i2c;
386
387 const struct mt2063_config *config;
388 struct dvb_tuner_ops ops;
389 struct dvb_frontend *frontend;
390 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300391 bool MT2063_init;
392
393 enum MTTune_atv_standard tv_type;
394 u32 frequency;
395 u32 srate;
396 u32 bandwidth;
397 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300398
399 u32 tuner_id;
400 struct MT2063_AvoidSpursData_t AS_Data;
401 u32 f_IF1_actual;
402 u32 rcvr_mode;
403 u32 ctfilt_sw;
404 u32 CTFiltMax[31];
405 u32 num_regs;
406 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300407};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300408
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300409/* Prototypes */
410static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
411 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300412static u32 MT2063_ReInit(struct mt2063_state *state);
413static u32 MT2063_Close(struct mt2063_state *state);
414static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
415static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
416static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
417static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300418 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300419
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300420/*****************/
421/* From drivers/media/common/tuners/mt2063_cfg.h */
422
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300423unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300424 u32 bw_in,
425 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300426{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300427 struct dvb_frontend_ops *frontend_ops = NULL;
428 struct dvb_tuner_ops *tuner_ops = NULL;
429 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300430 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300431 int err = 0;
432
433 t_state.frequency = f_in;
434 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300435 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300436 if (&fe->ops)
437 frontend_ops = &fe->ops;
438 if (&frontend_ops->tuner_ops)
439 tuner_ops = &frontend_ops->tuner_ops;
440 if (tuner_ops->set_state) {
441 if ((err =
442 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
443 &t_state)) < 0) {
444 printk("%s: Invalid parameter\n", __func__);
445 return err;
446 }
447 }
448
449 return err;
450}
451
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300452unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300453{
454 struct dvb_frontend_ops *frontend_ops = &fe->ops;
455 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
456 struct tuner_state t_state;
457 int err = 0;
458
459 if (&fe->ops)
460 frontend_ops = &fe->ops;
461 if (&frontend_ops->tuner_ops)
462 tuner_ops = &frontend_ops->tuner_ops;
463 if (tuner_ops->get_state) {
464 if ((err =
465 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
466 &t_state)) < 0) {
467 printk("%s: Invalid parameter\n", __func__);
468 return err;
469 }
470 }
471 return err;
472}
473
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300474unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300475{
476 struct dvb_frontend_ops *frontend_ops = &fe->ops;
477 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
478 struct tuner_state t_state;
479 int err = 0;
480
481 if (&fe->ops)
482 frontend_ops = &fe->ops;
483 if (&frontend_ops->tuner_ops)
484 tuner_ops = &frontend_ops->tuner_ops;
485 if (tuner_ops->set_state) {
486 if ((err =
487 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
488 &t_state)) < 0) {
489 printk("%s: Invalid parameter\n", __func__);
490 return err;
491 }
492 }
493
494 return err;
495}
496
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300497unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300498{
499 struct dvb_frontend_ops *frontend_ops = &fe->ops;
500 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
501 struct tuner_state t_state;
502 int err = 0;
503
504 if (&fe->ops)
505 frontend_ops = &fe->ops;
506 if (&frontend_ops->tuner_ops)
507 tuner_ops = &frontend_ops->tuner_ops;
508 if (tuner_ops->set_state) {
509 if ((err =
510 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
511 &t_state)) < 0) {
512 printk("%s: Invalid parameter\n", __func__);
513 return err;
514 }
515 }
516
517 return err;
518}
519
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300520unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300521{
522 struct dvb_frontend_ops *frontend_ops = &fe->ops;
523 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
524 struct tuner_state t_state;
525 int err = 0;
526
527 if (&fe->ops)
528 frontend_ops = &fe->ops;
529 if (&frontend_ops->tuner_ops)
530 tuner_ops = &frontend_ops->tuner_ops;
531 if (tuner_ops->set_state) {
532 if ((err =
533 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
534 &t_state)) < 0) {
535 printk("%s: Invalid parameter\n", __func__);
536 return err;
537 }
538 }
539
540 return err;
541}
542
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300543/*
544 * mt2063_write - Write data into the I2C bus
545 */
546static u32 mt2063_write(struct mt2063_state *state,
547 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300548{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300549 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300550 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300551 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300552 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300553 .addr = state->config->tuner_address,
554 .flags = 0,
555 .buf = buf,
556 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300557 };
558
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300559 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300560 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300561
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300562 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300563 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300564 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300565
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
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300572/*
573 * mt2063_read - Read data from the I2C bus
574 */
575static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300576 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300577{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300578 u32 status = 0; /* Status to be returned */
579 struct dvb_frontend *fe = state->frontend;
580 u32 i = 0;
581
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300582 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300583
584 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300585 int ret;
586 u8 b0[] = { subAddress + i };
587 struct i2c_msg msg[] = {
588 {
589 .addr = state->config->tuner_address,
590 .flags = I2C_M_RD,
591 .buf = b0,
592 .len = 1
593 }, {
594 .addr = state->config->tuner_address,
595 .flags = I2C_M_RD,
596 .buf = pData + 1,
597 .len = 1
598 }
599 };
600
601 ret = i2c_transfer(state->i2c, msg, 2);
602 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300603 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300604 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300605 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300606 return (status);
607}
608
609/*****************************************************************************
610**
611** Name: MT_Sleep
612**
613** Description: Delay execution for "nMinDelayTime" milliseconds
614**
615** Parameters: hUserData - User-specific I/O parameter that was
616** passed to tuner's Open function.
617** nMinDelayTime - Delay time in milliseconds
618**
619** Returns: None.
620**
621** Notes: This is a callback function that is called from the
622** the tuning algorithm. You MUST provide code that
623** blocks execution for the specified period of time.
624**
625** Revision History:
626**
627** SCR Date Author Description
628** -------------------------------------------------------------------------
629** N/A 03-25-2004 DAD Original
630**
631*****************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300632static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300633{
634 /*
635 ** ToDo: Add code here to implement a OS blocking
636 ** for a period of "nMinDelayTime" milliseconds.
637 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300638 msleep(10);
639
640 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300641}
642
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300643//end of mt2063_userdef.c
644//=================================================================
645//#################################################################
646//=================================================================
647
648//context of mt2063_spuravoid.c <Henry> ======================================
649//#################################################################
650//=================================================================
651
652/*****************************************************************************
653**
654** Name: mt_spuravoid.c
655**
656** Description: Microtune spur avoidance software module.
657** Supports Microtune tuner drivers.
658**
659** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
660** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
661**
662** Revision History:
663**
664** SCR Date Author Description
665** -------------------------------------------------------------------------
666** 082 03-25-2005 JWS Original multi-tuner support - requires
667** MTxxxx_CNT declarations
668** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
669** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
670** of compiler warnings
671** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
672** avoidance into a single module.
673** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
674** (f_min, f_max) < 0, ignore the entry.
675** 115 03-23-2007 DAD Fix declaration of spur due to truncation
676** errors.
677** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
678** tuner DLL.
679** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
680** multi-tuners that have
681** (delta IF1) > (f_out-f_outbw/2).
682** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
683** Added logic to force f_Center within 1/2 f_Step.
684** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
685** Type casts added to preserve correct sign.
686** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
687** frequencies into MT_ResetExclZones().
688** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
689**
690*****************************************************************************/
691
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300692
693/* Implement ceiling, floor functions. */
694#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
695#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
696#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
697#define ufloor(n, d) ((n)/(d))
698
699struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300700 s32 min_;
701 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300702};
703
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300704
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300705static u32 MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300706{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300707 pAS_Info->nAS_Algorithm = 1;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300708 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300709}
710
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300711static void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300712{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300713}
714
715/*
716** Reset all exclusion zones.
717** Add zones to protect the PLL FracN regions near zero
718**
719** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
720** frequencies into MT_ResetExclZones().
721*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300722static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300723{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300724 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300725
726 pAS_Info->nZones = 0; /* this clears the used list */
727 pAS_Info->usedZones = NULL; /* reset ptr */
728 pAS_Info->freeZones = NULL; /* reset ptr */
729
730 center =
731 pAS_Info->f_ref *
732 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
733 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
734 while (center <
735 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
736 pAS_Info->f_LO1_FracN_Avoid) {
737 /* Exclude LO1 FracN */
738 MT2063_AddExclZone(pAS_Info,
739 center - pAS_Info->f_LO1_FracN_Avoid,
740 center - 1);
741 MT2063_AddExclZone(pAS_Info, center + 1,
742 center + pAS_Info->f_LO1_FracN_Avoid);
743 center += pAS_Info->f_ref;
744 }
745
746 center =
747 pAS_Info->f_ref *
748 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
749 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
750 while (center <
751 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
752 pAS_Info->f_LO2_FracN_Avoid) {
753 /* Exclude LO2 FracN */
754 MT2063_AddExclZone(pAS_Info,
755 center - pAS_Info->f_LO2_FracN_Avoid,
756 center - 1);
757 MT2063_AddExclZone(pAS_Info, center + 1,
758 center + pAS_Info->f_LO2_FracN_Avoid);
759 center += pAS_Info->f_ref;
760 }
761
762 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
763 /* Exclude LO1 values that conflict with DECT channels */
764 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
765 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
766 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
767 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
768 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
769 }
770
771 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
772 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
773 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
774 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
775 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
776 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
777 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
778 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
779 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
780 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
781 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
782 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300783}
784
785static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
786 *pAS_Info,
787 struct MT2063_ExclZone_t *pPrevNode)
788{
789 struct MT2063_ExclZone_t *pNode;
790 /* Check for a node in the free list */
791 if (pAS_Info->freeZones != NULL) {
792 /* Use one from the free list */
793 pNode = pAS_Info->freeZones;
794 pAS_Info->freeZones = pNode->next_;
795 } else {
796 /* Grab a node from the array */
797 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
798 }
799
800 if (pPrevNode != NULL) {
801 pNode->next_ = pPrevNode->next_;
802 pPrevNode->next_ = pNode;
803 } else { /* insert at the beginning of the list */
804
805 pNode->next_ = pAS_Info->usedZones;
806 pAS_Info->usedZones = pNode;
807 }
808
809 pAS_Info->nZones++;
810 return pNode;
811}
812
813static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
814 *pAS_Info,
815 struct MT2063_ExclZone_t *pPrevNode,
816 struct MT2063_ExclZone_t
817 *pNodeToRemove)
818{
819 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
820
821 /* Make previous node point to the subsequent node */
822 if (pPrevNode != NULL)
823 pPrevNode->next_ = pNext;
824
825 /* Add pNodeToRemove to the beginning of the freeZones */
826 pNodeToRemove->next_ = pAS_Info->freeZones;
827 pAS_Info->freeZones = pNodeToRemove;
828
829 /* Decrement node count */
830 pAS_Info->nZones--;
831
832 return pNext;
833}
834
835/*****************************************************************************
836**
837** Name: MT_AddExclZone
838**
839** Description: Add (and merge) an exclusion zone into the list.
840** If the range (f_min, f_max) is totally outside the
841** 1st IF BW, ignore the entry.
842** If the range (f_min, f_max) is negative, ignore the entry.
843**
844** Revision History:
845**
846** SCR Date Author Description
847** -------------------------------------------------------------------------
848** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
849** (f_min, f_max) < 0, ignore the entry.
850**
851*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300852static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300853 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300854{
855 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
856 struct MT2063_ExclZone_t *pPrev = NULL;
857 struct MT2063_ExclZone_t *pNext = NULL;
858
859 /* Check to see if this overlaps the 1st IF filter */
860 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
861 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
862 && (f_min < f_max)) {
863 /*
864 ** 1 2 3 4 5 6
865 **
866 ** New entry: |---| |--| |--| |-| |---| |--|
867 ** or or or or or
868 ** Existing: |--| |--| |--| |---| |-| |--|
869 */
870
871 /* Check for our place in the list */
872 while ((pNode != NULL) && (pNode->max_ < f_min)) {
873 pPrev = pNode;
874 pNode = pNode->next_;
875 }
876
877 if ((pNode != NULL) && (pNode->min_ < f_max)) {
878 /* Combine me with pNode */
879 if (f_min < pNode->min_)
880 pNode->min_ = f_min;
881 if (f_max > pNode->max_)
882 pNode->max_ = f_max;
883 } else {
884 pNode = InsertNode(pAS_Info, pPrev);
885 pNode->min_ = f_min;
886 pNode->max_ = f_max;
887 }
888
889 /* Look for merging possibilities */
890 pNext = pNode->next_;
891 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
892 if (pNext->max_ > pNode->max_)
893 pNode->max_ = pNext->max_;
894 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
895 }
896 }
897}
898
899/*****************************************************************************
900**
901** Name: MT_ChooseFirstIF
902**
903** Description: Choose the best available 1st IF
904** If f_Desired is not excluded, choose that first.
905** Otherwise, return the value closest to f_Center that is
906** not excluded
907**
908** Revision History:
909**
910** SCR Date Author Description
911** -------------------------------------------------------------------------
912** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
913** tuner DLL.
914** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
915** Added logic to force f_Center within 1/2 f_Step.
916**
917*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300918static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300919{
920 /*
921 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
922 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
923 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
924 ** However, the sum must be.
925 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300926 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300927 pAS_Info->f_LO1_Step *
928 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
929 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
930 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300931 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300932 (pAS_Info->f_LO1_Step >
933 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
934 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300935 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300936
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300937 s32 i;
938 s32 j = 0;
939 u32 bDesiredExcluded = 0;
940 u32 bZeroExcluded = 0;
941 s32 tmpMin, tmpMax;
942 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300943 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
944 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
945
946 if (pAS_Info->nZones == 0)
947 return f_Desired;
948
949 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
950 if (pAS_Info->f_if1_Center > f_Desired)
951 f_Center =
952 f_Desired +
953 f_Step *
954 ((pAS_Info->f_if1_Center - f_Desired +
955 f_Step / 2) / f_Step);
956 else
957 f_Center =
958 f_Desired -
959 f_Step *
960 ((f_Desired - pAS_Info->f_if1_Center +
961 f_Step / 2) / f_Step);
962
963 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300964 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300965 // return 0;
966
967 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
968 while (pNode != NULL) {
969 /* floor function */
970 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300971 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300972
973 /* ceil function */
974 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300975 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300976
977 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
978 bDesiredExcluded = 1;
979
980 if ((tmpMin < 0) && (tmpMax > 0))
981 bZeroExcluded = 1;
982
983 /* See if this zone overlaps the previous */
984 if ((j > 0) && (tmpMin < zones[j - 1].max_))
985 zones[j - 1].max_ = tmpMax;
986 else {
987 /* Add new zone */
988 //assert(j<MT2063_MAX_ZONES);
989 //if (j>=MT2063_MAX_ZONES)
990 //break;
991
992 zones[j].min_ = tmpMin;
993 zones[j].max_ = tmpMax;
994 j++;
995 }
996 pNode = pNode->next_;
997 }
998
999 /*
1000 ** If the desired is okay, return with it
1001 */
1002 if (bDesiredExcluded == 0)
1003 return f_Desired;
1004
1005 /*
1006 ** If the desired is excluded and the center is okay, return with it
1007 */
1008 if (bZeroExcluded == 0)
1009 return f_Center;
1010
1011 /* Find the value closest to 0 (f_Center) */
1012 bestDiff = zones[0].min_;
1013 for (i = 0; i < j; i++) {
1014 if (abs(zones[i].min_) < abs(bestDiff))
1015 bestDiff = zones[i].min_;
1016 if (abs(zones[i].max_) < abs(bestDiff))
1017 bestDiff = zones[i].max_;
1018 }
1019
1020 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001021 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001022
1023 return f_Center + (bestDiff * f_Step);
1024}
1025
1026/****************************************************************************
1027**
1028** Name: gcd
1029**
1030** Description: Uses Euclid's algorithm
1031**
1032** Parameters: u, v - unsigned values whose GCD is desired.
1033**
1034** Global: None
1035**
1036** Returns: greatest common divisor of u and v, if either value
1037** is 0, the other value is returned as the result.
1038**
1039** Dependencies: None.
1040**
1041** Revision History:
1042**
1043** SCR Date Author Description
1044** -------------------------------------------------------------------------
1045** N/A 06-01-2004 JWS Original
1046** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
1047** unsigned numbers.
1048**
1049****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001050static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001051{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001052 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001053
1054 while (v != 0) {
1055 r = u % v;
1056 u = v;
1057 v = r;
1058 }
1059
1060 return u;
1061}
1062
1063/****************************************************************************
1064**
1065** Name: umax
1066**
1067** Description: Implements a simple maximum function for unsigned numbers.
1068** Implemented as a function rather than a macro to avoid
1069** multiple evaluation of the calling parameters.
1070**
1071** Parameters: a, b - Values to be compared
1072**
1073** Global: None
1074**
1075** Returns: larger of the input values.
1076**
1077** Dependencies: None.
1078**
1079** Revision History:
1080**
1081** SCR Date Author Description
1082** -------------------------------------------------------------------------
1083** N/A 06-02-2004 JWS Original
1084**
1085****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001086static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001087{
1088 return (a >= b) ? a : b;
1089}
1090
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001091/****************************************************************************
1092**
1093** Name: IsSpurInBand
1094**
1095** Description: Checks to see if a spur will be present within the IF's
1096** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1097**
1098** ma mb mc md
1099** <--+-+-+-------------------+-------------------+-+-+-->
1100** | ^ 0 ^ |
1101** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1102** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1103**
1104** Note that some equations are doubled to prevent round-off
1105** problems when calculating fIFBW/2
1106**
1107** Parameters: pAS_Info - Avoid Spurs information block
1108** fm - If spur, amount f_IF1 has to move negative
1109** fp - If spur, amount f_IF1 has to move positive
1110**
1111** Global: None
1112**
1113** Returns: 1 if an LO spur would be present, otherwise 0.
1114**
1115** Dependencies: None.
1116**
1117** Revision History:
1118**
1119** SCR Date Author Description
1120** -------------------------------------------------------------------------
1121** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1122**
1123****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001124static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1125 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001126{
1127 /*
1128 ** Calculate LO frequency settings.
1129 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001130 u32 n, n0;
1131 const u32 f_LO1 = pAS_Info->f_LO1;
1132 const u32 f_LO2 = pAS_Info->f_LO2;
1133 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1134 const u32 c = d - pAS_Info->f_out_bw;
1135 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -03001136 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001137 s32 f_nsLO1, f_nsLO2;
1138 s32 f_Spur;
1139 u32 ma, mb, mc, md, me, mf;
1140 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001141 *fm = 0;
1142
1143 /*
1144 ** For each edge (d, c & f), calculate a scale, based on the gcd
1145 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1146 ** gcd-based scale factor or f_Scale.
1147 */
1148 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001149 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001150 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001151 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001152 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001153 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001154 hgfs = gf_Scale / 2;
1155
1156 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1157
1158 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1159 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1160 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1161 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1162
1163 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1164 if (md >= pAS_Info->maxH1)
1165 break;
1166
1167 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1168 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1169
1170 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1171 if (md == ma)
1172 continue;
1173
1174 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1175 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1176 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001177 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1178 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001179 f_Spur =
1180 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1181 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1182
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001183 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1184 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001185 return 1;
1186 }
1187
1188 /* Location of Zero-IF-spur to be checked */
1189 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1190 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1191 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1192 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1193 if (me != mf) {
1194 f_nsLO1 = n * (f_LO1 / gf_Scale);
1195 f_nsLO2 = me * (f_LO2 / gf_Scale);
1196 f_Spur =
1197 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1198 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1199
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001200 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1201 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001202 return 1;
1203 }
1204
1205 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1206 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1207 if (ma != mb) {
1208 f_nsLO1 = n * (f_LO1 / gc_Scale);
1209 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1210 f_Spur =
1211 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1212 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1213
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001214 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1215 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001216 return 1;
1217 }
1218 }
1219
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001220 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001221 return 0;
1222}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001223
1224/*****************************************************************************
1225**
1226** Name: MT_AvoidSpurs
1227**
1228** Description: Main entry point to avoid spurs.
1229** Checks for existing spurs in present LO1, LO2 freqs
1230** and if present, chooses spur-free LO1, LO2 combination
1231** that tunes the same input/output frequencies.
1232**
1233** Revision History:
1234**
1235** SCR Date Author Description
1236** -------------------------------------------------------------------------
1237** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1238**
1239*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001240static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001241{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001242 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001243 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001244 pAS_Info->bSpurAvoided = 0;
1245 pAS_Info->nSpursFound = 0;
1246
1247 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001248 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001249
1250 /*
1251 ** Avoid LO Generated Spurs
1252 **
1253 ** Make sure that have no LO-related spurs within the IF output
1254 ** bandwidth.
1255 **
1256 ** If there is an LO spur in this band, start at the current IF1 frequency
1257 ** and work out until we find a spur-free frequency or run up against the
1258 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1259 ** will be unchanged if a spur-free setting is not found.
1260 */
1261 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1262 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001263 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1264 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1265 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1266 u32 delta_IF1;
1267 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001268
1269 /*
1270 ** Spur was found, attempt to find a spur-free 1st IF
1271 */
1272 do {
1273 pAS_Info->nSpursFound++;
1274
1275 /* Raise f_IF1_upper, if needed */
1276 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1277
1278 /* Choose next IF1 that is closest to f_IF1_CENTER */
1279 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1280
1281 if (new_IF1 > zfIF1) {
1282 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1283 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1284 } else {
1285 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1286 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1287 }
1288 zfIF1 = new_IF1;
1289
1290 if (zfIF1 > pAS_Info->f_if1_Center)
1291 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1292 else
1293 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1294 }
1295 /*
1296 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1297 ** and there is a spur in the band (again)
1298 */
1299 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1300 pAS_Info->f_if1_bw)
1301 && (pAS_Info->bSpurPresent =
1302 IsSpurInBand(pAS_Info, &fm, &fp)));
1303
1304 /*
1305 ** Use the LO-spur free values found. If the search went all the way to
1306 ** the 1st IF band edge and always found spurs, just leave the original
1307 ** choice. It's as "good" as any other.
1308 */
1309 if (pAS_Info->bSpurPresent == 1) {
1310 status |= MT2063_SPUR_PRESENT_ERR;
1311 pAS_Info->f_LO1 = zfLO1;
1312 pAS_Info->f_LO2 = zfLO2;
1313 } else
1314 pAS_Info->bSpurAvoided = 1;
1315 }
1316
1317 status |=
1318 ((pAS_Info->
1319 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1320
1321 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001322}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001323
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001324//end of mt2063_spuravoid.c
1325//=================================================================
1326//#################################################################
1327//=================================================================
1328
1329/*
1330** The expected version of MT_AvoidSpursData_t
1331** If the version is different, an updated file is needed from Microtune
1332*/
1333/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001334
1335typedef enum {
1336 MT2063_SET_ATTEN,
1337 MT2063_INCR_ATTEN,
1338 MT2063_DECR_ATTEN
1339} MT2063_ATTEN_CNTL_MODE;
1340
1341//#define TUNER_MT2063_OPTIMIZATION
1342/*
1343** Constants used by the tuning algorithm
1344*/
1345#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1346#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1347#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1348#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1349#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1350#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1351#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1352#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1353#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1354#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1355#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1356#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1357#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1358#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1359#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1360#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1361#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1362#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1363
1364/*
1365** Define the supported Part/Rev codes for the MT2063
1366*/
1367#define MT2063_B0 (0x9B)
1368#define MT2063_B1 (0x9C)
1369#define MT2063_B2 (0x9D)
1370#define MT2063_B3 (0x9E)
1371
1372/*
1373** The number of Tuner Registers
1374*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001375static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001376
1377#define USE_GLOBAL_TUNER 0
1378
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001379static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001380static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001381
1382/*
1383** Constants for setting receiver modes.
1384** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1385** (DNC1GC & DNC2GC are the values, which are used, when the specific
1386** DNC Output is selected, the other is always off)
1387**
1388** If PAL-L or L' is received, set:
1389** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1390**
1391** --------------+----------------------------------------------
1392** Mode 0 : | MT2063_CABLE_QAM
1393** Mode 1 : | MT2063_CABLE_ANALOG
1394** Mode 2 : | MT2063_OFFAIR_COFDM
1395** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1396** Mode 4 : | MT2063_OFFAIR_ANALOG
1397** Mode 5 : | MT2063_OFFAIR_8VSB
1398** --------------+----+----+----+----+-----+-----+--------------
1399** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1400** --------------+----+----+----+----+-----+-----+
1401**
1402**
1403*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001404static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1405static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1406static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1407static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1408static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1409static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1410static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1411static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1412static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1413static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1414static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1415static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1416static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1417static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001418
1419/*
1420** Local Function Prototypes - not available for external access.
1421*/
1422
1423/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001424static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1425 u32 f_LO_Step, u32 f_Ref);
1426static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1427 u32 f_LO_Step, u32 f_Ref);
1428static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1429 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001430
1431/******************************************************************************
1432**
1433** Name: MT2063_Open
1434**
1435** Description: Initialize the tuner's register values.
1436**
1437** Parameters: MT2063_Addr - Serial bus address of the tuner.
1438** hMT2063 - Tuner handle passed back.
1439** hUserData - User-defined data, if needed for the
1440** MT_ReadSub() & MT_WriteSub functions.
1441**
1442** Returns: status:
1443** MT_OK - No errors
1444** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1445** MT_TUNER_INIT_ERR - Tuner initialization failed
1446** MT_COMM_ERR - Serial bus communications error
1447** MT_ARG_NULL - Null pointer argument passed
1448** MT_TUNER_CNT_ERR - Too many tuners open
1449**
1450** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1451** MT_WriteSub - Write byte(s) of data to the two-wire bus
1452**
1453** Revision History:
1454**
1455** SCR Date Author Description
1456** -------------------------------------------------------------------------
1457** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1458**
1459******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001460static u32 MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001461{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001462 u32 status; /* Status to be returned. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001463 struct mt2063_state *state = fe->tuner_priv;
1464
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001465 /* Default tuner handle to NULL. If successful, it will be reassigned */
1466
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001467 if (state->MT2063_init == false)
1468 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001469
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001470 status = MT2063_RegisterTuner(&state->AS_Data);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001471 if (status >= 0) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001472 state->rcvr_mode = MT2063_CABLE_QAM;
1473 status = MT2063_ReInit(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001474 }
1475
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001476 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001477 /* MT2063_Close handles the un-registration of the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001478 MT2063_Close(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001479 else {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001480 state->MT2063_init = true;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001481 }
1482
1483 return (status);
1484}
1485
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001486/******************************************************************************
1487**
1488** Name: MT2063_Close
1489**
1490** Description: Release the handle to the tuner.
1491**
1492** Parameters: hMT2063 - Handle to the MT2063 tuner
1493**
1494** Returns: status:
1495** MT_OK - No errors
1496** MT_INV_HANDLE - Invalid tuner handle
1497**
1498** Dependencies: mt_errordef.h - definition of error codes
1499**
1500** Revision History:
1501**
1502** SCR Date Author Description
1503** -------------------------------------------------------------------------
1504** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1505**
1506******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001507static u32 MT2063_Close(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001508{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001509 /* Unregister tuner with SpurAvoidance routines (if needed) */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001510 MT2063_UnRegisterTuner(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001511 /* Now remove the tuner from our own list of tuners */
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001512
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001513 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001514}
1515
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001516/****************************************************************************
1517**
1518** Name: MT2063_GetLocked
1519**
1520** Description: Checks to see if LO1 and LO2 are locked.
1521**
1522** Parameters: h - Open handle to the tuner (from MT2063_Open).
1523**
1524** Returns: status:
1525** MT_OK - No errors
1526** MT_UPC_UNLOCK - Upconverter PLL unlocked
1527** MT_DNC_UNLOCK - Downconverter PLL unlocked
1528** MT_COMM_ERR - Serial bus communications error
1529** MT_INV_HANDLE - Invalid tuner handle
1530**
1531** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1532** MT_Sleep - Delay execution for x milliseconds
1533**
1534** Revision History:
1535**
1536** SCR Date Author Description
1537** -------------------------------------------------------------------------
1538** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1539**
1540****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001541static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001542{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001543 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1544 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1545 const u32 nMaxLoops = nMaxWait / nPollRate;
1546 const u8 LO1LK = 0x80;
1547 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001548 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001549 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001550
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001551 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001552 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001553 LO2LK = 0x40;
1554
1555 do {
1556 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001557 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001558 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001559 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001560
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001561 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001562 return (status);
1563
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001564 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001565 (LO1LK | LO2LK)) {
1566 return (status);
1567 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001568 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001569 }
1570 while (++nDelays < nMaxLoops);
1571
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001572 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001573 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001574 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001575 status |= MT2063_DNC_UNLOCK;
1576
1577 return (status);
1578}
1579
1580/****************************************************************************
1581**
1582** Name: MT2063_GetParam
1583**
1584** Description: Gets a tuning algorithm parameter.
1585**
1586** This function provides access to the internals of the
1587** tuning algorithm - mostly for testing purposes.
1588**
1589** Parameters: h - Tuner handle (returned by MT2063_Open)
1590** param - Tuning algorithm parameter
1591** (see enum MT2063_Param)
1592** pValue - ptr to returned value
1593**
1594** param Description
1595** ---------------------- --------------------------------
1596** MT2063_IC_ADDR Serial Bus address of this tuner
1597** MT2063_MAX_OPEN Max # of MT2063's allowed open
1598** MT2063_NUM_OPEN # of MT2063's open
1599** MT2063_SRO_FREQ crystal frequency
1600** MT2063_STEPSIZE minimum tuning step size
1601** MT2063_INPUT_FREQ input center frequency
1602** MT2063_LO1_FREQ LO1 Frequency
1603** MT2063_LO1_STEPSIZE LO1 minimum step size
1604** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1605** MT2063_IF1_ACTUAL Current 1st IF in use
1606** MT2063_IF1_REQUEST Requested 1st IF
1607** MT2063_IF1_CENTER Center of 1st IF SAW filter
1608** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1609** MT2063_ZIF_BW zero-IF bandwidth
1610** MT2063_LO2_FREQ LO2 Frequency
1611** MT2063_LO2_STEPSIZE LO2 minimum step size
1612** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1613** MT2063_OUTPUT_FREQ output center frequency
1614** MT2063_OUTPUT_BW output bandwidth
1615** MT2063_LO_SEPARATION min inter-tuner LO separation
1616** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1617** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1618** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1619** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1620** MT2063_NUM_SPURS # of spurs found/avoided
1621** MT2063_SPUR_AVOIDED >0 spurs avoided
1622** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1623** MT2063_RCVR_MODE Predefined modes.
1624** MT2063_ACLNA LNA attenuator gain code
1625** MT2063_ACRF RF attenuator gain code
1626** MT2063_ACFIF FIF attenuator gain code
1627** MT2063_ACLNA_MAX LNA attenuator limit
1628** MT2063_ACRF_MAX RF attenuator limit
1629** MT2063_ACFIF_MAX FIF attenuator limit
1630** MT2063_PD1 Actual value of PD1
1631** MT2063_PD2 Actual value of PD2
1632** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1633** MT2063_VGAGC VGA gain code
1634** MT2063_VGAOI VGA output current
1635** MT2063_TAGC TAGC setting
1636** MT2063_AMPGC AMP gain code
1637** MT2063_AVOID_DECT Avoid DECT Frequencies
1638** MT2063_CTFILT_SW Cleartune filter selection
1639**
1640** Usage: status |= MT2063_GetParam(hMT2063,
1641** MT2063_IF1_ACTUAL,
1642** &f_IF1_Actual);
1643**
1644** Returns: status:
1645** MT_OK - No errors
1646** MT_INV_HANDLE - Invalid tuner handle
1647** MT_ARG_NULL - Null pointer argument passed
1648** MT_ARG_RANGE - Invalid parameter requested
1649**
1650** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1651**
1652** See Also: MT2063_SetParam, MT2063_Open
1653**
1654** Revision History:
1655**
1656** SCR Date Author Description
1657** -------------------------------------------------------------------------
1658** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1659** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1660** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1661** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1662** in GetParam.
1663** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1664** Split SetParam up to ACLNA / ACLNA_MAX
1665** removed ACLNA_INRC/DECR (+RF & FIF)
1666** removed GCUAUTO / BYPATNDN/UP
1667** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1668** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1669** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1670**
1671****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001672static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001673{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001674 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001675 u32 Div;
1676 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001677
1678 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001679 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001680
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001681 switch (param) {
1682 /* Serial Bus address of this tuner */
1683 case MT2063_IC_ADDR:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001684 *pValue = state->config->tuner_address;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001685 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001686
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001687 /* Max # of MT2063's allowed to be open */
1688 case MT2063_MAX_OPEN:
1689 *pValue = nMT2063MaxTuners;
1690 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001691
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001692 /* # of MT2063's open */
1693 case MT2063_NUM_OPEN:
1694 *pValue = nMT2063OpenTuners;
1695 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001696
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001697 /* crystal frequency */
1698 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001699 *pValue = state->AS_Data.f_ref;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001700 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001701
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001702 /* minimum tuning step size */
1703 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001704 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001705 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001706
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001707 /* input center frequency */
1708 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001709 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001710 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001711
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001712 /* LO1 Frequency */
1713 case MT2063_LO1_FREQ:
1714 {
1715 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1716 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001717 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001718 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001719 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001720 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001721 Div = state->reg[MT2063_REG_LO1C_1];
1722 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1723 state->AS_Data.f_LO1 =
1724 (state->AS_Data.f_ref * Div) +
1725 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001726 f_ref, Num, 64);
1727 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001728 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001729 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001730
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001731 /* LO1 minimum step size */
1732 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001733 *pValue = state->AS_Data.f_LO1_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001734 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001735
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001736 /* LO1 FracN keep-out region */
1737 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001738 *pValue = state->AS_Data.f_LO1_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001739 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001740
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001741 /* Current 1st IF in use */
1742 case MT2063_IF1_ACTUAL:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001743 *pValue = state->f_IF1_actual;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001744 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001745
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001746 /* Requested 1st IF */
1747 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001748 *pValue = state->AS_Data.f_if1_Request;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001749 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001750
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001751 /* Center of 1st IF SAW filter */
1752 case MT2063_IF1_CENTER:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001753 *pValue = state->AS_Data.f_if1_Center;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001754 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001755
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001756 /* Bandwidth of 1st IF SAW filter */
1757 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001758 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001759 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001760
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001761 /* zero-IF bandwidth */
1762 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001763 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001764 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001765
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001766 /* LO2 Frequency */
1767 case MT2063_LO2_FREQ:
1768 {
1769 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1770 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001771 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001772 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001773 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001774 reg[MT2063_REG_LO2C_1], 3);
1775 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001776 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001777 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001778 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001779 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001780 (state->
1781 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001782 reg
1783 [MT2063_REG_LO2C_3]
1784 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001785 state->AS_Data.f_LO2 =
1786 (state->AS_Data.f_ref * Div) +
1787 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001788 f_ref, Num, 8191);
1789 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001790 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001791 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001792
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001793 /* LO2 minimum step size */
1794 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001795 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001796 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001797
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001798 /* LO2 FracN keep-out region */
1799 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001800 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
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 /* output center frequency */
1804 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001805 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001806 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001807
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001808 /* output bandwidth */
1809 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001810 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001811 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001812
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001813 /* min inter-tuner LO separation */
1814 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001815 *pValue = state->AS_Data.f_min_LO_Separation;
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 /* ID of avoid-spurs algorithm in use */
1819 case MT2063_AS_ALG:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001820 *pValue = state->AS_Data.nAS_Algorithm;
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 /* max # of intra-tuner harmonics */
1824 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001825 *pValue = state->AS_Data.maxH1;
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 /* max # of inter-tuner harmonics */
1829 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001830 *pValue = state->AS_Data.maxH2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001831 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001832
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001833 /* # of 1st IF exclusion zones */
1834 case MT2063_EXCL_ZONES:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001835 *pValue = state->AS_Data.nZones;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001836 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001837
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001838 /* # of spurs found/avoided */
1839 case MT2063_NUM_SPURS:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001840 *pValue = state->AS_Data.nSpursFound;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001841 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001842
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001843 /* >0 spurs avoided */
1844 case MT2063_SPUR_AVOIDED:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001845 *pValue = state->AS_Data.bSpurAvoided;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001846 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001847
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001848 /* >0 spurs in output (mathematically) */
1849 case MT2063_SPUR_PRESENT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001850 *pValue = state->AS_Data.bSpurPresent;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001851 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001852
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001853 /* Predefined receiver setup combination */
1854 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001855 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001856 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001857
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001858 case MT2063_PD1:
1859 case MT2063_PD2: {
1860 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001861 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001862 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1863 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001864
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001865 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001866
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001867 /* Initiate ADC output to reg 0x0A */
1868 if (reg != orig)
1869 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001870 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001871 MT2063_REG_BYP_CTRL,
1872 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001873
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001874 if (status < 0)
1875 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001876
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001877 for (i = 0; i < 8; i++) {
1878 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001879 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001880 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001881 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001882 reg
1883 [MT2063_REG_ADC_OUT],
1884 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001885
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001886 if (status >= 0)
1887 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001888 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001889 reg[MT2063_REG_ADC_OUT];
1890 else {
1891 if (i)
1892 *pValue /= i;
1893 return (status);
1894 }
1895 }
1896 *pValue /= 8; /* divide by number of reads */
1897 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001898
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001899 /* Restore value of Register BYP_CTRL */
1900 if (reg != orig)
1901 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001902 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001903 MT2063_REG_BYP_CTRL,
1904 &orig, 1);
1905 }
1906 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001907
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001908 /* Get LNA attenuator code */
1909 case MT2063_ACLNA:
1910 {
1911 u8 val;
1912 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001913 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001914 &val);
1915 *pValue = val & 0x1f;
1916 }
1917 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001918
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001919 /* Get RF attenuator code */
1920 case MT2063_ACRF:
1921 {
1922 u8 val;
1923 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001924 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001925 &val);
1926 *pValue = val & 0x1f;
1927 }
1928 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001929
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001930 /* Get FIF attenuator code */
1931 case MT2063_ACFIF:
1932 {
1933 u8 val;
1934 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001935 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001936 &val);
1937 *pValue = val & 0x1f;
1938 }
1939 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001940
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001941 /* Get LNA attenuator limit */
1942 case MT2063_ACLNA_MAX:
1943 {
1944 u8 val;
1945 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001946 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001947 &val);
1948 *pValue = val & 0x1f;
1949 }
1950 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001951
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001952 /* Get RF attenuator limit */
1953 case MT2063_ACRF_MAX:
1954 {
1955 u8 val;
1956 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001957 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001958 &val);
1959 *pValue = val & 0x1f;
1960 }
1961 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001962
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001963 /* Get FIF attenuator limit */
1964 case MT2063_ACFIF_MAX:
1965 {
1966 u8 val;
1967 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001968 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001969 &val);
1970 *pValue = val & 0x1f;
1971 }
1972 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001973
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001974 /* Get current used DNC output */
1975 case MT2063_DNC_OUTPUT_ENABLE:
1976 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001977 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1978 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001979 *pValue =
1980 (u32) MT2063_DNC_NONE;
1981 else
1982 *pValue =
1983 (u32) MT2063_DNC_2;
1984 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001985
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001986 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001987 *pValue =
1988 (u32) MT2063_DNC_1;
1989 else
1990 *pValue =
1991 (u32) MT2063_DNC_BOTH;
1992 }
1993 }
1994 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001996 /* Get VGA Gain Code */
1997 case MT2063_VGAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001998 *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001999 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002000
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002001 /* Get VGA bias current */
2002 case MT2063_VGAOI:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002003 *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002004 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002005
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002006 /* Get TAGC setting */
2007 case MT2063_TAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002008 *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002009 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002010
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002011 /* Get AMP Gain Code */
2012 case MT2063_AMPGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002013 *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002014 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002015
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002016 /* Avoid DECT Frequencies */
2017 case MT2063_AVOID_DECT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002018 *pValue = state->AS_Data.avoidDECT;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002019 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002020
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002021 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2022 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002023 *pValue = state->ctfilt_sw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002024 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002025
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002026 case MT2063_EOP:
2027 default:
2028 status |= -ERANGE;
2029 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002030 return (status);
2031}
2032
2033/****************************************************************************
2034**
2035** Name: MT2063_GetReg
2036**
2037** Description: Gets an MT2063 register.
2038**
2039** Parameters: h - Tuner handle (returned by MT2063_Open)
2040** reg - MT2063 register/subaddress location
2041** *val - MT2063 register/subaddress value
2042**
2043** Returns: status:
2044** MT_OK - No errors
2045** MT_COMM_ERR - Serial bus communications error
2046** MT_INV_HANDLE - Invalid tuner handle
2047** MT_ARG_NULL - Null pointer argument passed
2048** MT_ARG_RANGE - Argument out of range
2049**
2050** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2051**
2052** Use this function if you need to read a register from
2053** the MT2063.
2054**
2055** Revision History:
2056**
2057** SCR Date Author Description
2058** -------------------------------------------------------------------------
2059** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2060**
2061****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002062static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002063{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002064 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002065
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002066 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002067 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002068
2069 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002070 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002071
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002072 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002073
2074 return (status);
2075}
2076
2077/******************************************************************************
2078**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002079** Name: MT2063_SetReceiverMode
2080**
2081** Description: Set the MT2063 receiver mode
2082**
2083** --------------+----------------------------------------------
2084** Mode 0 : | MT2063_CABLE_QAM
2085** Mode 1 : | MT2063_CABLE_ANALOG
2086** Mode 2 : | MT2063_OFFAIR_COFDM
2087** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2088** Mode 4 : | MT2063_OFFAIR_ANALOG
2089** Mode 5 : | MT2063_OFFAIR_8VSB
2090** --------------+----+----+----+----+-----+--------------------
2091** (DNC1GC & DNC2GC are the values, which are used, when the specific
2092** DNC Output is selected, the other is always off)
2093**
2094** |<---------- Mode -------------->|
2095** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2096** ------------+-----+-----+-----+-----+-----+-----+
2097** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2098** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2099** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2100** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2101** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2102** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2103** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2104** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2105** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2106** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2107** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2108** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2109** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2110** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2111** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2112**
2113**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002114** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002115** Mode - desired reciever mode
2116**
2117** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2118**
2119** Returns: status:
2120** MT_OK - No errors
2121** MT_COMM_ERR - Serial bus communications error
2122**
2123** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2124** Assumes that the tuner cache is valid.
2125**
2126** Revision History:
2127**
2128** SCR Date Author Description
2129** -------------------------------------------------------------------------
2130** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2131** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2132** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2133** modulation
2134** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2135** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2136** the same settings as with MT Launcher
2137** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2138** Add SetParam DNC_OUTPUT_ENABLE
2139** Removed VGAGC from receiver mode,
2140** default now 1
2141** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2142** Add SetParam AMPGC, removed from rcvr-mode
2143** Corrected names of GCU values
2144** reorganized receiver modes, removed,
2145** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2146** Actualized Receiver-Mode values
2147** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2148** N/A 11-27-2007 PINZ Improved buffered writing
2149** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2150** correct wakeup of the LNA after shutdown
2151** Set AFCsd = 1 as default
2152** Changed CAP1sel default
2153** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2154** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2155** Split SetParam up to ACLNA / ACLNA_MAX
2156** removed ACLNA_INRC/DECR (+RF & FIF)
2157** removed GCUAUTO / BYPATNDN/UP
2158**
2159******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002160static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002161 enum MT2063_RCVR_MODES Mode)
2162{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002163 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002164 u8 val;
2165 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002166
2167 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002168 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002169
2170 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002171 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002172 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002173 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002174 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002175 ? 0x40 :
2176 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002177 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2178 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002179 }
2180 }
2181
2182 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002183 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002184 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002185 }
2186
2187 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002188 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002189 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002190 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002191 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002192 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002193 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002194 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002195 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002196 /* trigger FIFF calibration, needed after changing FIFFQ */
2197 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002198 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002199 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002200 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002201 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002202 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002203 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002204 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002205 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002206 }
2207 }
2208
2209 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002210 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
2211 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002212
2213 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002214 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002215 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002216 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002217 }
2218
2219 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002220 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002221 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002222 }
2223
2224 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002225 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002226 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002227 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002228 }
2229
2230 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002231 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002232 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002233 }
2234
2235 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002236 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002237 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002238 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002239 }
2240
2241 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002242 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002243 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002244 }
2245
2246 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002247 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002248 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002249 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002250 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002251 ? 0x80 :
2252 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002253 if (state->reg[MT2063_REG_LNA_TGT] != val) {
2254 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002255 }
2256 }
2257
2258 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002259 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002260 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002261 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002262 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002263 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002264 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2265 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002266 }
2267 }
2268
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002269 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002270 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002271
2272 return (status);
2273}
2274
2275/******************************************************************************
2276**
2277** Name: MT2063_ReInit
2278**
2279** Description: Initialize the tuner's register values.
2280**
2281** Parameters: h - Tuner handle (returned by MT2063_Open)
2282**
2283** Returns: status:
2284** MT_OK - No errors
2285** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2286** MT_INV_HANDLE - Invalid tuner handle
2287** MT_COMM_ERR - Serial bus communications error
2288**
2289** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2290** MT_WriteSub - Write byte(s) of data to the two-wire bus
2291**
2292** Revision History:
2293**
2294** SCR Date Author Description
2295** -------------------------------------------------------------------------
2296** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2297** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2298** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2299** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2300** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2301** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2302** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2303** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2304** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2305** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2306** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2307**
2308******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002309static u32 MT2063_ReInit(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002310{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002311 u8 all_resets = 0xF0; /* reset/load bits */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002312 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03002313 u8 *def = NULL;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002314 u32 FCRUN;
2315 s32 maxReads;
2316 u32 fcu_osc;
2317 u32 i;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002318 u8 MT2063B0_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002319 0x19, 0x05,
2320 0x1B, 0x1D,
2321 0x1C, 0x1F,
2322 0x1D, 0x0F,
2323 0x1E, 0x3F,
2324 0x1F, 0x0F,
2325 0x20, 0x3F,
2326 0x22, 0x21,
2327 0x23, 0x3F,
2328 0x24, 0x20,
2329 0x25, 0x3F,
2330 0x27, 0xEE,
2331 0x2C, 0x27, /* bit at 0x20 is cleared below */
2332 0x30, 0x03,
2333 0x2C, 0x07, /* bit at 0x20 is cleared here */
2334 0x2D, 0x87,
2335 0x2E, 0xAA,
2336 0x28, 0xE1, /* Set the FIFCrst bit here */
2337 0x28, 0xE0, /* Clear the FIFCrst bit here */
2338 0x00
2339 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002340 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002341 u8 MT2063B1_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002342 0x05, 0xF0,
2343 0x11, 0x10, /* New Enable AFCsd */
2344 0x19, 0x05,
2345 0x1A, 0x6C,
2346 0x1B, 0x24,
2347 0x1C, 0x28,
2348 0x1D, 0x8F,
2349 0x1E, 0x14,
2350 0x1F, 0x8F,
2351 0x20, 0x57,
2352 0x22, 0x21, /* New - ver 1.03 */
2353 0x23, 0x3C, /* New - ver 1.10 */
2354 0x24, 0x20, /* New - ver 1.03 */
2355 0x2C, 0x24, /* bit at 0x20 is cleared below */
2356 0x2D, 0x87, /* FIFFQ=0 */
2357 0x2F, 0xF3,
2358 0x30, 0x0C, /* New - ver 1.11 */
2359 0x31, 0x1B, /* New - ver 1.11 */
2360 0x2C, 0x04, /* bit at 0x20 is cleared here */
2361 0x28, 0xE1, /* Set the FIFCrst bit here */
2362 0x28, 0xE0, /* Clear the FIFCrst bit here */
2363 0x00
2364 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002365 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002366 u8 MT2063B3_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002367 0x05, 0xF0,
2368 0x19, 0x3D,
2369 0x2C, 0x24, /* bit at 0x20 is cleared below */
2370 0x2C, 0x04, /* bit at 0x20 is cleared here */
2371 0x28, 0xE1, /* Set the FIFCrst bit here */
2372 0x28, 0xE0, /* Clear the FIFCrst bit here */
2373 0x00
2374 };
2375
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002376 /* Read the Part/Rev code from the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002377 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002378 if (status < 0)
2379 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002380
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002381 /* Check the part/rev code */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002382 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2383 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2384 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002385 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002386
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002387 /* Check the 2nd byte of the Part/Rev code from the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002388 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002389 MT2063_REG_RSVD_3B,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002390 &state->reg[MT2063_REG_RSVD_3B], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002391
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002392 if (status >= 0
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002393 &&((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002394 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002395
2396 /* Reset the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002397 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002398 if (status < 0)
2399 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002400
2401 /* change all of the default values that vary from the HW reset values */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002402 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2403 switch (state->reg[MT2063_REG_PART_REV]) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002404 case MT2063_B3:
2405 def = MT2063B3_defaults;
2406 break;
2407
2408 case MT2063_B1:
2409 def = MT2063B1_defaults;
2410 break;
2411
2412 case MT2063_B0:
2413 def = MT2063B0_defaults;
2414 break;
2415
2416 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002417 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002418 break;
2419 }
2420
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002421 while (status >= 0 && *def) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002422 u8 reg = *def++;
2423 u8 val = *def++;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002424 status = mt2063_write(state, reg, &val, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002425 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002426 if (status < 0)
2427 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002428
2429 /* Wait for FIFF location to complete. */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002430 FCRUN = 1;
2431 maxReads = 10;
2432 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
2433 msleep(2);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002434 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002435 MT2063_REG_XO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002436 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002437 reg[MT2063_REG_XO_STATUS], 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002438 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002439 }
2440
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002441 if (FCRUN != 0)
2442 return -ENODEV;
2443
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002444 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002445 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002446 &state->reg[MT2063_REG_FIFFC], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002447 if (status < 0)
2448 return status;
2449
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002450 /* Read back all the registers from the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002451 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002452 MT2063_REG_PART_REV,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002453 state->reg, MT2063_REG_END_REGS);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002454 if (status < 0)
2455 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002456
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002457 /* Initialize the tuner state. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002458 state->tuner_id = state->reg[MT2063_REG_PART_REV];
2459 state->AS_Data.f_ref = MT2063_REF_FREQ;
2460 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
2461 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
2462 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
2463 state->AS_Data.f_out = 43750000UL;
2464 state->AS_Data.f_out_bw = 6750000UL;
2465 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2466 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
2467 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2468 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2469 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2470 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2471 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
2472 state->AS_Data.f_LO1 = 2181000000UL;
2473 state->AS_Data.f_LO2 = 1486249786UL;
2474 state->f_IF1_actual = state->AS_Data.f_if1_Center;
2475 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
2476 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2477 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2478 state->num_regs = MT2063_REG_END_REGS;
2479 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2480 state->ctfilt_sw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002481
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002482 state->CTFiltMax[0] = 69230000;
2483 state->CTFiltMax[1] = 105770000;
2484 state->CTFiltMax[2] = 140350000;
2485 state->CTFiltMax[3] = 177110000;
2486 state->CTFiltMax[4] = 212860000;
2487 state->CTFiltMax[5] = 241130000;
2488 state->CTFiltMax[6] = 274370000;
2489 state->CTFiltMax[7] = 309820000;
2490 state->CTFiltMax[8] = 342450000;
2491 state->CTFiltMax[9] = 378870000;
2492 state->CTFiltMax[10] = 416210000;
2493 state->CTFiltMax[11] = 456500000;
2494 state->CTFiltMax[12] = 495790000;
2495 state->CTFiltMax[13] = 534530000;
2496 state->CTFiltMax[14] = 572610000;
2497 state->CTFiltMax[15] = 598970000;
2498 state->CTFiltMax[16] = 635910000;
2499 state->CTFiltMax[17] = 672130000;
2500 state->CTFiltMax[18] = 714840000;
2501 state->CTFiltMax[19] = 739660000;
2502 state->CTFiltMax[20] = 770410000;
2503 state->CTFiltMax[21] = 814660000;
2504 state->CTFiltMax[22] = 846950000;
2505 state->CTFiltMax[23] = 867820000;
2506 state->CTFiltMax[24] = 915980000;
2507 state->CTFiltMax[25] = 947450000;
2508 state->CTFiltMax[26] = 983110000;
2509 state->CTFiltMax[27] = 1021630000;
2510 state->CTFiltMax[28] = 1061870000;
2511 state->CTFiltMax[29] = 1098330000;
2512 state->CTFiltMax[30] = 1138990000;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002513
2514 /*
2515 ** Fetch the FCU osc value and use it and the fRef value to
2516 ** scale all of the Band Max values
2517 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002518
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002519 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002520 status = mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002521 MT2063_REG_CTUNE_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002522 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002523 if (status < 0)
2524 return status;
2525 /* Read the ClearTune filter calibration value */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002526 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002527 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002528 &state->reg[MT2063_REG_FIFFC], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002529 if (status < 0)
2530 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002531
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002532 fcu_osc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002533
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002534 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002535 status = mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002536 MT2063_REG_CTUNE_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002537 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002538 if (status < 0)
2539 return status;
2540
2541 /* Adjust each of the values in the ClearTune filter cross-over table */
2542 for (i = 0; i < 31; i++)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002543 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002544
2545 return (status);
2546}
2547
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002548/****************************************************************************
2549**
2550** Name: MT2063_SetParam
2551**
2552** Description: Sets a tuning algorithm parameter.
2553**
2554** This function provides access to the internals of the
2555** tuning algorithm. You can override many of the tuning
2556** algorithm defaults using this function.
2557**
2558** Parameters: h - Tuner handle (returned by MT2063_Open)
2559** param - Tuning algorithm parameter
2560** (see enum MT2063_Param)
2561** nValue - value to be set
2562**
2563** param Description
2564** ---------------------- --------------------------------
2565** MT2063_SRO_FREQ crystal frequency
2566** MT2063_STEPSIZE minimum tuning step size
2567** MT2063_LO1_FREQ LO1 frequency
2568** MT2063_LO1_STEPSIZE LO1 minimum step size
2569** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2570** MT2063_IF1_REQUEST Requested 1st IF
2571** MT2063_ZIF_BW zero-IF bandwidth
2572** MT2063_LO2_FREQ LO2 frequency
2573** MT2063_LO2_STEPSIZE LO2 minimum step size
2574** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2575** MT2063_OUTPUT_FREQ output center frequency
2576** MT2063_OUTPUT_BW output bandwidth
2577** MT2063_LO_SEPARATION min inter-tuner LO separation
2578** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2579** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2580** MT2063_RCVR_MODE Predefined modes
2581** MT2063_LNA_RIN Set LNA Rin (*)
2582** MT2063_LNA_TGT Set target power level at LNA (*)
2583** MT2063_PD1_TGT Set target power level at PD1 (*)
2584** MT2063_PD2_TGT Set target power level at PD2 (*)
2585** MT2063_ACLNA_MAX LNA attenuator limit (*)
2586** MT2063_ACRF_MAX RF attenuator limit (*)
2587** MT2063_ACFIF_MAX FIF attenuator limit (*)
2588** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2589** MT2063_VGAGC VGA gain code
2590** MT2063_VGAOI VGA output current
2591** MT2063_TAGC TAGC setting
2592** MT2063_AMPGC AMP gain code
2593** MT2063_AVOID_DECT Avoid DECT Frequencies
2594** MT2063_CTFILT_SW Cleartune filter selection
2595**
2596** (*) This parameter is set by MT2063_RCVR_MODE, do not call
2597** additionally.
2598**
2599** Usage: status |= MT2063_SetParam(hMT2063,
2600** MT2063_STEPSIZE,
2601** 50000);
2602**
2603** Returns: status:
2604** MT_OK - No errors
2605** MT_INV_HANDLE - Invalid tuner handle
2606** MT_ARG_NULL - Null pointer argument passed
2607** MT_ARG_RANGE - Invalid parameter requested
2608** or set value out of range
2609** or non-writable parameter
2610**
2611** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2612**
2613** See Also: MT2063_GetParam, MT2063_Open
2614**
2615** Revision History:
2616**
2617** SCR Date Author Description
2618** -------------------------------------------------------------------------
2619** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2620** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2621** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2622** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2623** Split SetParam up to ACLNA / ACLNA_MAX
2624** removed ACLNA_INRC/DECR (+RF & FIF)
2625** removed GCUAUTO / BYPATNDN/UP
2626** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2627** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2628** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2629**
2630****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002631static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002632 enum MT2063_Param param,
2633 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002634{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002635 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002636 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002637
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002638 switch (param) {
2639 /* crystal frequency */
2640 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002641 state->AS_Data.f_ref = nValue;
2642 state->AS_Data.f_LO1_FracN_Avoid = 0;
2643 state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
2644 state->AS_Data.f_LO1_Step = nValue / 64;
2645 state->AS_Data.f_if1_Center =
2646 (state->AS_Data.f_ref / 8) *
2647 (state->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002648 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002649
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002650 /* minimum tuning step size */
2651 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002652 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002653 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002654
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002655 /* LO1 frequency */
2656 case MT2063_LO1_FREQ:
2657 {
2658 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2659 /* Capture the Divider and Numerator portions of other LO */
2660 u8 tempLO2CQ[3];
2661 u8 tempLO2C[3];
2662 u8 tmpOneShot;
2663 u32 Div, FracN;
2664 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002665
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002666 /* Buffer the queue for restoration later and get actual LO2 values. */
2667 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002668 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002669 MT2063_REG_LO2CQ_1,
2670 &(tempLO2CQ[0]), 3);
2671 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002672 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002673 MT2063_REG_LO2C_1,
2674 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002675
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002676 /* clear the one-shot bits */
2677 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
2678 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002679
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002680 /* only write the queue values if they are different from the actual. */
2681 if ((tempLO2CQ[0] != tempLO2C[0]) ||
2682 (tempLO2CQ[1] != tempLO2C[1]) ||
2683 (tempLO2CQ[2] != tempLO2C[2])) {
2684 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002685 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002686 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002687 MT2063_REG_LO2CQ_1,
2688 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002689
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002690 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002691 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002692 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002693 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002694 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002695 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002696 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002697 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002698 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002699 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002700 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002701
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002702 /* Calculate the Divider and Numberator components of LO1 */
2703 status =
2704 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002705 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002706 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002707 state->AS_Data.f_ref);
2708 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002709 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002710 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002711 (u8) (FracN);
2712 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002713 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002714 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002715 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002716 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002717
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002718 /* set the one-shot bit to load the pair of LO values */
2719 tmpOneShot = tempLO2CQ[2] | 0xE0;
2720 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002721 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002722 MT2063_REG_LO2CQ_3,
2723 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002724
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002725 /* only restore the queue values if they were different from the actual. */
2726 if (restore) {
2727 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002728 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002729 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002730 MT2063_REG_LO2CQ_1,
2731 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002732
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002733 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002734 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002735 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002736 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002737 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002738 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002739 tempLO2CQ[2];
2740 }
2741
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002742 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002743 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002744 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002745 }
2746 break;
2747
2748 /* LO1 minimum step size */
2749 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002750 state->AS_Data.f_LO1_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002751 break;
2752
2753 /* LO1 FracN keep-out region */
2754 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002755 state->AS_Data.f_LO1_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002756 break;
2757
2758 /* Requested 1st IF */
2759 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002760 state->AS_Data.f_if1_Request = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002761 break;
2762
2763 /* zero-IF bandwidth */
2764 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002765 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002766 break;
2767
2768 /* LO2 frequency */
2769 case MT2063_LO2_FREQ:
2770 {
2771 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2772 /* Capture the Divider and Numerator portions of other LO */
2773 u8 tempLO1CQ[2];
2774 u8 tempLO1C[2];
2775 u32 Div2;
2776 u32 FracN2;
2777 u8 tmpOneShot;
2778 u8 restore = 0;
2779
2780 /* Buffer the queue for restoration later and get actual LO2 values. */
2781 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002782 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002783 MT2063_REG_LO1CQ_1,
2784 &(tempLO1CQ[0]), 2);
2785 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002786 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002787 MT2063_REG_LO1C_1,
2788 &(tempLO1C[0]), 2);
2789
2790 /* only write the queue values if they are different from the actual. */
2791 if ((tempLO1CQ[0] != tempLO1C[0])
2792 || (tempLO1CQ[1] != tempLO1C[1])) {
2793 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002794 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002795 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002796 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002797 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002798
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002799 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002800 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002801 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002802 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002803 tempLO1C[1];
2804 restore = 1;
2805 }
2806
2807 /* Calculate the Divider and Numberator components of LO2 */
2808 status =
2809 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002810 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002811 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002812 state->AS_Data.f_ref);
2813 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002814 (u8) ((Div2 << 1) |
2815 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002816 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002817 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002818 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002819 (u8) ((FracN2 & 0x0F));
2820 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002821 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002822 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002823 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002824 reg[MT2063_REG_LO1CQ_1], 3);
2825
2826 /* set the one-shot bit to load the LO values */
2827 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002828 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002829 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002830 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002831 MT2063_REG_LO2CQ_3,
2832 &tmpOneShot, 1);
2833
2834 /* only restore LO1 queue value if they were different from the actual. */
2835 if (restore) {
2836 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002837 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002838 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002839 MT2063_REG_LO1CQ_1,
2840 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002841
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002842 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002843 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002844 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002845 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002846 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002847 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002848
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002849 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002850 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002851 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002852 }
2853 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002854
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002855 /* LO2 minimum step size */
2856 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002857 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002858 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002859
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002860 /* LO2 FracN keep-out region */
2861 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002862 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002863 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002864
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002865 /* output center frequency */
2866 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002867 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002868 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002869
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002870 /* output bandwidth */
2871 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002872 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002873 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002874
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002875 /* min inter-tuner LO separation */
2876 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002877 state->AS_Data.f_min_LO_Separation = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002878 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002879
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002880 /* max # of intra-tuner harmonics */
2881 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002882 state->AS_Data.maxH1 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002883 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002884
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002885 /* max # of inter-tuner harmonics */
2886 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002887 state->AS_Data.maxH2 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002888 break;
2889
2890 case MT2063_RCVR_MODE:
2891 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002892 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002893 (enum MT2063_RCVR_MODES)
2894 nValue);
2895 break;
2896
2897 /* Set LNA Rin -- nValue is desired value */
2898 case MT2063_LNA_RIN:
2899 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002900 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002901 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2902 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002903 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002904 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002905 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002906 val);
2907 }
2908 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002909
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002910 /* Set target power level at LNA -- nValue is desired value */
2911 case MT2063_LNA_TGT:
2912 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002913 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002914 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2915 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002916 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002917 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002918 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002919 val);
2920 }
2921 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002922
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002923 /* Set target power level at PD1 -- nValue is desired value */
2924 case MT2063_PD1_TGT:
2925 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002926 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002927 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2928 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002929 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002930 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002931 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002932 val);
2933 }
2934 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002935
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002936 /* Set target power level at PD2 -- nValue is desired value */
2937 case MT2063_PD2_TGT:
2938 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002939 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002940 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2941 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002942 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002943 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002944 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002945 val);
2946 }
2947 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002948
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002949 /* Set LNA atten limit -- nValue is desired value */
2950 case MT2063_ACLNA_MAX:
2951 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002952 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002953 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2954 &
2955 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002956 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002957 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002958 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002959 val);
2960 }
2961 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002962
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002963 /* Set RF atten limit -- nValue is desired value */
2964 case MT2063_ACRF_MAX:
2965 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002966 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002967 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2968 &
2969 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002970 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002971 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002972 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002973 }
2974 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002975
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002976 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2977 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002978 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002979 && nValue > 5)
2980 nValue = 5;
2981 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002982 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002983 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2984 &
2985 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002986 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002987 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002988 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002989 val);
2990 }
2991 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002992
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002993 case MT2063_DNC_OUTPUT_ENABLE:
2994 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002995 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002996 case MT2063_DNC_NONE:
2997 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002998 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2999 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003000 val)
3001 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003002 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003003 MT2063_REG_DNC_GAIN,
3004 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003005
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003006 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3007 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003008 val)
3009 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003010 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003011 MT2063_REG_VGA_GAIN,
3012 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003013
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003014 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3015 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003016 val)
3017 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003018 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003019 MT2063_REG_RSVD_20,
3020 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003021
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003022 break;
3023 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003024 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003025 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003026 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3027 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003028 val)
3029 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003030 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003031 MT2063_REG_DNC_GAIN,
3032 val);
3033
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003034 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3035 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003036 val)
3037 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003038 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003039 MT2063_REG_VGA_GAIN,
3040 val);
3041
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003042 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3043 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003044 val)
3045 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003046 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003047 MT2063_REG_RSVD_20,
3048 val);
3049
3050 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003051 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003052 case MT2063_DNC_2:
3053 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003054 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3055 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003056 val)
3057 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003058 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003059 MT2063_REG_DNC_GAIN,
3060 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003061
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003062 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3063 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003064 val)
3065 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003066 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003067 MT2063_REG_VGA_GAIN,
3068 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003069
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003070 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3071 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003072 val)
3073 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003074 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003075 MT2063_REG_RSVD_20,
3076 val);
3077
3078 break;
3079 }
3080 case MT2063_DNC_BOTH:
3081 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003082 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3083 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003084 val)
3085 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003086 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003087 MT2063_REG_DNC_GAIN,
3088 val);
3089
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003090 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3091 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003092 val)
3093 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003094 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003095 MT2063_REG_VGA_GAIN,
3096 val);
3097
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003098 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3099 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003100 val)
3101 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003102 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003103 MT2063_REG_RSVD_20,
3104 val);
3105
3106 break;
3107 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003108 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003109 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003110 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003111 break;
3112
3113 case MT2063_VGAGC:
3114 /* Set VGA gain code */
3115 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003116 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003117 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
3118 ((nValue & 0x03) << 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003119 if (state->reg[MT2063_REG_VGA_GAIN] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003120 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003121 MT2063_SetReg(state, MT2063_REG_VGA_GAIN,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003122 val);
3123 }
3124 break;
3125
3126 case MT2063_VGAOI:
3127 /* Set VGA bias current */
3128 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003129 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003130 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
3131 (nValue & 0x07);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003132 if (state->reg[MT2063_REG_RSVD_31] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003133 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003134 MT2063_SetReg(state, MT2063_REG_RSVD_31,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003135 val);
3136 }
3137 break;
3138
3139 case MT2063_TAGC:
3140 /* Set TAGC */
3141 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003142 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003143 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
3144 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003145 if (state->reg[MT2063_REG_RSVD_1E] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003146 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003147 MT2063_SetReg(state, MT2063_REG_RSVD_1E,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003148 val);
3149 }
3150 break;
3151
3152 case MT2063_AMPGC:
3153 /* Set Amp gain code */
3154 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003155 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003156 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
3157 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003158 if (state->reg[MT2063_REG_TEMP_SEL] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003159 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003160 MT2063_SetReg(state, MT2063_REG_TEMP_SEL,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003161 val);
3162 }
3163 break;
3164
3165 /* Avoid DECT Frequencies */
3166 case MT2063_AVOID_DECT:
3167 {
3168 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3169 (enum MT2063_DECT_Avoid_Type)nValue;
3170 if ((newAvoidSetting >=
3171 MT2063_NO_DECT_AVOIDANCE)
3172 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003173 state->AS_Data.avoidDECT =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003174 newAvoidSetting;
3175 }
3176 }
3177 break;
3178
3179 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3180 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003181 state->ctfilt_sw = (nValue & 0x01);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003182 break;
3183
3184 /* These parameters are read-only */
3185 case MT2063_IC_ADDR:
3186 case MT2063_MAX_OPEN:
3187 case MT2063_NUM_OPEN:
3188 case MT2063_INPUT_FREQ:
3189 case MT2063_IF1_ACTUAL:
3190 case MT2063_IF1_CENTER:
3191 case MT2063_IF1_BW:
3192 case MT2063_AS_ALG:
3193 case MT2063_EXCL_ZONES:
3194 case MT2063_SPUR_AVOIDED:
3195 case MT2063_NUM_SPURS:
3196 case MT2063_SPUR_PRESENT:
3197 case MT2063_ACLNA:
3198 case MT2063_ACRF:
3199 case MT2063_ACFIF:
3200 case MT2063_EOP:
3201 default:
3202 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003203 }
3204 return (status);
3205}
3206
3207/****************************************************************************
3208**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003209** Name: MT2063_ClearPowerMaskBits
3210**
3211** Description: Clears the power-down mask bits for various sections of
3212** the MT2063
3213**
3214** Parameters: h - Tuner handle (returned by MT2063_Open)
3215** Bits - Mask bits to be cleared.
3216**
3217** See definition of MT2063_Mask_Bits type for description
3218** of each of the power bits.
3219**
3220** Returns: status:
3221** MT_OK - No errors
3222** MT_INV_HANDLE - Invalid tuner handle
3223** MT_COMM_ERR - Serial bus communications error
3224**
3225** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3226**
3227** Revision History:
3228**
3229** SCR Date Author Description
3230** -------------------------------------------------------------------------
3231** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3232**
3233****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003234static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003235{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003236 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003237
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003238 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3239 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003240 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003241 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003242 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003243 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003244 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003245 }
3246 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003247 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003248 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003249 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003250 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003251 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003252 }
3253
3254 return (status);
3255}
3256
3257/****************************************************************************
3258**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003259** Name: MT2063_SoftwareShutdown
3260**
3261** Description: Enables or disables software shutdown function. When
3262** Shutdown==1, any section whose power mask is set will be
3263** shutdown.
3264**
3265** Parameters: h - Tuner handle (returned by MT2063_Open)
3266** Shutdown - 1 = shutdown the masked sections, otherwise
3267** power all sections on
3268**
3269** Returns: status:
3270** MT_OK - No errors
3271** MT_INV_HANDLE - Invalid tuner handle
3272** MT_COMM_ERR - Serial bus communications error
3273**
3274** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3275**
3276** Revision History:
3277**
3278** SCR Date Author Description
3279** -------------------------------------------------------------------------
3280** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3281** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3282** correct wakeup of the LNA
3283**
3284****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003285static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003286{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003287 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003288
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003289 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003290 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003291 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003292 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003293
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003294 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003295 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003296 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003297 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003298
3299 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003300 state->reg[MT2063_REG_BYP_CTRL] =
3301 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003302 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003303 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003304 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003305 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003306 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003307 state->reg[MT2063_REG_BYP_CTRL] =
3308 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003309 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003310 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003311 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003312 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003313 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003314 }
3315
3316 return (status);
3317}
3318
3319/****************************************************************************
3320**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003321** Name: MT2063_SetReg
3322**
3323** Description: Sets an MT2063 register.
3324**
3325** Parameters: h - Tuner handle (returned by MT2063_Open)
3326** reg - MT2063 register/subaddress location
3327** val - MT2063 register/subaddress value
3328**
3329** Returns: status:
3330** MT_OK - No errors
3331** MT_COMM_ERR - Serial bus communications error
3332** MT_INV_HANDLE - Invalid tuner handle
3333** MT_ARG_RANGE - Argument out of range
3334**
3335** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3336**
3337** Use this function if you need to override a default
3338** register value
3339**
3340** Revision History:
3341**
3342** SCR Date Author Description
3343** -------------------------------------------------------------------------
3344** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3345**
3346****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003347static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003348{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003349 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003350
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003351 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003352 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003353
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003354 status = mt2063_write(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003355 1);
3356 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003357 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003358
3359 return (status);
3360}
3361
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003362static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003363{
3364 return f_ref * (f_LO / f_ref)
3365 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
3366}
3367
3368/****************************************************************************
3369**
3370** Name: fLO_FractionalTerm
3371**
3372** Description: Calculates the portion contributed by FracN / denom.
3373**
3374** This function preserves maximum precision without
3375** risk of overflow. It accurately calculates
3376** f_ref * num / denom to within 1 HZ with fixed math.
3377**
3378** Parameters: num - Fractional portion of the multiplier
3379** denom - denominator portion of the ratio
3380** This routine successfully handles denom values
3381** up to and including 2^18.
3382** f_Ref - SRO frequency. This calculation handles
3383** f_ref as two separate 14-bit fields.
3384** Therefore, a maximum value of 2^28-1
3385** may safely be used for f_ref. This is
3386** the genesis of the magic number "14" and the
3387** magic mask value of 0x03FFF.
3388**
3389** Returns: f_ref * num / denom
3390**
3391** Revision History:
3392**
3393** SCR Date Author Description
3394** -------------------------------------------------------------------------
3395** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3396**
3397****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003398static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
3399 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003400{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003401 u32 t1 = (f_ref >> 14) * num;
3402 u32 term1 = t1 / denom;
3403 u32 loss = t1 % denom;
3404 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003405 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
3406 return ((term1 << 14) + term2);
3407}
3408
3409/****************************************************************************
3410**
3411** Name: CalcLO1Mult
3412**
3413** Description: Calculates Integer divider value and the numerator
3414** value for a FracN PLL.
3415**
3416** This function assumes that the f_LO and f_Ref are
3417** evenly divisible by f_LO_Step.
3418**
3419** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3420** FracN - OUTPUT: Fractional portion of the multiplier
3421** f_LO - desired LO frequency.
3422** f_LO_Step - Minimum step size for the LO (in Hz).
3423** f_Ref - SRO frequency.
3424** f_Avoid - Range of PLL frequencies to avoid near
3425** integer multiples of f_Ref (in Hz).
3426**
3427** Returns: Recalculated LO frequency.
3428**
3429** Revision History:
3430**
3431** SCR Date Author Description
3432** -------------------------------------------------------------------------
3433** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3434**
3435****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003436static u32 MT2063_CalcLO1Mult(u32 * Div,
3437 u32 * FracN,
3438 u32 f_LO,
3439 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003440{
3441 /* Calculate the whole number portion of the divider */
3442 *Div = f_LO / f_Ref;
3443
3444 /* Calculate the numerator value (round to nearest f_LO_Step) */
3445 *FracN =
3446 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3447 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3448
3449 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
3450}
3451
3452/****************************************************************************
3453**
3454** Name: CalcLO2Mult
3455**
3456** Description: Calculates Integer divider value and the numerator
3457** value for a FracN PLL.
3458**
3459** This function assumes that the f_LO and f_Ref are
3460** evenly divisible by f_LO_Step.
3461**
3462** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3463** FracN - OUTPUT: Fractional portion of the multiplier
3464** f_LO - desired LO frequency.
3465** f_LO_Step - Minimum step size for the LO (in Hz).
3466** f_Ref - SRO frequency.
3467** f_Avoid - Range of PLL frequencies to avoid near
3468** integer multiples of f_Ref (in Hz).
3469**
3470** Returns: Recalculated LO frequency.
3471**
3472** Revision History:
3473**
3474** SCR Date Author Description
3475** -------------------------------------------------------------------------
3476** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3477**
3478****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003479static u32 MT2063_CalcLO2Mult(u32 * Div,
3480 u32 * FracN,
3481 u32 f_LO,
3482 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003483{
3484 /* Calculate the whole number portion of the divider */
3485 *Div = f_LO / f_Ref;
3486
3487 /* Calculate the numerator value (round to nearest f_LO_Step) */
3488 *FracN =
3489 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3490 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3491
3492 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
3493 8191);
3494}
3495
3496/****************************************************************************
3497**
3498** Name: FindClearTuneFilter
3499**
3500** Description: Calculate the corrrect ClearTune filter to be used for
3501** a given input frequency.
3502**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003503** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003504** f_in - RF input center frequency (in Hz).
3505**
3506** Returns: ClearTune filter number (0-31)
3507**
3508** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3509**
3510** Revision History:
3511**
3512** SCR Date Author Description
3513** -------------------------------------------------------------------------
3514** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3515** cross-over frequency values.
3516**
3517****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003518static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003519{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003520 u32 RFBand;
3521 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003522
3523 /*
3524 ** Find RF Band setting
3525 */
3526 RFBand = 31; /* def when f_in > all */
3527 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003528 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003529 RFBand = idx;
3530 break;
3531 }
3532 }
3533 return (RFBand);
3534}
3535
3536/****************************************************************************
3537**
3538** Name: MT2063_Tune
3539**
3540** Description: Change the tuner's tuned frequency to RFin.
3541**
3542** Parameters: h - Open handle to the tuner (from MT2063_Open).
3543** f_in - RF input center frequency (in Hz).
3544**
3545** Returns: status:
3546** MT_OK - No errors
3547** MT_INV_HANDLE - Invalid tuner handle
3548** MT_UPC_UNLOCK - Upconverter PLL unlocked
3549** MT_DNC_UNLOCK - Downconverter PLL unlocked
3550** MT_COMM_ERR - Serial bus communications error
3551** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3552** MT_SPUR_PRESENT - LO spur possible in output
3553** MT_FIN_RANGE - Input freq out of range
3554** MT_FOUT_RANGE - Output freq out of range
3555** MT_UPC_RANGE - Upconverter freq out of range
3556** MT_DNC_RANGE - Downconverter freq out of range
3557**
3558** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
3559**
3560** MT_ReadSub - Read data from the two-wire serial bus
3561** MT_WriteSub - Write data to the two-wire serial bus
3562** MT_Sleep - Delay execution for x milliseconds
3563** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
3564**
3565** Revision History:
3566**
3567** SCR Date Author Description
3568** -------------------------------------------------------------------------
3569** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3570** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
3571** cross-over frequency values.
3572** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3573** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3574** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3575**
3576****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003577static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003578{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003579
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003580 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003581 u32 LO1; /* 1st LO register value */
3582 u32 Num1; /* Numerator for LO1 reg. value */
3583 u32 f_IF1; /* 1st IF requested */
3584 u32 LO2; /* 2nd LO register value */
3585 u32 Num2; /* Numerator for LO2 reg. value */
3586 u32 ofLO1, ofLO2; /* last time's LO frequencies */
3587 u32 ofin, ofout; /* last time's I/O frequencies */
3588 u8 fiffc = 0x80; /* FIFF center freq from tuner */
3589 u32 fiffof; /* Offset from FIFF center freq */
3590 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
3591 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
3592 u8 val;
3593 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003594
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003595 /* Check the input and output frequency ranges */
3596 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003597 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003598
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003599 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
3600 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003601 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003602
3603 /*
3604 ** Save original LO1 and LO2 register values
3605 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003606 ofLO1 = state->AS_Data.f_LO1;
3607 ofLO2 = state->AS_Data.f_LO2;
3608 ofin = state->AS_Data.f_in;
3609 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003610
3611 /*
3612 ** Find and set RF Band setting
3613 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003614 if (state->ctfilt_sw == 1) {
3615 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
3616 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003617 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003618 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003619 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003620 val = state->reg[MT2063_REG_CTUNE_OV];
3621 RFBand = FindClearTuneFilter(state, f_in);
3622 state->reg[MT2063_REG_CTUNE_OV] =
3623 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003624 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003625 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003626 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003627 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003628 }
3629 }
3630
3631 /*
3632 ** Read the FIFF Center Frequency from the tuner
3633 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003634 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003635 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003636 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003637 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003638 &state->reg[MT2063_REG_FIFFC], 1);
3639 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003640 }
3641 /*
3642 ** Assign in the requested values
3643 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003644 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003645 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003646 state->AS_Data.f_if1_Request =
3647 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
3648 state->AS_Data.f_LO1_Step,
3649 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003650
3651 /*
3652 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
3653 ** desired LO1 frequency
3654 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003655 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003656
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003657 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003658
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003659 state->AS_Data.f_LO1 =
3660 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
3661 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003662
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003663 state->AS_Data.f_LO2 =
3664 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3665 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003666
3667 /*
3668 ** Check for any LO spurs in the output bandwidth and adjust
3669 ** the LO settings to avoid them if needed
3670 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003671 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003672 /*
3673 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
3674 ** Recalculate the LO frequencies and the values to be placed
3675 ** in the tuning registers.
3676 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003677 state->AS_Data.f_LO1 =
3678 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
3679 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
3680 state->AS_Data.f_LO2 =
3681 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3682 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
3683 state->AS_Data.f_LO2 =
3684 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
3685 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003686
3687 /*
3688 ** Check the upconverter and downconverter frequency ranges
3689 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003690 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
3691 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003692 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003693 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
3694 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003695 status |= MT2063_DNC_RANGE;
3696 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003697 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003698 LO2LK = 0x40;
3699
3700 /*
3701 ** If we have the same LO frequencies and we're already locked,
3702 ** then skip re-programming the LO registers.
3703 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003704 if ((ofLO1 != state->AS_Data.f_LO1)
3705 || (ofLO2 != state->AS_Data.f_LO2)
3706 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003707 (LO1LK | LO2LK))) {
3708 /*
3709 ** Calculate the FIFFOF register value
3710 **
3711 ** IF1_Actual
3712 ** FIFFOF = ------------ - 8 * FIFFC - 4992
3713 ** f_ref/64
3714 */
3715 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003716 (state->AS_Data.f_LO1 -
3717 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003718 4992;
3719 if (fiffof > 0xFF)
3720 fiffof = 0xFF;
3721
3722 /*
3723 ** Place all of the calculated values into the local tuner
3724 ** register fields.
3725 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003726 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003727 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
3728 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
3729 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003730 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003731 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
3732 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003733
3734 /*
3735 ** Now write out the computed register values
3736 ** IMPORTANT: There is a required order for writing
3737 ** (0x05 must follow all the others).
3738 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003739 status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003740 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003741 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003742 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003743 }
3744 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003745 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003746 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003747 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003748 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003749 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003750 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003751 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003752 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003753 reg[MT2063_REG_FIFF_OFFSET],
3754 1);
3755 }
3756 }
3757
3758 /*
3759 ** Check for LO's locking
3760 */
3761
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003762 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003763 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003764 }
3765 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003766 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003767 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003768 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003769 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003770 }
3771 }
3772
3773 return (status);
3774}
3775
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003776static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003777 enum MTTune_atv_standard tv_type)
3778{
3779
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003780 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003781
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003782 s32 pict_car = 0;
3783 s32 pict2chanb_vsb = 0;
3784 s32 pict2chanb_snd = 0;
3785 s32 pict2snd1 = 0;
3786 s32 pict2snd2 = 0;
3787 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003788
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003789 s32 if_mid = 0;
3790 s32 rcvr_mode = 0;
3791 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003792
3793 switch (tv_type) {
3794 case MTTUNEA_PAL_B:{
3795 pict_car = 38900000;
3796 ch_bw = 8000000;
3797 pict2chanb_vsb = -1250000;
3798 pict2snd1 = 5500000;
3799 pict2snd2 = 5742000;
3800 rcvr_mode = 1;
3801 break;
3802 }
3803 case MTTUNEA_PAL_G:{
3804 pict_car = 38900000;
3805 ch_bw = 7000000;
3806 pict2chanb_vsb = -1250000;
3807 pict2snd1 = 5500000;
3808 pict2snd2 = 0;
3809 rcvr_mode = 1;
3810 break;
3811 }
3812 case MTTUNEA_PAL_I:{
3813 pict_car = 38900000;
3814 ch_bw = 8000000;
3815 pict2chanb_vsb = -1250000;
3816 pict2snd1 = 6000000;
3817 pict2snd2 = 0;
3818 rcvr_mode = 1;
3819 break;
3820 }
3821 case MTTUNEA_PAL_L:{
3822 pict_car = 38900000;
3823 ch_bw = 8000000;
3824 pict2chanb_vsb = -1250000;
3825 pict2snd1 = 6500000;
3826 pict2snd2 = 0;
3827 rcvr_mode = 1;
3828 break;
3829 }
3830 case MTTUNEA_PAL_MN:{
3831 pict_car = 38900000;
3832 ch_bw = 6000000;
3833 pict2chanb_vsb = -1250000;
3834 pict2snd1 = 4500000;
3835 pict2snd2 = 0;
3836 rcvr_mode = 1;
3837 break;
3838 }
3839 case MTTUNEA_PAL_DK:{
3840 pict_car = 38900000;
3841 ch_bw = 8000000;
3842 pict2chanb_vsb = -1250000;
3843 pict2snd1 = 6500000;
3844 pict2snd2 = 0;
3845 rcvr_mode = 1;
3846 break;
3847 }
3848 case MTTUNEA_DIGITAL:{
3849 pict_car = 36125000;
3850 ch_bw = 8000000;
3851 pict2chanb_vsb = -(ch_bw / 2);
3852 pict2snd1 = 0;
3853 pict2snd2 = 0;
3854 rcvr_mode = 2;
3855 break;
3856 }
3857 case MTTUNEA_FMRADIO:{
3858 pict_car = 38900000;
3859 ch_bw = 8000000;
3860 pict2chanb_vsb = -(ch_bw / 2);
3861 pict2snd1 = 0;
3862 pict2snd2 = 0;
3863 rcvr_mode = 4;
3864 //f_in -= 2900000;
3865 break;
3866 }
3867 case MTTUNEA_DVBC:{
3868 pict_car = 36125000;
3869 ch_bw = 8000000;
3870 pict2chanb_vsb = -(ch_bw / 2);
3871 pict2snd1 = 0;
3872 pict2snd2 = 0;
3873 rcvr_mode = MT2063_CABLE_QAM;
3874 break;
3875 }
3876 case MTTUNEA_DVBT:{
3877 pict_car = 36125000;
3878 ch_bw = bw_in; //8000000
3879 pict2chanb_vsb = -(ch_bw / 2);
3880 pict2snd1 = 0;
3881 pict2snd2 = 0;
3882 rcvr_mode = MT2063_OFFAIR_COFDM;
3883 break;
3884 }
3885 case MTTUNEA_UNKNOWN:
3886 break;
3887 default:
3888 break;
3889 }
3890
3891 pict2chanb_snd = pict2chanb_vsb - ch_bw;
3892 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
3893
3894 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
3895 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
3896 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
3897 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3898
3899 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
3900 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
3901 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3902
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003903 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003904}
3905
3906static int mt2063_init(struct dvb_frontend *fe)
3907{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003908 u32 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003909 struct mt2063_state *state = fe->tuner_priv;
3910
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003911 status = MT2063_Open(fe);
3912 status |= MT2063_SoftwareShutdown(state, 1);
3913 status |= MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003914
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003915 if (0 != status) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003916 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
3917 status);
3918 return -1;
3919 }
3920
3921 return 0;
3922}
3923
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003924static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3925{
3926 int rc = 0;
3927
3928 //get tuner lock status
3929
3930 return rc;
3931}
3932
3933static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003934 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003935{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003936 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003937
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003938 switch (param) {
3939 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003940 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003941 break;
3942 case DVBFE_TUNER_TUNERSTEP:
3943 break;
3944 case DVBFE_TUNER_IFFREQ:
3945 break;
3946 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003947 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003948 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003949 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003950 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003951 break;
3952 default:
3953 break;
3954 }
3955
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003956 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003957}
3958
3959static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003960 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003961{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003962 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003963 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003964
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003965 switch (param) {
3966 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003967 //set frequency
3968
3969 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003970 MT_Tune_atv(state,
3971 tunstate->frequency, tunstate->bandwidth,
3972 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003973
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003974 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003975 break;
3976 case DVBFE_TUNER_TUNERSTEP:
3977 break;
3978 case DVBFE_TUNER_IFFREQ:
3979 break;
3980 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003981 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003982 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003983 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003984 case DVBFE_TUNER_REFCLOCK:
3985
3986 break;
3987 case DVBFE_TUNER_OPEN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003988 status = MT2063_Open(fe);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003989 break;
3990 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003991 status = MT2063_SoftwareShutdown(state, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003992 break;
3993 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
3994 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003995 MT2063_ClearPowerMaskBits(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003996 MT2063_ALL_SD);
3997 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003998 default:
3999 break;
4000 }
4001
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004002 return (int)status;
4003}
4004
4005static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004006{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004007 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004008
4009 fe->tuner_priv = NULL;
4010 kfree(state);
4011
4012 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004013}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004014
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004015static struct dvb_tuner_ops mt2063_ops = {
4016 .info = {
4017 .name = "MT2063 Silicon Tuner",
4018 .frequency_min = 45000000,
4019 .frequency_max = 850000000,
4020 .frequency_step = 0,
4021 },
4022
4023 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03004024 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004025 .get_status = mt2063_get_status,
4026 .get_state = mt2063_get_state,
4027 .set_state = mt2063_set_state,
4028 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004029};
4030
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004031struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4032 struct mt2063_config *config,
4033 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004034{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004035 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004036
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004037 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004038 if (state == NULL)
4039 goto error;
4040
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004041 state->config = config;
4042 state->i2c = i2c;
4043 state->frontend = fe;
4044 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004045 state->MT2063_init = false;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004046 fe->tuner_priv = state;
4047 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004048
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004049 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004050 return fe;
4051
4052error:
4053 kfree(state);
4054 return NULL;
4055}
4056
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004057EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004058MODULE_PARM_DESC(verbose, "Set Verbosity level");
4059
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004060MODULE_AUTHOR("Henry");
4061MODULE_DESCRIPTION("MT2063 Silicon tuner");
4062MODULE_LICENSE("GPL");