blob: c5e95ddd11f90cd5ad973bd2e4a873e5c718133a [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_SOFTWARE_SHUTDOWN 100
15#define DVBFE_TUNER_CLEAR_POWER_MASKBITS 101
16
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030017/* FIXME: Those two error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030018/* Error: Upconverter PLL is not locked */
19#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030020/* Error: Downconverter PLL is not locked */
21#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030022
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030023/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030024#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030025
26/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
27#define MT2063_SPUR_CNT_MASK (0x001f0000)
28#define MT2063_SPUR_SHIFT (16)
29
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030030/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
31#define MT2063_UPC_RANGE (0x04000000)
32
33/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
34#define MT2063_DNC_RANGE (0x08000000)
35
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030036/*
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030037 * Data Types
38 */
39
40/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030041 * Constant defining the version of the following structure
42 * and therefore the API for this code.
43 *
44 * When compiling the tuner driver, the preprocessor will
45 * check against this version number to make sure that
46 * it matches the version that the tuner driver knows about.
47 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030048
49/* DECT Frequency Avoidance */
50#define MT2063_DECT_AVOID_US_FREQS 0x00000001
51
52#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
53
54#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
55
56#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
57
58enum MT2063_DECT_Avoid_Type {
59 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
60 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
61 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
62 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
63};
64
65#define MT2063_MAX_ZONES 48
66
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030067struct MT2063_ExclZone_t {
68 u32 min_;
69 u32 max_;
70 struct MT2063_ExclZone_t *next_;
71};
72
73/*
74 * Structure of data needed for Spur Avoidance
75 */
76struct MT2063_AvoidSpursData_t {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030077 u32 f_ref;
78 u32 f_in;
79 u32 f_LO1;
80 u32 f_if1_Center;
81 u32 f_if1_Request;
82 u32 f_if1_bw;
83 u32 f_LO2;
84 u32 f_out;
85 u32 f_out_bw;
86 u32 f_LO1_Step;
87 u32 f_LO2_Step;
88 u32 f_LO1_FracN_Avoid;
89 u32 f_LO2_FracN_Avoid;
90 u32 f_zif_bw;
91 u32 f_min_LO_Separation;
92 u32 maxH1;
93 u32 maxH2;
94 enum MT2063_DECT_Avoid_Type avoidDECT;
95 u32 bSpurPresent;
96 u32 bSpurAvoided;
97 u32 nSpursFound;
98 u32 nZones;
99 struct MT2063_ExclZone_t *freeZones;
100 struct MT2063_ExclZone_t *usedZones;
101 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
102};
103
104/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300105 * Parameter for function MT2063_SetPowerMask that specifies the power down
106 * of various sections of the MT2063.
107 */
108enum MT2063_Mask_Bits {
109 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
110 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
111 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
112 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
113 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
114 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
115 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
116 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
117 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
118 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
119 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
120 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
121 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
122 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
123 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
124};
125
126/*
127 * Parameter for function MT2063_GetParam & MT2063_SetParam that
128 * specifies the tuning algorithm parameter to be read/written.
129 */
130enum MT2063_Param {
131 /* tuner address set by MT2063_Open() */
132 MT2063_IC_ADDR,
133
134 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
135 MT2063_MAX_OPEN,
136
137 /* current number of open MT2063 tuners set by MT2063_Open() */
138 MT2063_NUM_OPEN,
139
140 /* crystal frequency (default: 16000000 Hz) */
141 MT2063_SRO_FREQ,
142
143 /* min tuning step size (default: 50000 Hz) */
144 MT2063_STEPSIZE,
145
146 /* input center frequency set by MT2063_Tune() */
147 MT2063_INPUT_FREQ,
148
149 /* LO1 Frequency set by MT2063_Tune() */
150 MT2063_LO1_FREQ,
151
152 /* LO1 minimum step size (default: 250000 Hz) */
153 MT2063_LO1_STEPSIZE,
154
155 /* LO1 FracN keep-out region (default: 999999 Hz) */
156 MT2063_LO1_FRACN_AVOID_PARAM,
157
158 /* Current 1st IF in use set by MT2063_Tune() */
159 MT2063_IF1_ACTUAL,
160
161 /* Requested 1st IF set by MT2063_Tune() */
162 MT2063_IF1_REQUEST,
163
164 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
165 MT2063_IF1_CENTER,
166
167 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
168 MT2063_IF1_BW,
169
170 /* zero-IF bandwidth (default: 2000000 Hz) */
171 MT2063_ZIF_BW,
172
173 /* LO2 Frequency set by MT2063_Tune() */
174 MT2063_LO2_FREQ,
175
176 /* LO2 minimum step size (default: 50000 Hz) */
177 MT2063_LO2_STEPSIZE,
178
179 /* LO2 FracN keep-out region (default: 374999 Hz) */
180 MT2063_LO2_FRACN_AVOID,
181
182 /* output center frequency set by MT2063_Tune() */
183 MT2063_OUTPUT_FREQ,
184
185 /* output bandwidth set by MT2063_Tune() */
186 MT2063_OUTPUT_BW,
187
188 /* min inter-tuner LO separation (default: 1000000 Hz) */
189 MT2063_LO_SEPARATION,
190
191 /* ID of avoid-spurs algorithm in use compile-time constant */
192 MT2063_AS_ALG,
193
194 /* max # of intra-tuner harmonics (default: 15) */
195 MT2063_MAX_HARM1,
196
197 /* max # of inter-tuner harmonics (default: 7) */
198 MT2063_MAX_HARM2,
199
200 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
201 MT2063_EXCL_ZONES,
202
203 /* # of spurs found/avoided set by MT2063_Tune() */
204 MT2063_NUM_SPURS,
205
206 /* >0 spurs avoided set by MT2063_Tune() */
207 MT2063_SPUR_AVOIDED,
208
209 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
210 MT2063_SPUR_PRESENT,
211
212 /* Receiver Mode for some parameters. 1 is DVB-T */
213 MT2063_RCVR_MODE,
214
215 /* directly set LNA attenuation, parameter is value to set */
216 MT2063_ACLNA,
217
218 /* maximum LNA attenuation, parameter is value to set */
219 MT2063_ACLNA_MAX,
220
221 /* directly set ATN attenuation. Paremeter is value to set. */
222 MT2063_ACRF,
223
224 /* maxium ATN attenuation. Paremeter is value to set. */
225 MT2063_ACRF_MAX,
226
227 /* directly set FIF attenuation. Paremeter is value to set. */
228 MT2063_ACFIF,
229
230 /* maxium FIF attenuation. Paremeter is value to set. */
231 MT2063_ACFIF_MAX,
232
233 /* LNA Rin */
234 MT2063_LNA_RIN,
235
236 /* Power Detector LNA level target */
237 MT2063_LNA_TGT,
238
239 /* Power Detector 1 level */
240 MT2063_PD1,
241
242 /* Power Detector 1 level target */
243 MT2063_PD1_TGT,
244
245 /* Power Detector 2 level */
246 MT2063_PD2,
247
248 /* Power Detector 2 level target */
249 MT2063_PD2_TGT,
250
251 /* Selects, which DNC is activ */
252 MT2063_DNC_OUTPUT_ENABLE,
253
254 /* VGA gain code */
255 MT2063_VGAGC,
256
257 /* VGA bias current */
258 MT2063_VGAOI,
259
260 /* TAGC, determins the speed of the AGC */
261 MT2063_TAGC,
262
263 /* AMP gain code */
264 MT2063_AMPGC,
265
266 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
267 MT2063_AVOID_DECT,
268
269 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
270 MT2063_CTFILT_SW,
271
272 MT2063_EOP /* last entry in enumerated list */
273};
274
275/*
276 * Parameter for selecting tuner mode
277 */
278enum MT2063_RCVR_MODES {
279 MT2063_CABLE_QAM = 0, /* Digital cable */
280 MT2063_CABLE_ANALOG, /* Analog cable */
281 MT2063_OFFAIR_COFDM, /* Digital offair */
282 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
283 MT2063_OFFAIR_ANALOG, /* Analog offair */
284 MT2063_OFFAIR_8VSB, /* Analog offair */
285 MT2063_NUM_RCVR_MODES
286};
287
288/*
289 * Possible values for MT2063_DNC_OUTPUT
290 */
291enum MT2063_DNC_Output_Enable {
292 MT2063_DNC_NONE = 0,
293 MT2063_DNC_1,
294 MT2063_DNC_2,
295 MT2063_DNC_BOTH
296};
297
298/*
299** Two-wire serial bus subaddresses of the tuner registers.
300** Also known as the tuner's register addresses.
301*/
302enum MT2063_Register_Offsets {
303 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
304 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
305 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
306 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
307 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
308 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
309 MT2063_REG_RSVD_06, /* 0x06: Reserved */
310 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
311 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
312 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
313 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
314 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
315 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
316 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
317 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
318 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
319 MT2063_REG_RSVD_10, /* 0x10: Reserved */
320 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
321 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
322 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
323 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
324 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
325 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
326 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
327 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
328 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
329 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
330 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
331 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
332 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
333 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
334 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
335 MT2063_REG_RSVD_20, /* 0x20: Reserved */
336 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
337 MT2063_REG_RSVD_22, /* 0x22: Reserved */
338 MT2063_REG_RSVD_23, /* 0x23: Reserved */
339 MT2063_REG_RSVD_24, /* 0x24: Reserved */
340 MT2063_REG_RSVD_25, /* 0x25: Reserved */
341 MT2063_REG_RSVD_26, /* 0x26: Reserved */
342 MT2063_REG_RSVD_27, /* 0x27: Reserved */
343 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
344 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
345 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
346 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
347 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
348 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
349 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
350 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
351 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
352 MT2063_REG_RSVD_31, /* 0x31: Reserved */
353 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
354 MT2063_REG_RSVD_33, /* 0x33: Reserved */
355 MT2063_REG_RSVD_34, /* 0x34: Reserved */
356 MT2063_REG_RSVD_35, /* 0x35: Reserved */
357 MT2063_REG_RSVD_36, /* 0x36: Reserved */
358 MT2063_REG_RSVD_37, /* 0x37: Reserved */
359 MT2063_REG_RSVD_38, /* 0x38: Reserved */
360 MT2063_REG_RSVD_39, /* 0x39: Reserved */
361 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
362 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
363 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
364 MT2063_REG_END_REGS
365};
366
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300367enum MTTune_atv_standard {
368 MTTUNEA_UNKNOWN = 0,
369 MTTUNEA_PAL_B,
370 MTTUNEA_PAL_G,
371 MTTUNEA_PAL_I,
372 MTTUNEA_PAL_L,
373 MTTUNEA_PAL_MN,
374 MTTUNEA_PAL_DK,
375 MTTUNEA_DIGITAL,
376 MTTUNEA_FMRADIO,
377 MTTUNEA_DVBC,
378 MTTUNEA_DVBT
379};
380
381
382struct mt2063_state {
383 struct i2c_adapter *i2c;
384
385 const struct mt2063_config *config;
386 struct dvb_tuner_ops ops;
387 struct dvb_frontend *frontend;
388 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300389
390 enum MTTune_atv_standard tv_type;
391 u32 frequency;
392 u32 srate;
393 u32 bandwidth;
394 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300395
396 u32 tuner_id;
397 struct MT2063_AvoidSpursData_t AS_Data;
398 u32 f_IF1_actual;
399 u32 rcvr_mode;
400 u32 ctfilt_sw;
401 u32 CTFiltMax[31];
402 u32 num_regs;
403 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300404};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300405
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300406/* Prototypes */
407static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
408 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300409static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
410static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
411static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
412static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300413 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300414
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300415/*****************/
416/* From drivers/media/common/tuners/mt2063_cfg.h */
417
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300418unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300419 u32 bw_in,
420 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300421{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300422 struct dvb_frontend_ops *frontend_ops = NULL;
423 struct dvb_tuner_ops *tuner_ops = NULL;
424 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300425 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300426 int err = 0;
427
428 t_state.frequency = f_in;
429 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300430 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300431 if (&fe->ops)
432 frontend_ops = &fe->ops;
433 if (&frontend_ops->tuner_ops)
434 tuner_ops = &frontend_ops->tuner_ops;
435 if (tuner_ops->set_state) {
436 if ((err =
437 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
438 &t_state)) < 0) {
439 printk("%s: Invalid parameter\n", __func__);
440 return err;
441 }
442 }
443
444 return err;
445}
446
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300447unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300448{
449 struct dvb_frontend_ops *frontend_ops = &fe->ops;
450 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
451 struct tuner_state t_state;
452 int err = 0;
453
454 if (&fe->ops)
455 frontend_ops = &fe->ops;
456 if (&frontend_ops->tuner_ops)
457 tuner_ops = &frontend_ops->tuner_ops;
458 if (tuner_ops->get_state) {
459 if ((err =
460 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
461 &t_state)) < 0) {
462 printk("%s: Invalid parameter\n", __func__);
463 return err;
464 }
465 }
466 return err;
467}
468
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300469unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300470{
471 struct dvb_frontend_ops *frontend_ops = &fe->ops;
472 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
473 struct tuner_state t_state;
474 int err = 0;
475
476 if (&fe->ops)
477 frontend_ops = &fe->ops;
478 if (&frontend_ops->tuner_ops)
479 tuner_ops = &frontend_ops->tuner_ops;
480 if (tuner_ops->set_state) {
481 if ((err =
482 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
483 &t_state)) < 0) {
484 printk("%s: Invalid parameter\n", __func__);
485 return err;
486 }
487 }
488
489 return err;
490}
491
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300492unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300493{
494 struct dvb_frontend_ops *frontend_ops = &fe->ops;
495 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
496 struct tuner_state t_state;
497 int err = 0;
498
499 if (&fe->ops)
500 frontend_ops = &fe->ops;
501 if (&frontend_ops->tuner_ops)
502 tuner_ops = &frontend_ops->tuner_ops;
503 if (tuner_ops->set_state) {
504 if ((err =
505 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
506 &t_state)) < 0) {
507 printk("%s: Invalid parameter\n", __func__);
508 return err;
509 }
510 }
511
512 return err;
513}
514
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300515unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300516{
517 struct dvb_frontend_ops *frontend_ops = &fe->ops;
518 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
519 struct tuner_state t_state;
520 int err = 0;
521
522 if (&fe->ops)
523 frontend_ops = &fe->ops;
524 if (&frontend_ops->tuner_ops)
525 tuner_ops = &frontend_ops->tuner_ops;
526 if (tuner_ops->set_state) {
527 if ((err =
528 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
529 &t_state)) < 0) {
530 printk("%s: Invalid parameter\n", __func__);
531 return err;
532 }
533 }
534
535 return err;
536}
537
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300538/*
539 * mt2063_write - Write data into the I2C bus
540 */
541static u32 mt2063_write(struct mt2063_state *state,
542 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300543{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300544 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300545 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300546 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300547 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300548 .addr = state->config->tuner_address,
549 .flags = 0,
550 .buf = buf,
551 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300552 };
553
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300554 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300555 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300556
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300557 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300558 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300559 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300560
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300561 if (ret < 0)
562 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300563
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300564 return ret;
565}
566
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300567/*
568 * mt2063_read - Read data from the I2C bus
569 */
570static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300571 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300572{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300573 u32 status = 0; /* Status to be returned */
574 struct dvb_frontend *fe = state->frontend;
575 u32 i = 0;
576
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300577 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300578
579 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300580 int ret;
581 u8 b0[] = { subAddress + i };
582 struct i2c_msg msg[] = {
583 {
584 .addr = state->config->tuner_address,
585 .flags = I2C_M_RD,
586 .buf = b0,
587 .len = 1
588 }, {
589 .addr = state->config->tuner_address,
590 .flags = I2C_M_RD,
591 .buf = pData + 1,
592 .len = 1
593 }
594 };
595
596 ret = i2c_transfer(state->i2c, msg, 2);
597 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300598 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300599 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300600 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300601 return (status);
602}
603
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300604/*
605 * FIXME: Is this really needed?
606 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300607static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300608{
609 /*
610 ** ToDo: Add code here to implement a OS blocking
611 ** for a period of "nMinDelayTime" milliseconds.
612 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300613 msleep(10);
614
615 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300616}
617
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300618/*
619 * Microtune spur avoidance
620 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300621
622/* Implement ceiling, floor functions. */
623#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300624#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300625
626struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300627 s32 min_;
628 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300629};
630
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300631/*
632** Reset all exclusion zones.
633** Add zones to protect the PLL FracN regions near zero
634**
635** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
636** frequencies into MT_ResetExclZones().
637*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300638static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300639{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300640 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300641
642 pAS_Info->nZones = 0; /* this clears the used list */
643 pAS_Info->usedZones = NULL; /* reset ptr */
644 pAS_Info->freeZones = NULL; /* reset ptr */
645
646 center =
647 pAS_Info->f_ref *
648 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
649 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
650 while (center <
651 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
652 pAS_Info->f_LO1_FracN_Avoid) {
653 /* Exclude LO1 FracN */
654 MT2063_AddExclZone(pAS_Info,
655 center - pAS_Info->f_LO1_FracN_Avoid,
656 center - 1);
657 MT2063_AddExclZone(pAS_Info, center + 1,
658 center + pAS_Info->f_LO1_FracN_Avoid);
659 center += pAS_Info->f_ref;
660 }
661
662 center =
663 pAS_Info->f_ref *
664 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
665 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
666 while (center <
667 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
668 pAS_Info->f_LO2_FracN_Avoid) {
669 /* Exclude LO2 FracN */
670 MT2063_AddExclZone(pAS_Info,
671 center - pAS_Info->f_LO2_FracN_Avoid,
672 center - 1);
673 MT2063_AddExclZone(pAS_Info, center + 1,
674 center + pAS_Info->f_LO2_FracN_Avoid);
675 center += pAS_Info->f_ref;
676 }
677
678 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
679 /* Exclude LO1 values that conflict with DECT channels */
680 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
681 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
682 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
683 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
684 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
685 }
686
687 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
688 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
689 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
690 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
691 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
692 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
693 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
694 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
695 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
696 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
697 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
698 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300699}
700
701static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
702 *pAS_Info,
703 struct MT2063_ExclZone_t *pPrevNode)
704{
705 struct MT2063_ExclZone_t *pNode;
706 /* Check for a node in the free list */
707 if (pAS_Info->freeZones != NULL) {
708 /* Use one from the free list */
709 pNode = pAS_Info->freeZones;
710 pAS_Info->freeZones = pNode->next_;
711 } else {
712 /* Grab a node from the array */
713 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
714 }
715
716 if (pPrevNode != NULL) {
717 pNode->next_ = pPrevNode->next_;
718 pPrevNode->next_ = pNode;
719 } else { /* insert at the beginning of the list */
720
721 pNode->next_ = pAS_Info->usedZones;
722 pAS_Info->usedZones = pNode;
723 }
724
725 pAS_Info->nZones++;
726 return pNode;
727}
728
729static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
730 *pAS_Info,
731 struct MT2063_ExclZone_t *pPrevNode,
732 struct MT2063_ExclZone_t
733 *pNodeToRemove)
734{
735 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
736
737 /* Make previous node point to the subsequent node */
738 if (pPrevNode != NULL)
739 pPrevNode->next_ = pNext;
740
741 /* Add pNodeToRemove to the beginning of the freeZones */
742 pNodeToRemove->next_ = pAS_Info->freeZones;
743 pAS_Info->freeZones = pNodeToRemove;
744
745 /* Decrement node count */
746 pAS_Info->nZones--;
747
748 return pNext;
749}
750
751/*****************************************************************************
752**
753** Name: MT_AddExclZone
754**
755** Description: Add (and merge) an exclusion zone into the list.
756** If the range (f_min, f_max) is totally outside the
757** 1st IF BW, ignore the entry.
758** If the range (f_min, f_max) is negative, ignore the entry.
759**
760** Revision History:
761**
762** SCR Date Author Description
763** -------------------------------------------------------------------------
764** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
765** (f_min, f_max) < 0, ignore the entry.
766**
767*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300768static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300769 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300770{
771 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
772 struct MT2063_ExclZone_t *pPrev = NULL;
773 struct MT2063_ExclZone_t *pNext = NULL;
774
775 /* Check to see if this overlaps the 1st IF filter */
776 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
777 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
778 && (f_min < f_max)) {
779 /*
780 ** 1 2 3 4 5 6
781 **
782 ** New entry: |---| |--| |--| |-| |---| |--|
783 ** or or or or or
784 ** Existing: |--| |--| |--| |---| |-| |--|
785 */
786
787 /* Check for our place in the list */
788 while ((pNode != NULL) && (pNode->max_ < f_min)) {
789 pPrev = pNode;
790 pNode = pNode->next_;
791 }
792
793 if ((pNode != NULL) && (pNode->min_ < f_max)) {
794 /* Combine me with pNode */
795 if (f_min < pNode->min_)
796 pNode->min_ = f_min;
797 if (f_max > pNode->max_)
798 pNode->max_ = f_max;
799 } else {
800 pNode = InsertNode(pAS_Info, pPrev);
801 pNode->min_ = f_min;
802 pNode->max_ = f_max;
803 }
804
805 /* Look for merging possibilities */
806 pNext = pNode->next_;
807 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
808 if (pNext->max_ > pNode->max_)
809 pNode->max_ = pNext->max_;
810 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
811 }
812 }
813}
814
815/*****************************************************************************
816**
817** Name: MT_ChooseFirstIF
818**
819** Description: Choose the best available 1st IF
820** If f_Desired is not excluded, choose that first.
821** Otherwise, return the value closest to f_Center that is
822** not excluded
823**
824** Revision History:
825**
826** SCR Date Author Description
827** -------------------------------------------------------------------------
828** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
829** tuner DLL.
830** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
831** Added logic to force f_Center within 1/2 f_Step.
832**
833*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300834static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300835{
836 /*
837 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
838 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
839 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
840 ** However, the sum must be.
841 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300842 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300843 pAS_Info->f_LO1_Step *
844 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
845 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
846 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300847 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300848 (pAS_Info->f_LO1_Step >
849 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
850 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300851 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300852
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300853 s32 i;
854 s32 j = 0;
855 u32 bDesiredExcluded = 0;
856 u32 bZeroExcluded = 0;
857 s32 tmpMin, tmpMax;
858 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300859 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
860 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
861
862 if (pAS_Info->nZones == 0)
863 return f_Desired;
864
865 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
866 if (pAS_Info->f_if1_Center > f_Desired)
867 f_Center =
868 f_Desired +
869 f_Step *
870 ((pAS_Info->f_if1_Center - f_Desired +
871 f_Step / 2) / f_Step);
872 else
873 f_Center =
874 f_Desired -
875 f_Step *
876 ((f_Desired - pAS_Info->f_if1_Center +
877 f_Step / 2) / f_Step);
878
879 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300880 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300881 // return 0;
882
883 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
884 while (pNode != NULL) {
885 /* floor function */
886 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300887 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300888
889 /* ceil function */
890 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300891 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300892
893 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
894 bDesiredExcluded = 1;
895
896 if ((tmpMin < 0) && (tmpMax > 0))
897 bZeroExcluded = 1;
898
899 /* See if this zone overlaps the previous */
900 if ((j > 0) && (tmpMin < zones[j - 1].max_))
901 zones[j - 1].max_ = tmpMax;
902 else {
903 /* Add new zone */
904 //assert(j<MT2063_MAX_ZONES);
905 //if (j>=MT2063_MAX_ZONES)
906 //break;
907
908 zones[j].min_ = tmpMin;
909 zones[j].max_ = tmpMax;
910 j++;
911 }
912 pNode = pNode->next_;
913 }
914
915 /*
916 ** If the desired is okay, return with it
917 */
918 if (bDesiredExcluded == 0)
919 return f_Desired;
920
921 /*
922 ** If the desired is excluded and the center is okay, return with it
923 */
924 if (bZeroExcluded == 0)
925 return f_Center;
926
927 /* Find the value closest to 0 (f_Center) */
928 bestDiff = zones[0].min_;
929 for (i = 0; i < j; i++) {
930 if (abs(zones[i].min_) < abs(bestDiff))
931 bestDiff = zones[i].min_;
932 if (abs(zones[i].max_) < abs(bestDiff))
933 bestDiff = zones[i].max_;
934 }
935
936 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300937 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300938
939 return f_Center + (bestDiff * f_Step);
940}
941
942/****************************************************************************
943**
944** Name: gcd
945**
946** Description: Uses Euclid's algorithm
947**
948** Parameters: u, v - unsigned values whose GCD is desired.
949**
950** Global: None
951**
952** Returns: greatest common divisor of u and v, if either value
953** is 0, the other value is returned as the result.
954**
955** Dependencies: None.
956**
957** Revision History:
958**
959** SCR Date Author Description
960** -------------------------------------------------------------------------
961** N/A 06-01-2004 JWS Original
962** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
963** unsigned numbers.
964**
965****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300966static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300967{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300968 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300969
970 while (v != 0) {
971 r = u % v;
972 u = v;
973 v = r;
974 }
975
976 return u;
977}
978
979/****************************************************************************
980**
981** Name: umax
982**
983** Description: Implements a simple maximum function for unsigned numbers.
984** Implemented as a function rather than a macro to avoid
985** multiple evaluation of the calling parameters.
986**
987** Parameters: a, b - Values to be compared
988**
989** Global: None
990**
991** Returns: larger of the input values.
992**
993** Dependencies: None.
994**
995** Revision History:
996**
997** SCR Date Author Description
998** -------------------------------------------------------------------------
999** N/A 06-02-2004 JWS Original
1000**
1001****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001002static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001003{
1004 return (a >= b) ? a : b;
1005}
1006
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001007/****************************************************************************
1008**
1009** Name: IsSpurInBand
1010**
1011** Description: Checks to see if a spur will be present within the IF's
1012** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1013**
1014** ma mb mc md
1015** <--+-+-+-------------------+-------------------+-+-+-->
1016** | ^ 0 ^ |
1017** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1018** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1019**
1020** Note that some equations are doubled to prevent round-off
1021** problems when calculating fIFBW/2
1022**
1023** Parameters: pAS_Info - Avoid Spurs information block
1024** fm - If spur, amount f_IF1 has to move negative
1025** fp - If spur, amount f_IF1 has to move positive
1026**
1027** Global: None
1028**
1029** Returns: 1 if an LO spur would be present, otherwise 0.
1030**
1031** Dependencies: None.
1032**
1033** Revision History:
1034**
1035** SCR Date Author Description
1036** -------------------------------------------------------------------------
1037** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1038**
1039****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001040static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1041 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001042{
1043 /*
1044 ** Calculate LO frequency settings.
1045 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001046 u32 n, n0;
1047 const u32 f_LO1 = pAS_Info->f_LO1;
1048 const u32 f_LO2 = pAS_Info->f_LO2;
1049 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1050 const u32 c = d - pAS_Info->f_out_bw;
1051 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -03001052 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001053 s32 f_nsLO1, f_nsLO2;
1054 s32 f_Spur;
1055 u32 ma, mb, mc, md, me, mf;
1056 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001057 *fm = 0;
1058
1059 /*
1060 ** For each edge (d, c & f), calculate a scale, based on the gcd
1061 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1062 ** gcd-based scale factor or f_Scale.
1063 */
1064 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001065 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001066 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001067 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001068 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001069 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001070 hgfs = gf_Scale / 2;
1071
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001072 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001073
1074 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1075 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1076 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1077 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1078
1079 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1080 if (md >= pAS_Info->maxH1)
1081 break;
1082
1083 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1084 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1085
1086 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1087 if (md == ma)
1088 continue;
1089
1090 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1091 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1092 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001093 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1094 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001095 f_Spur =
1096 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1097 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1098
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001099 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1100 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001101 return 1;
1102 }
1103
1104 /* Location of Zero-IF-spur to be checked */
1105 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1106 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1107 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1108 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1109 if (me != mf) {
1110 f_nsLO1 = n * (f_LO1 / gf_Scale);
1111 f_nsLO2 = me * (f_LO2 / gf_Scale);
1112 f_Spur =
1113 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1114 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1115
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001116 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1117 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001118 return 1;
1119 }
1120
1121 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1122 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1123 if (ma != mb) {
1124 f_nsLO1 = n * (f_LO1 / gc_Scale);
1125 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1126 f_Spur =
1127 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1128 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1129
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001130 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1131 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001132 return 1;
1133 }
1134 }
1135
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001136 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001137 return 0;
1138}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001139
1140/*****************************************************************************
1141**
1142** Name: MT_AvoidSpurs
1143**
1144** Description: Main entry point to avoid spurs.
1145** Checks for existing spurs in present LO1, LO2 freqs
1146** and if present, chooses spur-free LO1, LO2 combination
1147** that tunes the same input/output frequencies.
1148**
1149** Revision History:
1150**
1151** SCR Date Author Description
1152** -------------------------------------------------------------------------
1153** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1154**
1155*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001156static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001157{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001158 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001159 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001160 pAS_Info->bSpurAvoided = 0;
1161 pAS_Info->nSpursFound = 0;
1162
1163 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001164 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001165
1166 /*
1167 ** Avoid LO Generated Spurs
1168 **
1169 ** Make sure that have no LO-related spurs within the IF output
1170 ** bandwidth.
1171 **
1172 ** If there is an LO spur in this band, start at the current IF1 frequency
1173 ** and work out until we find a spur-free frequency or run up against the
1174 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1175 ** will be unchanged if a spur-free setting is not found.
1176 */
1177 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1178 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001179 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1180 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1181 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1182 u32 delta_IF1;
1183 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001184
1185 /*
1186 ** Spur was found, attempt to find a spur-free 1st IF
1187 */
1188 do {
1189 pAS_Info->nSpursFound++;
1190
1191 /* Raise f_IF1_upper, if needed */
1192 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1193
1194 /* Choose next IF1 that is closest to f_IF1_CENTER */
1195 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1196
1197 if (new_IF1 > zfIF1) {
1198 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1199 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1200 } else {
1201 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1202 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1203 }
1204 zfIF1 = new_IF1;
1205
1206 if (zfIF1 > pAS_Info->f_if1_Center)
1207 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1208 else
1209 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1210 }
1211 /*
1212 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1213 ** and there is a spur in the band (again)
1214 */
1215 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1216 pAS_Info->f_if1_bw)
1217 && (pAS_Info->bSpurPresent =
1218 IsSpurInBand(pAS_Info, &fm, &fp)));
1219
1220 /*
1221 ** Use the LO-spur free values found. If the search went all the way to
1222 ** the 1st IF band edge and always found spurs, just leave the original
1223 ** choice. It's as "good" as any other.
1224 */
1225 if (pAS_Info->bSpurPresent == 1) {
1226 status |= MT2063_SPUR_PRESENT_ERR;
1227 pAS_Info->f_LO1 = zfLO1;
1228 pAS_Info->f_LO2 = zfLO2;
1229 } else
1230 pAS_Info->bSpurAvoided = 1;
1231 }
1232
1233 status |=
1234 ((pAS_Info->
1235 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1236
1237 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001238}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001239
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001240//end of mt2063_spuravoid.c
1241//=================================================================
1242//#################################################################
1243//=================================================================
1244
1245/*
1246** The expected version of MT_AvoidSpursData_t
1247** If the version is different, an updated file is needed from Microtune
1248*/
1249/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001250
1251typedef enum {
1252 MT2063_SET_ATTEN,
1253 MT2063_INCR_ATTEN,
1254 MT2063_DECR_ATTEN
1255} MT2063_ATTEN_CNTL_MODE;
1256
1257//#define TUNER_MT2063_OPTIMIZATION
1258/*
1259** Constants used by the tuning algorithm
1260*/
1261#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1262#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1263#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1264#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1265#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1266#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1267#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1268#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1269#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1270#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1271#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1272#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1273#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1274#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1275#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1276#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1277#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1278#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1279
1280/*
1281** Define the supported Part/Rev codes for the MT2063
1282*/
1283#define MT2063_B0 (0x9B)
1284#define MT2063_B1 (0x9C)
1285#define MT2063_B2 (0x9D)
1286#define MT2063_B3 (0x9E)
1287
1288/*
1289** The number of Tuner Registers
1290*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001291static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001292
1293#define USE_GLOBAL_TUNER 0
1294
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001295static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001296static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001297
1298/*
1299** Constants for setting receiver modes.
1300** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1301** (DNC1GC & DNC2GC are the values, which are used, when the specific
1302** DNC Output is selected, the other is always off)
1303**
1304** If PAL-L or L' is received, set:
1305** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1306**
1307** --------------+----------------------------------------------
1308** Mode 0 : | MT2063_CABLE_QAM
1309** Mode 1 : | MT2063_CABLE_ANALOG
1310** Mode 2 : | MT2063_OFFAIR_COFDM
1311** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1312** Mode 4 : | MT2063_OFFAIR_ANALOG
1313** Mode 5 : | MT2063_OFFAIR_8VSB
1314** --------------+----+----+----+----+-----+-----+--------------
1315** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1316** --------------+----+----+----+----+-----+-----+
1317**
1318**
1319*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001320static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1321static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1322static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1323static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1324static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1325static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1326static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1327static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1328static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1329static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1330static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1331static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1332static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1333static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001334
1335/*
1336** Local Function Prototypes - not available for external access.
1337*/
1338
1339/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001340static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1341 u32 f_LO_Step, u32 f_Ref);
1342static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1343 u32 f_LO_Step, u32 f_Ref);
1344static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1345 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001346
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001347/****************************************************************************
1348**
1349** Name: MT2063_GetLocked
1350**
1351** Description: Checks to see if LO1 and LO2 are locked.
1352**
1353** Parameters: h - Open handle to the tuner (from MT2063_Open).
1354**
1355** Returns: status:
1356** MT_OK - No errors
1357** MT_UPC_UNLOCK - Upconverter PLL unlocked
1358** MT_DNC_UNLOCK - Downconverter PLL unlocked
1359** MT_COMM_ERR - Serial bus communications error
1360** MT_INV_HANDLE - Invalid tuner handle
1361**
1362** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1363** MT_Sleep - Delay execution for x milliseconds
1364**
1365** Revision History:
1366**
1367** SCR Date Author Description
1368** -------------------------------------------------------------------------
1369** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1370**
1371****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001372static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001373{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001374 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1375 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1376 const u32 nMaxLoops = nMaxWait / nPollRate;
1377 const u8 LO1LK = 0x80;
1378 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001379 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001380 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001381
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001382 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001383 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001384 LO2LK = 0x40;
1385
1386 do {
1387 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001388 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001389 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001390 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001391
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001392 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001393 return (status);
1394
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001395 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001396 (LO1LK | LO2LK)) {
1397 return (status);
1398 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001399 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001400 }
1401 while (++nDelays < nMaxLoops);
1402
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001403 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001404 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001405 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001406 status |= MT2063_DNC_UNLOCK;
1407
1408 return (status);
1409}
1410
1411/****************************************************************************
1412**
1413** Name: MT2063_GetParam
1414**
1415** Description: Gets a tuning algorithm parameter.
1416**
1417** This function provides access to the internals of the
1418** tuning algorithm - mostly for testing purposes.
1419**
1420** Parameters: h - Tuner handle (returned by MT2063_Open)
1421** param - Tuning algorithm parameter
1422** (see enum MT2063_Param)
1423** pValue - ptr to returned value
1424**
1425** param Description
1426** ---------------------- --------------------------------
1427** MT2063_IC_ADDR Serial Bus address of this tuner
1428** MT2063_MAX_OPEN Max # of MT2063's allowed open
1429** MT2063_NUM_OPEN # of MT2063's open
1430** MT2063_SRO_FREQ crystal frequency
1431** MT2063_STEPSIZE minimum tuning step size
1432** MT2063_INPUT_FREQ input center frequency
1433** MT2063_LO1_FREQ LO1 Frequency
1434** MT2063_LO1_STEPSIZE LO1 minimum step size
1435** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1436** MT2063_IF1_ACTUAL Current 1st IF in use
1437** MT2063_IF1_REQUEST Requested 1st IF
1438** MT2063_IF1_CENTER Center of 1st IF SAW filter
1439** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1440** MT2063_ZIF_BW zero-IF bandwidth
1441** MT2063_LO2_FREQ LO2 Frequency
1442** MT2063_LO2_STEPSIZE LO2 minimum step size
1443** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1444** MT2063_OUTPUT_FREQ output center frequency
1445** MT2063_OUTPUT_BW output bandwidth
1446** MT2063_LO_SEPARATION min inter-tuner LO separation
1447** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1448** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1449** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1450** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1451** MT2063_NUM_SPURS # of spurs found/avoided
1452** MT2063_SPUR_AVOIDED >0 spurs avoided
1453** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1454** MT2063_RCVR_MODE Predefined modes.
1455** MT2063_ACLNA LNA attenuator gain code
1456** MT2063_ACRF RF attenuator gain code
1457** MT2063_ACFIF FIF attenuator gain code
1458** MT2063_ACLNA_MAX LNA attenuator limit
1459** MT2063_ACRF_MAX RF attenuator limit
1460** MT2063_ACFIF_MAX FIF attenuator limit
1461** MT2063_PD1 Actual value of PD1
1462** MT2063_PD2 Actual value of PD2
1463** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1464** MT2063_VGAGC VGA gain code
1465** MT2063_VGAOI VGA output current
1466** MT2063_TAGC TAGC setting
1467** MT2063_AMPGC AMP gain code
1468** MT2063_AVOID_DECT Avoid DECT Frequencies
1469** MT2063_CTFILT_SW Cleartune filter selection
1470**
1471** Usage: status |= MT2063_GetParam(hMT2063,
1472** MT2063_IF1_ACTUAL,
1473** &f_IF1_Actual);
1474**
1475** Returns: status:
1476** MT_OK - No errors
1477** MT_INV_HANDLE - Invalid tuner handle
1478** MT_ARG_NULL - Null pointer argument passed
1479** MT_ARG_RANGE - Invalid parameter requested
1480**
1481** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1482**
1483** See Also: MT2063_SetParam, MT2063_Open
1484**
1485** Revision History:
1486**
1487** SCR Date Author Description
1488** -------------------------------------------------------------------------
1489** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1490** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1491** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1492** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1493** in GetParam.
1494** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1495** Split SetParam up to ACLNA / ACLNA_MAX
1496** removed ACLNA_INRC/DECR (+RF & FIF)
1497** removed GCUAUTO / BYPATNDN/UP
1498** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1499** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1500** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1501**
1502****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001503static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001504{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001505 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001506 u32 Div;
1507 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001508
1509 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001510 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001511
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001512 switch (param) {
1513 /* Serial Bus address of this tuner */
1514 case MT2063_IC_ADDR:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001515 *pValue = state->config->tuner_address;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001516 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001517
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001518 /* Max # of MT2063's allowed to be open */
1519 case MT2063_MAX_OPEN:
1520 *pValue = nMT2063MaxTuners;
1521 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001522
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001523 /* # of MT2063's open */
1524 case MT2063_NUM_OPEN:
1525 *pValue = nMT2063OpenTuners;
1526 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001527
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001528 /* crystal frequency */
1529 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001530 *pValue = state->AS_Data.f_ref;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001531 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001532
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001533 /* minimum tuning step size */
1534 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001535 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001536 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001537
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001538 /* input center frequency */
1539 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001540 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001541 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001542
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001543 /* LO1 Frequency */
1544 case MT2063_LO1_FREQ:
1545 {
1546 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1547 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001548 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001549 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001550 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001551 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001552 Div = state->reg[MT2063_REG_LO1C_1];
1553 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1554 state->AS_Data.f_LO1 =
1555 (state->AS_Data.f_ref * Div) +
1556 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001557 f_ref, Num, 64);
1558 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001559 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001560 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001561
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001562 /* LO1 minimum step size */
1563 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001564 *pValue = state->AS_Data.f_LO1_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001565 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001566
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001567 /* LO1 FracN keep-out region */
1568 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001569 *pValue = state->AS_Data.f_LO1_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001570 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001571
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001572 /* Current 1st IF in use */
1573 case MT2063_IF1_ACTUAL:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001574 *pValue = state->f_IF1_actual;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001575 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001576
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001577 /* Requested 1st IF */
1578 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001579 *pValue = state->AS_Data.f_if1_Request;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001580 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001581
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001582 /* Center of 1st IF SAW filter */
1583 case MT2063_IF1_CENTER:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001584 *pValue = state->AS_Data.f_if1_Center;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001585 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001586
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001587 /* Bandwidth of 1st IF SAW filter */
1588 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001589 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001590 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001591
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001592 /* zero-IF bandwidth */
1593 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001594 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001595 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001596
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001597 /* LO2 Frequency */
1598 case MT2063_LO2_FREQ:
1599 {
1600 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1601 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001602 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001603 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001604 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001605 reg[MT2063_REG_LO2C_1], 3);
1606 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001607 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001608 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001609 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001610 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001611 (state->
1612 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001613 reg
1614 [MT2063_REG_LO2C_3]
1615 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001616 state->AS_Data.f_LO2 =
1617 (state->AS_Data.f_ref * Div) +
1618 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001619 f_ref, Num, 8191);
1620 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001621 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001622 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001623
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001624 /* LO2 minimum step size */
1625 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001626 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001627 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001628
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001629 /* LO2 FracN keep-out region */
1630 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001631 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001632 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001633
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001634 /* output center frequency */
1635 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001636 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001637 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001638
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001639 /* output bandwidth */
1640 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001641 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001642 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001643
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001644 /* min inter-tuner LO separation */
1645 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001646 *pValue = state->AS_Data.f_min_LO_Separation;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001647 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001648
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001649 /* max # of intra-tuner harmonics */
1650 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001651 *pValue = state->AS_Data.maxH1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001652 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001653
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001654 /* max # of inter-tuner harmonics */
1655 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001656 *pValue = state->AS_Data.maxH2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001657 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001658
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001659 /* # of 1st IF exclusion zones */
1660 case MT2063_EXCL_ZONES:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001661 *pValue = state->AS_Data.nZones;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001662 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001663
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001664 /* # of spurs found/avoided */
1665 case MT2063_NUM_SPURS:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001666 *pValue = state->AS_Data.nSpursFound;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001667 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001668
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001669 /* >0 spurs avoided */
1670 case MT2063_SPUR_AVOIDED:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001671 *pValue = state->AS_Data.bSpurAvoided;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001672 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001673
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001674 /* >0 spurs in output (mathematically) */
1675 case MT2063_SPUR_PRESENT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001676 *pValue = state->AS_Data.bSpurPresent;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001677 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001678
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001679 /* Predefined receiver setup combination */
1680 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001681 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001682 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001683
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001684 case MT2063_PD1:
1685 case MT2063_PD2: {
1686 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001687 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001688 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1689 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001690
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001691 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001692
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001693 /* Initiate ADC output to reg 0x0A */
1694 if (reg != orig)
1695 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001696 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001697 MT2063_REG_BYP_CTRL,
1698 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001699
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001700 if (status < 0)
1701 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001702
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001703 for (i = 0; i < 8; i++) {
1704 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001705 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001706 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001707 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001708 reg
1709 [MT2063_REG_ADC_OUT],
1710 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001711
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001712 if (status >= 0)
1713 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001714 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001715 reg[MT2063_REG_ADC_OUT];
1716 else {
1717 if (i)
1718 *pValue /= i;
1719 return (status);
1720 }
1721 }
1722 *pValue /= 8; /* divide by number of reads */
1723 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001724
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001725 /* Restore value of Register BYP_CTRL */
1726 if (reg != orig)
1727 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001728 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001729 MT2063_REG_BYP_CTRL,
1730 &orig, 1);
1731 }
1732 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001733
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001734 /* Get LNA attenuator code */
1735 case MT2063_ACLNA:
1736 {
1737 u8 val;
1738 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001739 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001740 &val);
1741 *pValue = val & 0x1f;
1742 }
1743 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001744
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001745 /* Get RF attenuator code */
1746 case MT2063_ACRF:
1747 {
1748 u8 val;
1749 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001750 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001751 &val);
1752 *pValue = val & 0x1f;
1753 }
1754 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001755
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001756 /* Get FIF attenuator code */
1757 case MT2063_ACFIF:
1758 {
1759 u8 val;
1760 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001761 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001762 &val);
1763 *pValue = val & 0x1f;
1764 }
1765 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001766
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001767 /* Get LNA attenuator limit */
1768 case MT2063_ACLNA_MAX:
1769 {
1770 u8 val;
1771 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001772 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001773 &val);
1774 *pValue = val & 0x1f;
1775 }
1776 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001777
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001778 /* Get RF attenuator limit */
1779 case MT2063_ACRF_MAX:
1780 {
1781 u8 val;
1782 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001783 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001784 &val);
1785 *pValue = val & 0x1f;
1786 }
1787 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001788
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001789 /* Get FIF attenuator limit */
1790 case MT2063_ACFIF_MAX:
1791 {
1792 u8 val;
1793 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001794 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001795 &val);
1796 *pValue = val & 0x1f;
1797 }
1798 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001799
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001800 /* Get current used DNC output */
1801 case MT2063_DNC_OUTPUT_ENABLE:
1802 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001803 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1804 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001805 *pValue =
1806 (u32) MT2063_DNC_NONE;
1807 else
1808 *pValue =
1809 (u32) MT2063_DNC_2;
1810 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001811
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001812 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001813 *pValue =
1814 (u32) MT2063_DNC_1;
1815 else
1816 *pValue =
1817 (u32) MT2063_DNC_BOTH;
1818 }
1819 }
1820 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001821
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001822 /* Get VGA Gain Code */
1823 case MT2063_VGAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001824 *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001825 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001826
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001827 /* Get VGA bias current */
1828 case MT2063_VGAOI:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001829 *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001830 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001831
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001832 /* Get TAGC setting */
1833 case MT2063_TAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001834 *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001835 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001836
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001837 /* Get AMP Gain Code */
1838 case MT2063_AMPGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001839 *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001840 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001841
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001842 /* Avoid DECT Frequencies */
1843 case MT2063_AVOID_DECT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001844 *pValue = state->AS_Data.avoidDECT;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001845 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001846
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001847 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
1848 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001849 *pValue = state->ctfilt_sw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001850 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001851
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001852 case MT2063_EOP:
1853 default:
1854 status |= -ERANGE;
1855 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001856 return (status);
1857}
1858
1859/****************************************************************************
1860**
1861** Name: MT2063_GetReg
1862**
1863** Description: Gets an MT2063 register.
1864**
1865** Parameters: h - Tuner handle (returned by MT2063_Open)
1866** reg - MT2063 register/subaddress location
1867** *val - MT2063 register/subaddress value
1868**
1869** Returns: status:
1870** MT_OK - No errors
1871** MT_COMM_ERR - Serial bus communications error
1872** MT_INV_HANDLE - Invalid tuner handle
1873** MT_ARG_NULL - Null pointer argument passed
1874** MT_ARG_RANGE - Argument out of range
1875**
1876** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1877**
1878** Use this function if you need to read a register from
1879** the MT2063.
1880**
1881** Revision History:
1882**
1883** SCR Date Author Description
1884** -------------------------------------------------------------------------
1885** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1886**
1887****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001888static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001889{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001890 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001891
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001892 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001893 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001894
1895 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001896 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001897
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001898 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001899
1900 return (status);
1901}
1902
1903/******************************************************************************
1904**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001905** Name: MT2063_SetReceiverMode
1906**
1907** Description: Set the MT2063 receiver mode
1908**
1909** --------------+----------------------------------------------
1910** Mode 0 : | MT2063_CABLE_QAM
1911** Mode 1 : | MT2063_CABLE_ANALOG
1912** Mode 2 : | MT2063_OFFAIR_COFDM
1913** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1914** Mode 4 : | MT2063_OFFAIR_ANALOG
1915** Mode 5 : | MT2063_OFFAIR_8VSB
1916** --------------+----+----+----+----+-----+--------------------
1917** (DNC1GC & DNC2GC are the values, which are used, when the specific
1918** DNC Output is selected, the other is always off)
1919**
1920** |<---------- Mode -------------->|
1921** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1922** ------------+-----+-----+-----+-----+-----+-----+
1923** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1924** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1925** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1926** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1927** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1928** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1929** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1930** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1931** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1932** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1933** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1934** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1935** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1936** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1937** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1938**
1939**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001940** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001941** Mode - desired reciever mode
1942**
1943** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1944**
1945** Returns: status:
1946** MT_OK - No errors
1947** MT_COMM_ERR - Serial bus communications error
1948**
1949** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1950** Assumes that the tuner cache is valid.
1951**
1952** Revision History:
1953**
1954** SCR Date Author Description
1955** -------------------------------------------------------------------------
1956** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1957** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
1958** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
1959** modulation
1960** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1961** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
1962** the same settings as with MT Launcher
1963** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
1964** Add SetParam DNC_OUTPUT_ENABLE
1965** Removed VGAGC from receiver mode,
1966** default now 1
1967** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
1968** Add SetParam AMPGC, removed from rcvr-mode
1969** Corrected names of GCU values
1970** reorganized receiver modes, removed,
1971** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
1972** Actualized Receiver-Mode values
1973** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
1974** N/A 11-27-2007 PINZ Improved buffered writing
1975** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
1976** correct wakeup of the LNA after shutdown
1977** Set AFCsd = 1 as default
1978** Changed CAP1sel default
1979** 01-14-2008 PINZ Ver 1.11: Updated gain settings
1980** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1981** Split SetParam up to ACLNA / ACLNA_MAX
1982** removed ACLNA_INRC/DECR (+RF & FIF)
1983** removed GCUAUTO / BYPATNDN/UP
1984**
1985******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001986static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001987 enum MT2063_RCVR_MODES Mode)
1988{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001989 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001990 u8 val;
1991 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001992
1993 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001994 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001995
1996 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001997 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001998 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001999 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002000 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002001 ? 0x40 :
2002 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002003 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2004 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002005 }
2006 }
2007
2008 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002009 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002010 status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002011 }
2012
2013 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002014 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002015 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002016 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002017 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002018 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002019 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002020 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002021 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002022 /* trigger FIFF calibration, needed after changing FIFFQ */
2023 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002024 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002025 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002026 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002027 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002028 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002029 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002030 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002031 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002032 }
2033 }
2034
2035 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002036 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
2037 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002038
2039 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002040 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002041 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002042 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002043 }
2044
2045 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002046 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002047 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002048 }
2049
2050 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002051 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002052 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002053 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002054 }
2055
2056 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002057 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002058 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002059 }
2060
2061 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002062 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002063 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002064 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002065 }
2066
2067 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002068 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002069 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002070 }
2071
2072 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002073 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002074 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002075 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002076 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002077 ? 0x80 :
2078 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002079 if (state->reg[MT2063_REG_LNA_TGT] != val) {
2080 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002081 }
2082 }
2083
2084 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002085 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002086 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002087 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002088 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002089 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002090 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2091 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002092 }
2093 }
2094
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002095 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002096 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002097
2098 return (status);
2099}
2100
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002101/****************************************************************************
2102**
2103** Name: MT2063_SetParam
2104**
2105** Description: Sets a tuning algorithm parameter.
2106**
2107** This function provides access to the internals of the
2108** tuning algorithm. You can override many of the tuning
2109** algorithm defaults using this function.
2110**
2111** Parameters: h - Tuner handle (returned by MT2063_Open)
2112** param - Tuning algorithm parameter
2113** (see enum MT2063_Param)
2114** nValue - value to be set
2115**
2116** param Description
2117** ---------------------- --------------------------------
2118** MT2063_SRO_FREQ crystal frequency
2119** MT2063_STEPSIZE minimum tuning step size
2120** MT2063_LO1_FREQ LO1 frequency
2121** MT2063_LO1_STEPSIZE LO1 minimum step size
2122** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2123** MT2063_IF1_REQUEST Requested 1st IF
2124** MT2063_ZIF_BW zero-IF bandwidth
2125** MT2063_LO2_FREQ LO2 frequency
2126** MT2063_LO2_STEPSIZE LO2 minimum step size
2127** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2128** MT2063_OUTPUT_FREQ output center frequency
2129** MT2063_OUTPUT_BW output bandwidth
2130** MT2063_LO_SEPARATION min inter-tuner LO separation
2131** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2132** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2133** MT2063_RCVR_MODE Predefined modes
2134** MT2063_LNA_RIN Set LNA Rin (*)
2135** MT2063_LNA_TGT Set target power level at LNA (*)
2136** MT2063_PD1_TGT Set target power level at PD1 (*)
2137** MT2063_PD2_TGT Set target power level at PD2 (*)
2138** MT2063_ACLNA_MAX LNA attenuator limit (*)
2139** MT2063_ACRF_MAX RF attenuator limit (*)
2140** MT2063_ACFIF_MAX FIF attenuator limit (*)
2141** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2142** MT2063_VGAGC VGA gain code
2143** MT2063_VGAOI VGA output current
2144** MT2063_TAGC TAGC setting
2145** MT2063_AMPGC AMP gain code
2146** MT2063_AVOID_DECT Avoid DECT Frequencies
2147** MT2063_CTFILT_SW Cleartune filter selection
2148**
2149** (*) This parameter is set by MT2063_RCVR_MODE, do not call
2150** additionally.
2151**
2152** Usage: status |= MT2063_SetParam(hMT2063,
2153** MT2063_STEPSIZE,
2154** 50000);
2155**
2156** Returns: status:
2157** MT_OK - No errors
2158** MT_INV_HANDLE - Invalid tuner handle
2159** MT_ARG_NULL - Null pointer argument passed
2160** MT_ARG_RANGE - Invalid parameter requested
2161** or set value out of range
2162** or non-writable parameter
2163**
2164** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2165**
2166** See Also: MT2063_GetParam, MT2063_Open
2167**
2168** Revision History:
2169**
2170** SCR Date Author Description
2171** -------------------------------------------------------------------------
2172** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2173** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2174** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2175** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2176** Split SetParam up to ACLNA / ACLNA_MAX
2177** removed ACLNA_INRC/DECR (+RF & FIF)
2178** removed GCUAUTO / BYPATNDN/UP
2179** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2180** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2181** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2182**
2183****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002184static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002185 enum MT2063_Param param,
2186 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002187{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002188 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002189 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002190
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002191 switch (param) {
2192 /* crystal frequency */
2193 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002194 state->AS_Data.f_ref = nValue;
2195 state->AS_Data.f_LO1_FracN_Avoid = 0;
2196 state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
2197 state->AS_Data.f_LO1_Step = nValue / 64;
2198 state->AS_Data.f_if1_Center =
2199 (state->AS_Data.f_ref / 8) *
2200 (state->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002201 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002202
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002203 /* minimum tuning step size */
2204 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002205 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002206 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002207
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002208 /* LO1 frequency */
2209 case MT2063_LO1_FREQ:
2210 {
2211 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2212 /* Capture the Divider and Numerator portions of other LO */
2213 u8 tempLO2CQ[3];
2214 u8 tempLO2C[3];
2215 u8 tmpOneShot;
2216 u32 Div, FracN;
2217 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002218
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002219 /* Buffer the queue for restoration later and get actual LO2 values. */
2220 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002221 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002222 MT2063_REG_LO2CQ_1,
2223 &(tempLO2CQ[0]), 3);
2224 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002225 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002226 MT2063_REG_LO2C_1,
2227 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002228
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002229 /* clear the one-shot bits */
2230 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
2231 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002232
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002233 /* only write the queue values if they are different from the actual. */
2234 if ((tempLO2CQ[0] != tempLO2C[0]) ||
2235 (tempLO2CQ[1] != tempLO2C[1]) ||
2236 (tempLO2CQ[2] != tempLO2C[2])) {
2237 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002238 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002239 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002240 MT2063_REG_LO2CQ_1,
2241 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002242
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002243 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002244 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002245 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002246 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002247 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002248 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002249 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002250 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002251 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002252 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002253 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002254
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002255 /* Calculate the Divider and Numberator components of LO1 */
2256 status =
2257 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002258 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002259 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002260 state->AS_Data.f_ref);
2261 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002262 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002263 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002264 (u8) (FracN);
2265 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002266 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002267 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002268 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002269 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002270
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002271 /* set the one-shot bit to load the pair of LO values */
2272 tmpOneShot = tempLO2CQ[2] | 0xE0;
2273 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002274 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002275 MT2063_REG_LO2CQ_3,
2276 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002277
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002278 /* only restore the queue values if they were different from the actual. */
2279 if (restore) {
2280 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002281 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002282 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002283 MT2063_REG_LO2CQ_1,
2284 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002285
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002286 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002287 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002288 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002289 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002290 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002291 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002292 tempLO2CQ[2];
2293 }
2294
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002295 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002296 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002297 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002298 }
2299 break;
2300
2301 /* LO1 minimum step size */
2302 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002303 state->AS_Data.f_LO1_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002304 break;
2305
2306 /* LO1 FracN keep-out region */
2307 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002308 state->AS_Data.f_LO1_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002309 break;
2310
2311 /* Requested 1st IF */
2312 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002313 state->AS_Data.f_if1_Request = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002314 break;
2315
2316 /* zero-IF bandwidth */
2317 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002318 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002319 break;
2320
2321 /* LO2 frequency */
2322 case MT2063_LO2_FREQ:
2323 {
2324 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2325 /* Capture the Divider and Numerator portions of other LO */
2326 u8 tempLO1CQ[2];
2327 u8 tempLO1C[2];
2328 u32 Div2;
2329 u32 FracN2;
2330 u8 tmpOneShot;
2331 u8 restore = 0;
2332
2333 /* Buffer the queue for restoration later and get actual LO2 values. */
2334 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002335 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002336 MT2063_REG_LO1CQ_1,
2337 &(tempLO1CQ[0]), 2);
2338 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002339 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002340 MT2063_REG_LO1C_1,
2341 &(tempLO1C[0]), 2);
2342
2343 /* only write the queue values if they are different from the actual. */
2344 if ((tempLO1CQ[0] != tempLO1C[0])
2345 || (tempLO1CQ[1] != tempLO1C[1])) {
2346 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002347 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002348 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002349 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002350 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002351
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002352 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002353 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002354 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002355 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002356 tempLO1C[1];
2357 restore = 1;
2358 }
2359
2360 /* Calculate the Divider and Numberator components of LO2 */
2361 status =
2362 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002363 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002364 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002365 state->AS_Data.f_ref);
2366 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002367 (u8) ((Div2 << 1) |
2368 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002369 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002370 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002371 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002372 (u8) ((FracN2 & 0x0F));
2373 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002374 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002375 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002376 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002377 reg[MT2063_REG_LO1CQ_1], 3);
2378
2379 /* set the one-shot bit to load the LO values */
2380 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002381 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002382 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002383 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002384 MT2063_REG_LO2CQ_3,
2385 &tmpOneShot, 1);
2386
2387 /* only restore LO1 queue value if they were different from the actual. */
2388 if (restore) {
2389 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002390 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002391 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002392 MT2063_REG_LO1CQ_1,
2393 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002394
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002395 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002396 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002397 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002398 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002399 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002400 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002401
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002402 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002403 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002404 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002405 }
2406 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002407
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002408 /* LO2 minimum step size */
2409 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002410 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002411 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002412
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002413 /* LO2 FracN keep-out region */
2414 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002415 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002416 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002417
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002418 /* output center frequency */
2419 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002420 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002421 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002422
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002423 /* output bandwidth */
2424 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002425 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002426 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002427
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002428 /* min inter-tuner LO separation */
2429 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002430 state->AS_Data.f_min_LO_Separation = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002431 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002432
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002433 /* max # of intra-tuner harmonics */
2434 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002435 state->AS_Data.maxH1 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002436 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002437
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002438 /* max # of inter-tuner harmonics */
2439 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002440 state->AS_Data.maxH2 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002441 break;
2442
2443 case MT2063_RCVR_MODE:
2444 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002445 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002446 (enum MT2063_RCVR_MODES)
2447 nValue);
2448 break;
2449
2450 /* Set LNA Rin -- nValue is desired value */
2451 case MT2063_LNA_RIN:
2452 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002453 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002454 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2455 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002456 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002457 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002458 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002459 val);
2460 }
2461 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002462
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002463 /* Set target power level at LNA -- nValue is desired value */
2464 case MT2063_LNA_TGT:
2465 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002466 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002467 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2468 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002469 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002470 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002471 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002472 val);
2473 }
2474 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002475
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002476 /* Set target power level at PD1 -- nValue is desired value */
2477 case MT2063_PD1_TGT:
2478 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002479 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002480 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2481 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002482 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002483 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002484 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002485 val);
2486 }
2487 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002488
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002489 /* Set target power level at PD2 -- nValue is desired value */
2490 case MT2063_PD2_TGT:
2491 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002492 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002493 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2494 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002495 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002496 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002497 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002498 val);
2499 }
2500 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002501
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002502 /* Set LNA atten limit -- nValue is desired value */
2503 case MT2063_ACLNA_MAX:
2504 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002505 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002506 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2507 &
2508 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002509 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002510 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002511 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002512 val);
2513 }
2514 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002515
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002516 /* Set RF atten limit -- nValue is desired value */
2517 case MT2063_ACRF_MAX:
2518 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002519 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002520 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2521 &
2522 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002523 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002524 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002525 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002526 }
2527 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002528
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002529 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2530 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002531 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002532 && nValue > 5)
2533 nValue = 5;
2534 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002535 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002536 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2537 &
2538 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002539 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002540 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002541 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002542 val);
2543 }
2544 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002545
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002546 case MT2063_DNC_OUTPUT_ENABLE:
2547 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002548 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002549 case MT2063_DNC_NONE:
2550 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002551 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2552 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002553 val)
2554 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002555 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002556 MT2063_REG_DNC_GAIN,
2557 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002558
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002559 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2560 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002561 val)
2562 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002563 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002564 MT2063_REG_VGA_GAIN,
2565 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002566
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002567 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2568 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002569 val)
2570 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002571 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002572 MT2063_REG_RSVD_20,
2573 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002574
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002575 break;
2576 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002577 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002578 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002579 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2580 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002581 val)
2582 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002583 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002584 MT2063_REG_DNC_GAIN,
2585 val);
2586
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002587 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2588 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002589 val)
2590 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002591 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002592 MT2063_REG_VGA_GAIN,
2593 val);
2594
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002595 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2596 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002597 val)
2598 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002599 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002600 MT2063_REG_RSVD_20,
2601 val);
2602
2603 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002604 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002605 case MT2063_DNC_2:
2606 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002607 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2608 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002609 val)
2610 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002611 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002612 MT2063_REG_DNC_GAIN,
2613 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002614
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002615 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2616 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002617 val)
2618 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002619 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002620 MT2063_REG_VGA_GAIN,
2621 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002622
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002623 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2624 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002625 val)
2626 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002627 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002628 MT2063_REG_RSVD_20,
2629 val);
2630
2631 break;
2632 }
2633 case MT2063_DNC_BOTH:
2634 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002635 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2636 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002637 val)
2638 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002639 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002640 MT2063_REG_DNC_GAIN,
2641 val);
2642
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002643 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2644 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002645 val)
2646 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002647 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002648 MT2063_REG_VGA_GAIN,
2649 val);
2650
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002651 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2652 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002653 val)
2654 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002655 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002656 MT2063_REG_RSVD_20,
2657 val);
2658
2659 break;
2660 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002661 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002662 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002663 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002664 break;
2665
2666 case MT2063_VGAGC:
2667 /* Set VGA gain code */
2668 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002669 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002670 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
2671 ((nValue & 0x03) << 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002672 if (state->reg[MT2063_REG_VGA_GAIN] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002673 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002674 MT2063_SetReg(state, MT2063_REG_VGA_GAIN,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002675 val);
2676 }
2677 break;
2678
2679 case MT2063_VGAOI:
2680 /* Set VGA bias current */
2681 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002682 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002683 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
2684 (nValue & 0x07);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002685 if (state->reg[MT2063_REG_RSVD_31] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002686 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002687 MT2063_SetReg(state, MT2063_REG_RSVD_31,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002688 val);
2689 }
2690 break;
2691
2692 case MT2063_TAGC:
2693 /* Set TAGC */
2694 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002695 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002696 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
2697 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002698 if (state->reg[MT2063_REG_RSVD_1E] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002699 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002700 MT2063_SetReg(state, MT2063_REG_RSVD_1E,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002701 val);
2702 }
2703 break;
2704
2705 case MT2063_AMPGC:
2706 /* Set Amp gain code */
2707 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002708 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002709 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
2710 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002711 if (state->reg[MT2063_REG_TEMP_SEL] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002712 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002713 MT2063_SetReg(state, MT2063_REG_TEMP_SEL,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002714 val);
2715 }
2716 break;
2717
2718 /* Avoid DECT Frequencies */
2719 case MT2063_AVOID_DECT:
2720 {
2721 enum MT2063_DECT_Avoid_Type newAvoidSetting =
2722 (enum MT2063_DECT_Avoid_Type)nValue;
2723 if ((newAvoidSetting >=
2724 MT2063_NO_DECT_AVOIDANCE)
2725 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002726 state->AS_Data.avoidDECT =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002727 newAvoidSetting;
2728 }
2729 }
2730 break;
2731
2732 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2733 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002734 state->ctfilt_sw = (nValue & 0x01);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002735 break;
2736
2737 /* These parameters are read-only */
2738 case MT2063_IC_ADDR:
2739 case MT2063_MAX_OPEN:
2740 case MT2063_NUM_OPEN:
2741 case MT2063_INPUT_FREQ:
2742 case MT2063_IF1_ACTUAL:
2743 case MT2063_IF1_CENTER:
2744 case MT2063_IF1_BW:
2745 case MT2063_AS_ALG:
2746 case MT2063_EXCL_ZONES:
2747 case MT2063_SPUR_AVOIDED:
2748 case MT2063_NUM_SPURS:
2749 case MT2063_SPUR_PRESENT:
2750 case MT2063_ACLNA:
2751 case MT2063_ACRF:
2752 case MT2063_ACFIF:
2753 case MT2063_EOP:
2754 default:
2755 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002756 }
2757 return (status);
2758}
2759
2760/****************************************************************************
2761**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002762** Name: MT2063_ClearPowerMaskBits
2763**
2764** Description: Clears the power-down mask bits for various sections of
2765** the MT2063
2766**
2767** Parameters: h - Tuner handle (returned by MT2063_Open)
2768** Bits - Mask bits to be cleared.
2769**
2770** See definition of MT2063_Mask_Bits type for description
2771** of each of the power bits.
2772**
2773** Returns: status:
2774** MT_OK - No errors
2775** MT_INV_HANDLE - Invalid tuner handle
2776** MT_COMM_ERR - Serial bus communications error
2777**
2778** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2779**
2780** Revision History:
2781**
2782** SCR Date Author Description
2783** -------------------------------------------------------------------------
2784** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2785**
2786****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002787static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002788{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002789 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002790
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002791 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
2792 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002793 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002794 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002795 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002796 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002797 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002798 }
2799 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002800 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002801 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002802 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002803 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002804 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002805 }
2806
2807 return (status);
2808}
2809
2810/****************************************************************************
2811**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002812** Name: MT2063_SoftwareShutdown
2813**
2814** Description: Enables or disables software shutdown function. When
2815** Shutdown==1, any section whose power mask is set will be
2816** shutdown.
2817**
2818** Parameters: h - Tuner handle (returned by MT2063_Open)
2819** Shutdown - 1 = shutdown the masked sections, otherwise
2820** power all sections on
2821**
2822** Returns: status:
2823** MT_OK - No errors
2824** MT_INV_HANDLE - Invalid tuner handle
2825** MT_COMM_ERR - Serial bus communications error
2826**
2827** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2828**
2829** Revision History:
2830**
2831** SCR Date Author Description
2832** -------------------------------------------------------------------------
2833** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2834** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
2835** correct wakeup of the LNA
2836**
2837****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002838static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002839{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002840 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002841
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002842 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002843 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002844 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002845 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002846
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002847 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002848 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002849 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002850 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002851
2852 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002853 state->reg[MT2063_REG_BYP_CTRL] =
2854 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002855 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002856 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002857 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002858 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002859 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002860 state->reg[MT2063_REG_BYP_CTRL] =
2861 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002862 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002863 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002864 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002865 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002866 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002867 }
2868
2869 return (status);
2870}
2871
2872/****************************************************************************
2873**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002874** Name: MT2063_SetReg
2875**
2876** Description: Sets an MT2063 register.
2877**
2878** Parameters: h - Tuner handle (returned by MT2063_Open)
2879** reg - MT2063 register/subaddress location
2880** val - MT2063 register/subaddress value
2881**
2882** Returns: status:
2883** MT_OK - No errors
2884** MT_COMM_ERR - Serial bus communications error
2885** MT_INV_HANDLE - Invalid tuner handle
2886** MT_ARG_RANGE - Argument out of range
2887**
2888** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2889**
2890** Use this function if you need to override a default
2891** register value
2892**
2893** Revision History:
2894**
2895** SCR Date Author Description
2896** -------------------------------------------------------------------------
2897** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2898**
2899****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002900static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002901{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002902 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002903
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002904 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002905 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002906
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002907 status = mt2063_write(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002908 1);
2909 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002910 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002911
2912 return (status);
2913}
2914
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002915static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002916{
2917 return f_ref * (f_LO / f_ref)
2918 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
2919}
2920
2921/****************************************************************************
2922**
2923** Name: fLO_FractionalTerm
2924**
2925** Description: Calculates the portion contributed by FracN / denom.
2926**
2927** This function preserves maximum precision without
2928** risk of overflow. It accurately calculates
2929** f_ref * num / denom to within 1 HZ with fixed math.
2930**
2931** Parameters: num - Fractional portion of the multiplier
2932** denom - denominator portion of the ratio
2933** This routine successfully handles denom values
2934** up to and including 2^18.
2935** f_Ref - SRO frequency. This calculation handles
2936** f_ref as two separate 14-bit fields.
2937** Therefore, a maximum value of 2^28-1
2938** may safely be used for f_ref. This is
2939** the genesis of the magic number "14" and the
2940** magic mask value of 0x03FFF.
2941**
2942** Returns: f_ref * num / denom
2943**
2944** Revision History:
2945**
2946** SCR Date Author Description
2947** -------------------------------------------------------------------------
2948** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2949**
2950****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002951static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
2952 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002953{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002954 u32 t1 = (f_ref >> 14) * num;
2955 u32 term1 = t1 / denom;
2956 u32 loss = t1 % denom;
2957 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002958 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
2959 return ((term1 << 14) + term2);
2960}
2961
2962/****************************************************************************
2963**
2964** Name: CalcLO1Mult
2965**
2966** Description: Calculates Integer divider value and the numerator
2967** value for a FracN PLL.
2968**
2969** This function assumes that the f_LO and f_Ref are
2970** evenly divisible by f_LO_Step.
2971**
2972** Parameters: Div - OUTPUT: Whole number portion of the multiplier
2973** FracN - OUTPUT: Fractional portion of the multiplier
2974** f_LO - desired LO frequency.
2975** f_LO_Step - Minimum step size for the LO (in Hz).
2976** f_Ref - SRO frequency.
2977** f_Avoid - Range of PLL frequencies to avoid near
2978** integer multiples of f_Ref (in Hz).
2979**
2980** Returns: Recalculated LO frequency.
2981**
2982** Revision History:
2983**
2984** SCR Date Author Description
2985** -------------------------------------------------------------------------
2986** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2987**
2988****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002989static u32 MT2063_CalcLO1Mult(u32 * Div,
2990 u32 * FracN,
2991 u32 f_LO,
2992 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002993{
2994 /* Calculate the whole number portion of the divider */
2995 *Div = f_LO / f_Ref;
2996
2997 /* Calculate the numerator value (round to nearest f_LO_Step) */
2998 *FracN =
2999 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3000 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3001
3002 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
3003}
3004
3005/****************************************************************************
3006**
3007** Name: CalcLO2Mult
3008**
3009** Description: Calculates Integer divider value and the numerator
3010** value for a FracN PLL.
3011**
3012** This function assumes that the f_LO and f_Ref are
3013** evenly divisible by f_LO_Step.
3014**
3015** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3016** FracN - OUTPUT: Fractional portion of the multiplier
3017** f_LO - desired LO frequency.
3018** f_LO_Step - Minimum step size for the LO (in Hz).
3019** f_Ref - SRO frequency.
3020** f_Avoid - Range of PLL frequencies to avoid near
3021** integer multiples of f_Ref (in Hz).
3022**
3023** Returns: Recalculated LO frequency.
3024**
3025** Revision History:
3026**
3027** SCR Date Author Description
3028** -------------------------------------------------------------------------
3029** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3030**
3031****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003032static u32 MT2063_CalcLO2Mult(u32 * Div,
3033 u32 * FracN,
3034 u32 f_LO,
3035 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003036{
3037 /* Calculate the whole number portion of the divider */
3038 *Div = f_LO / f_Ref;
3039
3040 /* Calculate the numerator value (round to nearest f_LO_Step) */
3041 *FracN =
3042 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3043 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3044
3045 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
3046 8191);
3047}
3048
3049/****************************************************************************
3050**
3051** Name: FindClearTuneFilter
3052**
3053** Description: Calculate the corrrect ClearTune filter to be used for
3054** a given input frequency.
3055**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003056** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003057** f_in - RF input center frequency (in Hz).
3058**
3059** Returns: ClearTune filter number (0-31)
3060**
3061** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3062**
3063** Revision History:
3064**
3065** SCR Date Author Description
3066** -------------------------------------------------------------------------
3067** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3068** cross-over frequency values.
3069**
3070****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003071static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003072{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003073 u32 RFBand;
3074 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003075
3076 /*
3077 ** Find RF Band setting
3078 */
3079 RFBand = 31; /* def when f_in > all */
3080 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003081 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003082 RFBand = idx;
3083 break;
3084 }
3085 }
3086 return (RFBand);
3087}
3088
3089/****************************************************************************
3090**
3091** Name: MT2063_Tune
3092**
3093** Description: Change the tuner's tuned frequency to RFin.
3094**
3095** Parameters: h - Open handle to the tuner (from MT2063_Open).
3096** f_in - RF input center frequency (in Hz).
3097**
3098** Returns: status:
3099** MT_OK - No errors
3100** MT_INV_HANDLE - Invalid tuner handle
3101** MT_UPC_UNLOCK - Upconverter PLL unlocked
3102** MT_DNC_UNLOCK - Downconverter PLL unlocked
3103** MT_COMM_ERR - Serial bus communications error
3104** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3105** MT_SPUR_PRESENT - LO spur possible in output
3106** MT_FIN_RANGE - Input freq out of range
3107** MT_FOUT_RANGE - Output freq out of range
3108** MT_UPC_RANGE - Upconverter freq out of range
3109** MT_DNC_RANGE - Downconverter freq out of range
3110**
3111** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
3112**
3113** MT_ReadSub - Read data from the two-wire serial bus
3114** MT_WriteSub - Write data to the two-wire serial bus
3115** MT_Sleep - Delay execution for x milliseconds
3116** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
3117**
3118** Revision History:
3119**
3120** SCR Date Author Description
3121** -------------------------------------------------------------------------
3122** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3123** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
3124** cross-over frequency values.
3125** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3126** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3127** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3128**
3129****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003130static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003131{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003132
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003133 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003134 u32 LO1; /* 1st LO register value */
3135 u32 Num1; /* Numerator for LO1 reg. value */
3136 u32 f_IF1; /* 1st IF requested */
3137 u32 LO2; /* 2nd LO register value */
3138 u32 Num2; /* Numerator for LO2 reg. value */
3139 u32 ofLO1, ofLO2; /* last time's LO frequencies */
3140 u32 ofin, ofout; /* last time's I/O frequencies */
3141 u8 fiffc = 0x80; /* FIFF center freq from tuner */
3142 u32 fiffof; /* Offset from FIFF center freq */
3143 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
3144 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
3145 u8 val;
3146 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003147
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003148 /* Check the input and output frequency ranges */
3149 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003150 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003151
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003152 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
3153 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003154 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003155
3156 /*
3157 ** Save original LO1 and LO2 register values
3158 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003159 ofLO1 = state->AS_Data.f_LO1;
3160 ofLO2 = state->AS_Data.f_LO2;
3161 ofin = state->AS_Data.f_in;
3162 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003163
3164 /*
3165 ** Find and set RF Band setting
3166 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003167 if (state->ctfilt_sw == 1) {
3168 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
3169 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003170 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003171 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003172 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003173 val = state->reg[MT2063_REG_CTUNE_OV];
3174 RFBand = FindClearTuneFilter(state, f_in);
3175 state->reg[MT2063_REG_CTUNE_OV] =
3176 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003177 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003178 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003179 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003180 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003181 }
3182 }
3183
3184 /*
3185 ** Read the FIFF Center Frequency from the tuner
3186 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003187 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003188 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003189 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003190 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003191 &state->reg[MT2063_REG_FIFFC], 1);
3192 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003193 }
3194 /*
3195 ** Assign in the requested values
3196 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003197 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003198 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003199 state->AS_Data.f_if1_Request =
3200 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
3201 state->AS_Data.f_LO1_Step,
3202 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003203
3204 /*
3205 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
3206 ** desired LO1 frequency
3207 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003208 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003209
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003210 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003211
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003212 state->AS_Data.f_LO1 =
3213 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
3214 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003215
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003216 state->AS_Data.f_LO2 =
3217 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3218 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003219
3220 /*
3221 ** Check for any LO spurs in the output bandwidth and adjust
3222 ** the LO settings to avoid them if needed
3223 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003224 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003225 /*
3226 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
3227 ** Recalculate the LO frequencies and the values to be placed
3228 ** in the tuning registers.
3229 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003230 state->AS_Data.f_LO1 =
3231 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
3232 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
3233 state->AS_Data.f_LO2 =
3234 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3235 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
3236 state->AS_Data.f_LO2 =
3237 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
3238 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003239
3240 /*
3241 ** Check the upconverter and downconverter frequency ranges
3242 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003243 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
3244 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003245 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003246 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
3247 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003248 status |= MT2063_DNC_RANGE;
3249 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003250 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003251 LO2LK = 0x40;
3252
3253 /*
3254 ** If we have the same LO frequencies and we're already locked,
3255 ** then skip re-programming the LO registers.
3256 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003257 if ((ofLO1 != state->AS_Data.f_LO1)
3258 || (ofLO2 != state->AS_Data.f_LO2)
3259 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003260 (LO1LK | LO2LK))) {
3261 /*
3262 ** Calculate the FIFFOF register value
3263 **
3264 ** IF1_Actual
3265 ** FIFFOF = ------------ - 8 * FIFFC - 4992
3266 ** f_ref/64
3267 */
3268 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003269 (state->AS_Data.f_LO1 -
3270 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003271 4992;
3272 if (fiffof > 0xFF)
3273 fiffof = 0xFF;
3274
3275 /*
3276 ** Place all of the calculated values into the local tuner
3277 ** register fields.
3278 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003279 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003280 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
3281 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
3282 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003283 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003284 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
3285 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003286
3287 /*
3288 ** Now write out the computed register values
3289 ** IMPORTANT: There is a required order for writing
3290 ** (0x05 must follow all the others).
3291 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003292 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 -03003293 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003294 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003295 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003296 }
3297 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003298 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003299 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003300 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003301 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003302 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003303 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003304 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003305 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003306 reg[MT2063_REG_FIFF_OFFSET],
3307 1);
3308 }
3309 }
3310
3311 /*
3312 ** Check for LO's locking
3313 */
3314
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003315 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003316 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003317 }
3318 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003319 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003320 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003321 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003322 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003323 }
3324 }
3325
3326 return (status);
3327}
3328
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003329static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003330 enum MTTune_atv_standard tv_type)
3331{
3332
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003333 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003334
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003335 s32 pict_car = 0;
3336 s32 pict2chanb_vsb = 0;
3337 s32 pict2chanb_snd = 0;
3338 s32 pict2snd1 = 0;
3339 s32 pict2snd2 = 0;
3340 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003341
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003342 s32 if_mid = 0;
3343 s32 rcvr_mode = 0;
3344 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003345
3346 switch (tv_type) {
3347 case MTTUNEA_PAL_B:{
3348 pict_car = 38900000;
3349 ch_bw = 8000000;
3350 pict2chanb_vsb = -1250000;
3351 pict2snd1 = 5500000;
3352 pict2snd2 = 5742000;
3353 rcvr_mode = 1;
3354 break;
3355 }
3356 case MTTUNEA_PAL_G:{
3357 pict_car = 38900000;
3358 ch_bw = 7000000;
3359 pict2chanb_vsb = -1250000;
3360 pict2snd1 = 5500000;
3361 pict2snd2 = 0;
3362 rcvr_mode = 1;
3363 break;
3364 }
3365 case MTTUNEA_PAL_I:{
3366 pict_car = 38900000;
3367 ch_bw = 8000000;
3368 pict2chanb_vsb = -1250000;
3369 pict2snd1 = 6000000;
3370 pict2snd2 = 0;
3371 rcvr_mode = 1;
3372 break;
3373 }
3374 case MTTUNEA_PAL_L:{
3375 pict_car = 38900000;
3376 ch_bw = 8000000;
3377 pict2chanb_vsb = -1250000;
3378 pict2snd1 = 6500000;
3379 pict2snd2 = 0;
3380 rcvr_mode = 1;
3381 break;
3382 }
3383 case MTTUNEA_PAL_MN:{
3384 pict_car = 38900000;
3385 ch_bw = 6000000;
3386 pict2chanb_vsb = -1250000;
3387 pict2snd1 = 4500000;
3388 pict2snd2 = 0;
3389 rcvr_mode = 1;
3390 break;
3391 }
3392 case MTTUNEA_PAL_DK:{
3393 pict_car = 38900000;
3394 ch_bw = 8000000;
3395 pict2chanb_vsb = -1250000;
3396 pict2snd1 = 6500000;
3397 pict2snd2 = 0;
3398 rcvr_mode = 1;
3399 break;
3400 }
3401 case MTTUNEA_DIGITAL:{
3402 pict_car = 36125000;
3403 ch_bw = 8000000;
3404 pict2chanb_vsb = -(ch_bw / 2);
3405 pict2snd1 = 0;
3406 pict2snd2 = 0;
3407 rcvr_mode = 2;
3408 break;
3409 }
3410 case MTTUNEA_FMRADIO:{
3411 pict_car = 38900000;
3412 ch_bw = 8000000;
3413 pict2chanb_vsb = -(ch_bw / 2);
3414 pict2snd1 = 0;
3415 pict2snd2 = 0;
3416 rcvr_mode = 4;
3417 //f_in -= 2900000;
3418 break;
3419 }
3420 case MTTUNEA_DVBC:{
3421 pict_car = 36125000;
3422 ch_bw = 8000000;
3423 pict2chanb_vsb = -(ch_bw / 2);
3424 pict2snd1 = 0;
3425 pict2snd2 = 0;
3426 rcvr_mode = MT2063_CABLE_QAM;
3427 break;
3428 }
3429 case MTTUNEA_DVBT:{
3430 pict_car = 36125000;
3431 ch_bw = bw_in; //8000000
3432 pict2chanb_vsb = -(ch_bw / 2);
3433 pict2snd1 = 0;
3434 pict2snd2 = 0;
3435 rcvr_mode = MT2063_OFFAIR_COFDM;
3436 break;
3437 }
3438 case MTTUNEA_UNKNOWN:
3439 break;
3440 default:
3441 break;
3442 }
3443
3444 pict2chanb_snd = pict2chanb_vsb - ch_bw;
3445 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
3446
3447 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
3448 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
3449 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
3450 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3451
3452 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
3453 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
3454 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3455
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003456 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003457}
3458
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003459static const u8 MT2063B0_defaults[] = {
3460 /* Reg, Value */
3461 0x19, 0x05,
3462 0x1B, 0x1D,
3463 0x1C, 0x1F,
3464 0x1D, 0x0F,
3465 0x1E, 0x3F,
3466 0x1F, 0x0F,
3467 0x20, 0x3F,
3468 0x22, 0x21,
3469 0x23, 0x3F,
3470 0x24, 0x20,
3471 0x25, 0x3F,
3472 0x27, 0xEE,
3473 0x2C, 0x27, /* bit at 0x20 is cleared below */
3474 0x30, 0x03,
3475 0x2C, 0x07, /* bit at 0x20 is cleared here */
3476 0x2D, 0x87,
3477 0x2E, 0xAA,
3478 0x28, 0xE1, /* Set the FIFCrst bit here */
3479 0x28, 0xE0, /* Clear the FIFCrst bit here */
3480 0x00
3481};
3482
3483/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3484static const u8 MT2063B1_defaults[] = {
3485 /* Reg, Value */
3486 0x05, 0xF0,
3487 0x11, 0x10, /* New Enable AFCsd */
3488 0x19, 0x05,
3489 0x1A, 0x6C,
3490 0x1B, 0x24,
3491 0x1C, 0x28,
3492 0x1D, 0x8F,
3493 0x1E, 0x14,
3494 0x1F, 0x8F,
3495 0x20, 0x57,
3496 0x22, 0x21, /* New - ver 1.03 */
3497 0x23, 0x3C, /* New - ver 1.10 */
3498 0x24, 0x20, /* New - ver 1.03 */
3499 0x2C, 0x24, /* bit at 0x20 is cleared below */
3500 0x2D, 0x87, /* FIFFQ=0 */
3501 0x2F, 0xF3,
3502 0x30, 0x0C, /* New - ver 1.11 */
3503 0x31, 0x1B, /* New - ver 1.11 */
3504 0x2C, 0x04, /* bit at 0x20 is cleared here */
3505 0x28, 0xE1, /* Set the FIFCrst bit here */
3506 0x28, 0xE0, /* Clear the FIFCrst bit here */
3507 0x00
3508};
3509
3510/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
3511static const u8 MT2063B3_defaults[] = {
3512 /* Reg, Value */
3513 0x05, 0xF0,
3514 0x19, 0x3D,
3515 0x2C, 0x24, /* bit at 0x20 is cleared below */
3516 0x2C, 0x04, /* bit at 0x20 is cleared here */
3517 0x28, 0xE1, /* Set the FIFCrst bit here */
3518 0x28, 0xE0, /* Clear the FIFCrst bit here */
3519 0x00
3520};
3521
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003522static int mt2063_init(struct dvb_frontend *fe)
3523{
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003524 u32 status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003525 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003526 u8 all_resets = 0xF0; /* reset/load bits */
3527 const u8 *def = NULL;
3528 u32 FCRUN;
3529 s32 maxReads;
3530 u32 fcu_osc;
3531 u32 i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003532
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003533 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003534
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003535 /* Read the Part/Rev code from the tuner */
3536 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
3537 if (status < 0)
3538 return status;
3539
3540 /* Check the part/rev code */
3541 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
3542 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
3543 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
3544 return -ENODEV; /* Wrong tuner Part/Rev code */
3545
3546 /* Check the 2nd byte of the Part/Rev code from the tuner */
3547 status = mt2063_read(state, MT2063_REG_RSVD_3B,
3548 &state->reg[MT2063_REG_RSVD_3B], 1);
3549
3550 /* b7 != 0 ==> NOT MT2063 */
3551 if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00))
3552 return -ENODEV; /* Wrong tuner Part/Rev code */
3553
3554 /* Reset the tuner */
3555 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
3556 if (status < 0)
3557 return status;
3558
3559 /* change all of the default values that vary from the HW reset values */
3560 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
3561 switch (state->reg[MT2063_REG_PART_REV]) {
3562 case MT2063_B3:
3563 def = MT2063B3_defaults;
3564 break;
3565
3566 case MT2063_B1:
3567 def = MT2063B1_defaults;
3568 break;
3569
3570 case MT2063_B0:
3571 def = MT2063B0_defaults;
3572 break;
3573
3574 default:
3575 return -ENODEV;
3576 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003577 }
3578
Mauro Carvalho Chehab01e0daf2011-07-21 03:20:43 -03003579 while (status >= 0 && *def) {
3580 u8 reg = *def++;
3581 u8 val = *def++;
3582 status = mt2063_write(state, reg, &val, 1);
3583 }
3584 if (status < 0)
3585 return status;
3586
3587 /* Wait for FIFF location to complete. */
3588 FCRUN = 1;
3589 maxReads = 10;
3590 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
3591 msleep(2);
3592 status = mt2063_read(state,
3593 MT2063_REG_XO_STATUS,
3594 &state->
3595 reg[MT2063_REG_XO_STATUS], 1);
3596 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
3597 }
3598
3599 if (FCRUN != 0 || status < 0)
3600 return -ENODEV;
3601
3602 status = mt2063_read(state,
3603 MT2063_REG_FIFFC,
3604 &state->reg[MT2063_REG_FIFFC], 1);
3605 if (status < 0)
3606 return status;
3607
3608 /* Read back all the registers from the tuner */
3609 status = mt2063_read(state,
3610 MT2063_REG_PART_REV,
3611 state->reg, MT2063_REG_END_REGS);
3612 if (status < 0)
3613 return status;
3614
3615 /* Initialize the tuner state. */
3616 state->tuner_id = state->reg[MT2063_REG_PART_REV];
3617 state->AS_Data.f_ref = MT2063_REF_FREQ;
3618 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
3619 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
3620 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
3621 state->AS_Data.f_out = 43750000UL;
3622 state->AS_Data.f_out_bw = 6750000UL;
3623 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
3624 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
3625 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
3626 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
3627 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
3628 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
3629 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
3630 state->AS_Data.f_LO1 = 2181000000UL;
3631 state->AS_Data.f_LO2 = 1486249786UL;
3632 state->f_IF1_actual = state->AS_Data.f_if1_Center;
3633 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
3634 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
3635 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
3636 state->num_regs = MT2063_REG_END_REGS;
3637 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
3638 state->ctfilt_sw = 0;
3639
3640 state->CTFiltMax[0] = 69230000;
3641 state->CTFiltMax[1] = 105770000;
3642 state->CTFiltMax[2] = 140350000;
3643 state->CTFiltMax[3] = 177110000;
3644 state->CTFiltMax[4] = 212860000;
3645 state->CTFiltMax[5] = 241130000;
3646 state->CTFiltMax[6] = 274370000;
3647 state->CTFiltMax[7] = 309820000;
3648 state->CTFiltMax[8] = 342450000;
3649 state->CTFiltMax[9] = 378870000;
3650 state->CTFiltMax[10] = 416210000;
3651 state->CTFiltMax[11] = 456500000;
3652 state->CTFiltMax[12] = 495790000;
3653 state->CTFiltMax[13] = 534530000;
3654 state->CTFiltMax[14] = 572610000;
3655 state->CTFiltMax[15] = 598970000;
3656 state->CTFiltMax[16] = 635910000;
3657 state->CTFiltMax[17] = 672130000;
3658 state->CTFiltMax[18] = 714840000;
3659 state->CTFiltMax[19] = 739660000;
3660 state->CTFiltMax[20] = 770410000;
3661 state->CTFiltMax[21] = 814660000;
3662 state->CTFiltMax[22] = 846950000;
3663 state->CTFiltMax[23] = 867820000;
3664 state->CTFiltMax[24] = 915980000;
3665 state->CTFiltMax[25] = 947450000;
3666 state->CTFiltMax[26] = 983110000;
3667 state->CTFiltMax[27] = 1021630000;
3668 state->CTFiltMax[28] = 1061870000;
3669 state->CTFiltMax[29] = 1098330000;
3670 state->CTFiltMax[30] = 1138990000;
3671
3672 /*
3673 ** Fetch the FCU osc value and use it and the fRef value to
3674 ** scale all of the Band Max values
3675 */
3676
3677 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
3678 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3679 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3680 if (status < 0)
3681 return status;
3682
3683 /* Read the ClearTune filter calibration value */
3684 status = mt2063_read(state, MT2063_REG_FIFFC,
3685 &state->reg[MT2063_REG_FIFFC], 1);
3686 if (status < 0)
3687 return status;
3688
3689 fcu_osc = state->reg[MT2063_REG_FIFFC];
3690
3691 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
3692 status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
3693 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
3694 if (status < 0)
3695 return status;
3696
3697 /* Adjust each of the values in the ClearTune filter cross-over table */
3698 for (i = 0; i < 31; i++)
3699 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
3700
3701 status = MT2063_SoftwareShutdown(state, 1);
3702 if (status < 0)
3703 return status;
3704 status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
3705 if (status < 0)
3706 return status;
3707
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003708 return 0;
3709}
3710
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003711static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3712{
3713 int rc = 0;
3714
3715 //get tuner lock status
3716
3717 return rc;
3718}
3719
3720static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003721 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003722{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003723 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003724
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003725 switch (param) {
3726 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003727 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003728 break;
3729 case DVBFE_TUNER_TUNERSTEP:
3730 break;
3731 case DVBFE_TUNER_IFFREQ:
3732 break;
3733 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003734 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003735 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003736 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003737 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003738 break;
3739 default:
3740 break;
3741 }
3742
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003743 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003744}
3745
3746static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003747 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003748{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003749 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003750 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003751
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003752 switch (param) {
3753 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003754 //set frequency
3755
3756 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003757 MT_Tune_atv(state,
3758 tunstate->frequency, tunstate->bandwidth,
3759 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003760
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003761 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003762 break;
3763 case DVBFE_TUNER_TUNERSTEP:
3764 break;
3765 case DVBFE_TUNER_IFFREQ:
3766 break;
3767 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003768 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003769 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003770 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003771 case DVBFE_TUNER_REFCLOCK:
3772
3773 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003774 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003775 status = MT2063_SoftwareShutdown(state, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003776 break;
3777 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
3778 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003779 MT2063_ClearPowerMaskBits(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003780 MT2063_ALL_SD);
3781 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003782 default:
3783 break;
3784 }
3785
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003786 return (int)status;
3787}
3788
3789static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003790{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003791 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003792
3793 fe->tuner_priv = NULL;
3794 kfree(state);
3795
3796 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003797}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003798
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003799static struct dvb_tuner_ops mt2063_ops = {
3800 .info = {
3801 .name = "MT2063 Silicon Tuner",
3802 .frequency_min = 45000000,
3803 .frequency_max = 850000000,
3804 .frequency_step = 0,
3805 },
3806
3807 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003808 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003809 .get_status = mt2063_get_status,
3810 .get_state = mt2063_get_state,
3811 .set_state = mt2063_set_state,
3812 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003813};
3814
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003815struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3816 struct mt2063_config *config,
3817 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003818{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003819 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003820
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003821 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003822 if (state == NULL)
3823 goto error;
3824
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003825 state->config = config;
3826 state->i2c = i2c;
3827 state->frontend = fe;
3828 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003829 fe->tuner_priv = state;
3830 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003831
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003832 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003833 return fe;
3834
3835error:
3836 kfree(state);
3837 return NULL;
3838}
3839
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003840EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003841MODULE_PARM_DESC(verbose, "Set Verbosity level");
3842
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003843MODULE_AUTHOR("Henry");
3844MODULE_DESCRIPTION("MT2063 Silicon tuner");
3845MODULE_LICENSE("GPL");