blob: 10116356f3043eaec2ce99a88168aa15a1b49b53 [file] [log] [blame]
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001#include <linux/init.h>
2#include <linux/kernel.h>
3#include <linux/module.h>
4#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03005
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006#include "mt2063.h"
7
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03008static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03009module_param(verbose, int, 0644);
10
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030011/* Internal structures and types */
12
Mauro Carvalho Chehab065719a2011-07-20 22:45:06 -030013/* FIXME: we probably don't need these new FE get/set property types for tuner */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030014#define DVBFE_TUNER_OPEN 99
15#define DVBFE_TUNER_SOFTWARE_SHUTDOWN 100
16#define DVBFE_TUNER_CLEAR_POWER_MASKBITS 101
17
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030018/* FIXME: Those two error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030019/* Error: Upconverter PLL is not locked */
20#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030021/* Error: Downconverter PLL is not locked */
22#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030023
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030024/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030025#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030026
27/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
28#define MT2063_SPUR_CNT_MASK (0x001f0000)
29#define MT2063_SPUR_SHIFT (16)
30
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030031/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
32#define MT2063_UPC_RANGE (0x04000000)
33
34/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
35#define MT2063_DNC_RANGE (0x08000000)
36
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030037/*
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030038 * Data Types
39 */
40
41/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030042 * Constant defining the version of the following structure
43 * and therefore the API for this code.
44 *
45 * When compiling the tuner driver, the preprocessor will
46 * check against this version number to make sure that
47 * it matches the version that the tuner driver knows about.
48 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030049
50/* DECT Frequency Avoidance */
51#define MT2063_DECT_AVOID_US_FREQS 0x00000001
52
53#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
54
55#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
56
57#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
58
59enum MT2063_DECT_Avoid_Type {
60 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
61 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
62 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
63 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
64};
65
66#define MT2063_MAX_ZONES 48
67
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030068struct MT2063_ExclZone_t {
69 u32 min_;
70 u32 max_;
71 struct MT2063_ExclZone_t *next_;
72};
73
74/*
75 * Structure of data needed for Spur Avoidance
76 */
77struct MT2063_AvoidSpursData_t {
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030078 u32 f_ref;
79 u32 f_in;
80 u32 f_LO1;
81 u32 f_if1_Center;
82 u32 f_if1_Request;
83 u32 f_if1_bw;
84 u32 f_LO2;
85 u32 f_out;
86 u32 f_out_bw;
87 u32 f_LO1_Step;
88 u32 f_LO2_Step;
89 u32 f_LO1_FracN_Avoid;
90 u32 f_LO2_FracN_Avoid;
91 u32 f_zif_bw;
92 u32 f_min_LO_Separation;
93 u32 maxH1;
94 u32 maxH2;
95 enum MT2063_DECT_Avoid_Type avoidDECT;
96 u32 bSpurPresent;
97 u32 bSpurAvoided;
98 u32 nSpursFound;
99 u32 nZones;
100 struct MT2063_ExclZone_t *freeZones;
101 struct MT2063_ExclZone_t *usedZones;
102 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
103};
104
105/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300106 * Parameter for function MT2063_SetPowerMask that specifies the power down
107 * of various sections of the MT2063.
108 */
109enum MT2063_Mask_Bits {
110 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
111 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
112 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
113 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
114 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
115 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
116 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
117 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
118 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
119 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
120 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
121 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
122 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
123 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
124 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
125};
126
127/*
128 * Parameter for function MT2063_GetParam & MT2063_SetParam that
129 * specifies the tuning algorithm parameter to be read/written.
130 */
131enum MT2063_Param {
132 /* tuner address set by MT2063_Open() */
133 MT2063_IC_ADDR,
134
135 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
136 MT2063_MAX_OPEN,
137
138 /* current number of open MT2063 tuners set by MT2063_Open() */
139 MT2063_NUM_OPEN,
140
141 /* crystal frequency (default: 16000000 Hz) */
142 MT2063_SRO_FREQ,
143
144 /* min tuning step size (default: 50000 Hz) */
145 MT2063_STEPSIZE,
146
147 /* input center frequency set by MT2063_Tune() */
148 MT2063_INPUT_FREQ,
149
150 /* LO1 Frequency set by MT2063_Tune() */
151 MT2063_LO1_FREQ,
152
153 /* LO1 minimum step size (default: 250000 Hz) */
154 MT2063_LO1_STEPSIZE,
155
156 /* LO1 FracN keep-out region (default: 999999 Hz) */
157 MT2063_LO1_FRACN_AVOID_PARAM,
158
159 /* Current 1st IF in use set by MT2063_Tune() */
160 MT2063_IF1_ACTUAL,
161
162 /* Requested 1st IF set by MT2063_Tune() */
163 MT2063_IF1_REQUEST,
164
165 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
166 MT2063_IF1_CENTER,
167
168 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
169 MT2063_IF1_BW,
170
171 /* zero-IF bandwidth (default: 2000000 Hz) */
172 MT2063_ZIF_BW,
173
174 /* LO2 Frequency set by MT2063_Tune() */
175 MT2063_LO2_FREQ,
176
177 /* LO2 minimum step size (default: 50000 Hz) */
178 MT2063_LO2_STEPSIZE,
179
180 /* LO2 FracN keep-out region (default: 374999 Hz) */
181 MT2063_LO2_FRACN_AVOID,
182
183 /* output center frequency set by MT2063_Tune() */
184 MT2063_OUTPUT_FREQ,
185
186 /* output bandwidth set by MT2063_Tune() */
187 MT2063_OUTPUT_BW,
188
189 /* min inter-tuner LO separation (default: 1000000 Hz) */
190 MT2063_LO_SEPARATION,
191
192 /* ID of avoid-spurs algorithm in use compile-time constant */
193 MT2063_AS_ALG,
194
195 /* max # of intra-tuner harmonics (default: 15) */
196 MT2063_MAX_HARM1,
197
198 /* max # of inter-tuner harmonics (default: 7) */
199 MT2063_MAX_HARM2,
200
201 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
202 MT2063_EXCL_ZONES,
203
204 /* # of spurs found/avoided set by MT2063_Tune() */
205 MT2063_NUM_SPURS,
206
207 /* >0 spurs avoided set by MT2063_Tune() */
208 MT2063_SPUR_AVOIDED,
209
210 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
211 MT2063_SPUR_PRESENT,
212
213 /* Receiver Mode for some parameters. 1 is DVB-T */
214 MT2063_RCVR_MODE,
215
216 /* directly set LNA attenuation, parameter is value to set */
217 MT2063_ACLNA,
218
219 /* maximum LNA attenuation, parameter is value to set */
220 MT2063_ACLNA_MAX,
221
222 /* directly set ATN attenuation. Paremeter is value to set. */
223 MT2063_ACRF,
224
225 /* maxium ATN attenuation. Paremeter is value to set. */
226 MT2063_ACRF_MAX,
227
228 /* directly set FIF attenuation. Paremeter is value to set. */
229 MT2063_ACFIF,
230
231 /* maxium FIF attenuation. Paremeter is value to set. */
232 MT2063_ACFIF_MAX,
233
234 /* LNA Rin */
235 MT2063_LNA_RIN,
236
237 /* Power Detector LNA level target */
238 MT2063_LNA_TGT,
239
240 /* Power Detector 1 level */
241 MT2063_PD1,
242
243 /* Power Detector 1 level target */
244 MT2063_PD1_TGT,
245
246 /* Power Detector 2 level */
247 MT2063_PD2,
248
249 /* Power Detector 2 level target */
250 MT2063_PD2_TGT,
251
252 /* Selects, which DNC is activ */
253 MT2063_DNC_OUTPUT_ENABLE,
254
255 /* VGA gain code */
256 MT2063_VGAGC,
257
258 /* VGA bias current */
259 MT2063_VGAOI,
260
261 /* TAGC, determins the speed of the AGC */
262 MT2063_TAGC,
263
264 /* AMP gain code */
265 MT2063_AMPGC,
266
267 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
268 MT2063_AVOID_DECT,
269
270 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
271 MT2063_CTFILT_SW,
272
273 MT2063_EOP /* last entry in enumerated list */
274};
275
276/*
277 * Parameter for selecting tuner mode
278 */
279enum MT2063_RCVR_MODES {
280 MT2063_CABLE_QAM = 0, /* Digital cable */
281 MT2063_CABLE_ANALOG, /* Analog cable */
282 MT2063_OFFAIR_COFDM, /* Digital offair */
283 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
284 MT2063_OFFAIR_ANALOG, /* Analog offair */
285 MT2063_OFFAIR_8VSB, /* Analog offair */
286 MT2063_NUM_RCVR_MODES
287};
288
289/*
290 * Possible values for MT2063_DNC_OUTPUT
291 */
292enum MT2063_DNC_Output_Enable {
293 MT2063_DNC_NONE = 0,
294 MT2063_DNC_1,
295 MT2063_DNC_2,
296 MT2063_DNC_BOTH
297};
298
299/*
300** Two-wire serial bus subaddresses of the tuner registers.
301** Also known as the tuner's register addresses.
302*/
303enum MT2063_Register_Offsets {
304 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
305 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
306 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
307 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
308 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
309 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
310 MT2063_REG_RSVD_06, /* 0x06: Reserved */
311 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
312 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
313 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
314 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
315 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
316 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
317 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
318 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
319 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
320 MT2063_REG_RSVD_10, /* 0x10: Reserved */
321 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
322 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
323 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
324 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
325 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
326 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
327 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
328 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
329 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
330 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
331 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
332 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
333 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
334 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
335 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
336 MT2063_REG_RSVD_20, /* 0x20: Reserved */
337 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
338 MT2063_REG_RSVD_22, /* 0x22: Reserved */
339 MT2063_REG_RSVD_23, /* 0x23: Reserved */
340 MT2063_REG_RSVD_24, /* 0x24: Reserved */
341 MT2063_REG_RSVD_25, /* 0x25: Reserved */
342 MT2063_REG_RSVD_26, /* 0x26: Reserved */
343 MT2063_REG_RSVD_27, /* 0x27: Reserved */
344 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
345 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
346 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
347 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
348 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
349 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
350 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
351 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
352 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
353 MT2063_REG_RSVD_31, /* 0x31: Reserved */
354 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
355 MT2063_REG_RSVD_33, /* 0x33: Reserved */
356 MT2063_REG_RSVD_34, /* 0x34: Reserved */
357 MT2063_REG_RSVD_35, /* 0x35: Reserved */
358 MT2063_REG_RSVD_36, /* 0x36: Reserved */
359 MT2063_REG_RSVD_37, /* 0x37: Reserved */
360 MT2063_REG_RSVD_38, /* 0x38: Reserved */
361 MT2063_REG_RSVD_39, /* 0x39: Reserved */
362 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
363 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
364 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
365 MT2063_REG_END_REGS
366};
367
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300368enum MTTune_atv_standard {
369 MTTUNEA_UNKNOWN = 0,
370 MTTUNEA_PAL_B,
371 MTTUNEA_PAL_G,
372 MTTUNEA_PAL_I,
373 MTTUNEA_PAL_L,
374 MTTUNEA_PAL_MN,
375 MTTUNEA_PAL_DK,
376 MTTUNEA_DIGITAL,
377 MTTUNEA_FMRADIO,
378 MTTUNEA_DVBC,
379 MTTUNEA_DVBT
380};
381
382
383struct mt2063_state {
384 struct i2c_adapter *i2c;
385
386 const struct mt2063_config *config;
387 struct dvb_tuner_ops ops;
388 struct dvb_frontend *frontend;
389 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300390 bool MT2063_init;
391
392 enum MTTune_atv_standard tv_type;
393 u32 frequency;
394 u32 srate;
395 u32 bandwidth;
396 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300397
398 u32 tuner_id;
399 struct MT2063_AvoidSpursData_t AS_Data;
400 u32 f_IF1_actual;
401 u32 rcvr_mode;
402 u32 ctfilt_sw;
403 u32 CTFiltMax[31];
404 u32 num_regs;
405 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300406};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300407
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300408/* Prototypes */
409static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
410 u32 f_min, u32 f_max);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300411static u32 MT2063_ReInit(struct mt2063_state *state);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -0300412static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val);
413static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue);
414static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val);
415static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300416 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300417
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300418/*****************/
419/* From drivers/media/common/tuners/mt2063_cfg.h */
420
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300421unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300422 u32 bw_in,
423 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300424{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300425 struct dvb_frontend_ops *frontend_ops = NULL;
426 struct dvb_tuner_ops *tuner_ops = NULL;
427 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300428 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300429 int err = 0;
430
431 t_state.frequency = f_in;
432 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300433 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300434 if (&fe->ops)
435 frontend_ops = &fe->ops;
436 if (&frontend_ops->tuner_ops)
437 tuner_ops = &frontend_ops->tuner_ops;
438 if (tuner_ops->set_state) {
439 if ((err =
440 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
441 &t_state)) < 0) {
442 printk("%s: Invalid parameter\n", __func__);
443 return err;
444 }
445 }
446
447 return err;
448}
449
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300450unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300451{
452 struct dvb_frontend_ops *frontend_ops = &fe->ops;
453 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
454 struct tuner_state t_state;
455 int err = 0;
456
457 if (&fe->ops)
458 frontend_ops = &fe->ops;
459 if (&frontend_ops->tuner_ops)
460 tuner_ops = &frontend_ops->tuner_ops;
461 if (tuner_ops->get_state) {
462 if ((err =
463 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
464 &t_state)) < 0) {
465 printk("%s: Invalid parameter\n", __func__);
466 return err;
467 }
468 }
469 return err;
470}
471
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300472unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300473{
474 struct dvb_frontend_ops *frontend_ops = &fe->ops;
475 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
476 struct tuner_state t_state;
477 int err = 0;
478
479 if (&fe->ops)
480 frontend_ops = &fe->ops;
481 if (&frontend_ops->tuner_ops)
482 tuner_ops = &frontend_ops->tuner_ops;
483 if (tuner_ops->set_state) {
484 if ((err =
485 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
486 &t_state)) < 0) {
487 printk("%s: Invalid parameter\n", __func__);
488 return err;
489 }
490 }
491
492 return err;
493}
494
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300495unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300496{
497 struct dvb_frontend_ops *frontend_ops = &fe->ops;
498 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
499 struct tuner_state t_state;
500 int err = 0;
501
502 if (&fe->ops)
503 frontend_ops = &fe->ops;
504 if (&frontend_ops->tuner_ops)
505 tuner_ops = &frontend_ops->tuner_ops;
506 if (tuner_ops->set_state) {
507 if ((err =
508 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
509 &t_state)) < 0) {
510 printk("%s: Invalid parameter\n", __func__);
511 return err;
512 }
513 }
514
515 return err;
516}
517
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300518unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300519{
520 struct dvb_frontend_ops *frontend_ops = &fe->ops;
521 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
522 struct tuner_state t_state;
523 int err = 0;
524
525 if (&fe->ops)
526 frontend_ops = &fe->ops;
527 if (&frontend_ops->tuner_ops)
528 tuner_ops = &frontend_ops->tuner_ops;
529 if (tuner_ops->set_state) {
530 if ((err =
531 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
532 &t_state)) < 0) {
533 printk("%s: Invalid parameter\n", __func__);
534 return err;
535 }
536 }
537
538 return err;
539}
540
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300541/*
542 * mt2063_write - Write data into the I2C bus
543 */
544static u32 mt2063_write(struct mt2063_state *state,
545 u8 reg, u8 *data, u32 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300546{
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300547 struct dvb_frontend *fe = state->frontend;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300548 int ret;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300549 u8 buf[60];
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300550 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300551 .addr = state->config->tuner_address,
552 .flags = 0,
553 .buf = buf,
554 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300555 };
556
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300557 msg.buf[0] = reg;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300558 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300559
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300560 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300561 ret = i2c_transfer(state->i2c, &msg, 1);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300562 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300563
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300564 if (ret < 0)
565 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300566
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300567 return ret;
568}
569
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300570/*
571 * mt2063_read - Read data from the I2C bus
572 */
573static u32 mt2063_read(struct mt2063_state *state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300574 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300575{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300576 u32 status = 0; /* Status to be returned */
577 struct dvb_frontend *fe = state->frontend;
578 u32 i = 0;
579
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300580 fe->ops.i2c_gate_ctrl(fe, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300581
582 for (i = 0; i < cnt; i++) {
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300583 int ret;
584 u8 b0[] = { subAddress + i };
585 struct i2c_msg msg[] = {
586 {
587 .addr = state->config->tuner_address,
588 .flags = I2C_M_RD,
589 .buf = b0,
590 .len = 1
591 }, {
592 .addr = state->config->tuner_address,
593 .flags = I2C_M_RD,
594 .buf = pData + 1,
595 .len = 1
596 }
597 };
598
599 ret = i2c_transfer(state->i2c, msg, 2);
600 if (ret < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300601 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300602 }
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -0300603 fe->ops.i2c_gate_ctrl(fe, 0);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300604 return (status);
605}
606
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300607/*
608 * FIXME: Is this really needed?
609 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300610static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300611{
612 /*
613 ** ToDo: Add code here to implement a OS blocking
614 ** for a period of "nMinDelayTime" milliseconds.
615 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300616 msleep(10);
617
618 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300619}
620
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -0300621/*
622 * Microtune spur avoidance
623 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300624
625/* Implement ceiling, floor functions. */
626#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300627#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300628
629struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300630 s32 min_;
631 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300632};
633
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300634/*
635** Reset all exclusion zones.
636** Add zones to protect the PLL FracN regions near zero
637**
638** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
639** frequencies into MT_ResetExclZones().
640*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300641static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300642{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300643 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300644
645 pAS_Info->nZones = 0; /* this clears the used list */
646 pAS_Info->usedZones = NULL; /* reset ptr */
647 pAS_Info->freeZones = NULL; /* reset ptr */
648
649 center =
650 pAS_Info->f_ref *
651 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
652 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
653 while (center <
654 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
655 pAS_Info->f_LO1_FracN_Avoid) {
656 /* Exclude LO1 FracN */
657 MT2063_AddExclZone(pAS_Info,
658 center - pAS_Info->f_LO1_FracN_Avoid,
659 center - 1);
660 MT2063_AddExclZone(pAS_Info, center + 1,
661 center + pAS_Info->f_LO1_FracN_Avoid);
662 center += pAS_Info->f_ref;
663 }
664
665 center =
666 pAS_Info->f_ref *
667 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
668 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
669 while (center <
670 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
671 pAS_Info->f_LO2_FracN_Avoid) {
672 /* Exclude LO2 FracN */
673 MT2063_AddExclZone(pAS_Info,
674 center - pAS_Info->f_LO2_FracN_Avoid,
675 center - 1);
676 MT2063_AddExclZone(pAS_Info, center + 1,
677 center + pAS_Info->f_LO2_FracN_Avoid);
678 center += pAS_Info->f_ref;
679 }
680
681 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
682 /* Exclude LO1 values that conflict with DECT channels */
683 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
684 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
685 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
686 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
687 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
688 }
689
690 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
691 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
692 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
693 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
694 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
695 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
696 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
697 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
698 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
699 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
700 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
701 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300702}
703
704static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
705 *pAS_Info,
706 struct MT2063_ExclZone_t *pPrevNode)
707{
708 struct MT2063_ExclZone_t *pNode;
709 /* Check for a node in the free list */
710 if (pAS_Info->freeZones != NULL) {
711 /* Use one from the free list */
712 pNode = pAS_Info->freeZones;
713 pAS_Info->freeZones = pNode->next_;
714 } else {
715 /* Grab a node from the array */
716 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
717 }
718
719 if (pPrevNode != NULL) {
720 pNode->next_ = pPrevNode->next_;
721 pPrevNode->next_ = pNode;
722 } else { /* insert at the beginning of the list */
723
724 pNode->next_ = pAS_Info->usedZones;
725 pAS_Info->usedZones = pNode;
726 }
727
728 pAS_Info->nZones++;
729 return pNode;
730}
731
732static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
733 *pAS_Info,
734 struct MT2063_ExclZone_t *pPrevNode,
735 struct MT2063_ExclZone_t
736 *pNodeToRemove)
737{
738 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
739
740 /* Make previous node point to the subsequent node */
741 if (pPrevNode != NULL)
742 pPrevNode->next_ = pNext;
743
744 /* Add pNodeToRemove to the beginning of the freeZones */
745 pNodeToRemove->next_ = pAS_Info->freeZones;
746 pAS_Info->freeZones = pNodeToRemove;
747
748 /* Decrement node count */
749 pAS_Info->nZones--;
750
751 return pNext;
752}
753
754/*****************************************************************************
755**
756** Name: MT_AddExclZone
757**
758** Description: Add (and merge) an exclusion zone into the list.
759** If the range (f_min, f_max) is totally outside the
760** 1st IF BW, ignore the entry.
761** If the range (f_min, f_max) is negative, ignore the entry.
762**
763** Revision History:
764**
765** SCR Date Author Description
766** -------------------------------------------------------------------------
767** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
768** (f_min, f_max) < 0, ignore the entry.
769**
770*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300771static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300772 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300773{
774 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
775 struct MT2063_ExclZone_t *pPrev = NULL;
776 struct MT2063_ExclZone_t *pNext = NULL;
777
778 /* Check to see if this overlaps the 1st IF filter */
779 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
780 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
781 && (f_min < f_max)) {
782 /*
783 ** 1 2 3 4 5 6
784 **
785 ** New entry: |---| |--| |--| |-| |---| |--|
786 ** or or or or or
787 ** Existing: |--| |--| |--| |---| |-| |--|
788 */
789
790 /* Check for our place in the list */
791 while ((pNode != NULL) && (pNode->max_ < f_min)) {
792 pPrev = pNode;
793 pNode = pNode->next_;
794 }
795
796 if ((pNode != NULL) && (pNode->min_ < f_max)) {
797 /* Combine me with pNode */
798 if (f_min < pNode->min_)
799 pNode->min_ = f_min;
800 if (f_max > pNode->max_)
801 pNode->max_ = f_max;
802 } else {
803 pNode = InsertNode(pAS_Info, pPrev);
804 pNode->min_ = f_min;
805 pNode->max_ = f_max;
806 }
807
808 /* Look for merging possibilities */
809 pNext = pNode->next_;
810 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
811 if (pNext->max_ > pNode->max_)
812 pNode->max_ = pNext->max_;
813 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
814 }
815 }
816}
817
818/*****************************************************************************
819**
820** Name: MT_ChooseFirstIF
821**
822** Description: Choose the best available 1st IF
823** If f_Desired is not excluded, choose that first.
824** Otherwise, return the value closest to f_Center that is
825** not excluded
826**
827** Revision History:
828**
829** SCR Date Author Description
830** -------------------------------------------------------------------------
831** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
832** tuner DLL.
833** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
834** Added logic to force f_Center within 1/2 f_Step.
835**
836*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300837static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300838{
839 /*
840 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
841 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
842 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
843 ** However, the sum must be.
844 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300845 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300846 pAS_Info->f_LO1_Step *
847 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
848 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
849 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300850 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300851 (pAS_Info->f_LO1_Step >
852 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
853 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300854 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300855
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300856 s32 i;
857 s32 j = 0;
858 u32 bDesiredExcluded = 0;
859 u32 bZeroExcluded = 0;
860 s32 tmpMin, tmpMax;
861 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300862 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
863 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
864
865 if (pAS_Info->nZones == 0)
866 return f_Desired;
867
868 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
869 if (pAS_Info->f_if1_Center > f_Desired)
870 f_Center =
871 f_Desired +
872 f_Step *
873 ((pAS_Info->f_if1_Center - f_Desired +
874 f_Step / 2) / f_Step);
875 else
876 f_Center =
877 f_Desired -
878 f_Step *
879 ((f_Desired - pAS_Info->f_if1_Center +
880 f_Step / 2) / f_Step);
881
882 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300883 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300884 // return 0;
885
886 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
887 while (pNode != NULL) {
888 /* floor function */
889 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300890 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300891
892 /* ceil function */
893 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300894 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300895
896 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
897 bDesiredExcluded = 1;
898
899 if ((tmpMin < 0) && (tmpMax > 0))
900 bZeroExcluded = 1;
901
902 /* See if this zone overlaps the previous */
903 if ((j > 0) && (tmpMin < zones[j - 1].max_))
904 zones[j - 1].max_ = tmpMax;
905 else {
906 /* Add new zone */
907 //assert(j<MT2063_MAX_ZONES);
908 //if (j>=MT2063_MAX_ZONES)
909 //break;
910
911 zones[j].min_ = tmpMin;
912 zones[j].max_ = tmpMax;
913 j++;
914 }
915 pNode = pNode->next_;
916 }
917
918 /*
919 ** If the desired is okay, return with it
920 */
921 if (bDesiredExcluded == 0)
922 return f_Desired;
923
924 /*
925 ** If the desired is excluded and the center is okay, return with it
926 */
927 if (bZeroExcluded == 0)
928 return f_Center;
929
930 /* Find the value closest to 0 (f_Center) */
931 bestDiff = zones[0].min_;
932 for (i = 0; i < j; i++) {
933 if (abs(zones[i].min_) < abs(bestDiff))
934 bestDiff = zones[i].min_;
935 if (abs(zones[i].max_) < abs(bestDiff))
936 bestDiff = zones[i].max_;
937 }
938
939 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300940 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300941
942 return f_Center + (bestDiff * f_Step);
943}
944
945/****************************************************************************
946**
947** Name: gcd
948**
949** Description: Uses Euclid's algorithm
950**
951** Parameters: u, v - unsigned values whose GCD is desired.
952**
953** Global: None
954**
955** Returns: greatest common divisor of u and v, if either value
956** is 0, the other value is returned as the result.
957**
958** Dependencies: None.
959**
960** Revision History:
961**
962** SCR Date Author Description
963** -------------------------------------------------------------------------
964** N/A 06-01-2004 JWS Original
965** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
966** unsigned numbers.
967**
968****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300969static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300970{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300971 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300972
973 while (v != 0) {
974 r = u % v;
975 u = v;
976 v = r;
977 }
978
979 return u;
980}
981
982/****************************************************************************
983**
984** Name: umax
985**
986** Description: Implements a simple maximum function for unsigned numbers.
987** Implemented as a function rather than a macro to avoid
988** multiple evaluation of the calling parameters.
989**
990** Parameters: a, b - Values to be compared
991**
992** Global: None
993**
994** Returns: larger of the input values.
995**
996** Dependencies: None.
997**
998** Revision History:
999**
1000** SCR Date Author Description
1001** -------------------------------------------------------------------------
1002** N/A 06-02-2004 JWS Original
1003**
1004****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001005static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001006{
1007 return (a >= b) ? a : b;
1008}
1009
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001010/****************************************************************************
1011**
1012** Name: IsSpurInBand
1013**
1014** Description: Checks to see if a spur will be present within the IF's
1015** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1016**
1017** ma mb mc md
1018** <--+-+-+-------------------+-------------------+-+-+-->
1019** | ^ 0 ^ |
1020** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1021** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1022**
1023** Note that some equations are doubled to prevent round-off
1024** problems when calculating fIFBW/2
1025**
1026** Parameters: pAS_Info - Avoid Spurs information block
1027** fm - If spur, amount f_IF1 has to move negative
1028** fp - If spur, amount f_IF1 has to move positive
1029**
1030** Global: None
1031**
1032** Returns: 1 if an LO spur would be present, otherwise 0.
1033**
1034** Dependencies: None.
1035**
1036** Revision History:
1037**
1038** SCR Date Author Description
1039** -------------------------------------------------------------------------
1040** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1041**
1042****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001043static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1044 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001045{
1046 /*
1047 ** Calculate LO frequency settings.
1048 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001049 u32 n, n0;
1050 const u32 f_LO1 = pAS_Info->f_LO1;
1051 const u32 f_LO2 = pAS_Info->f_LO2;
1052 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1053 const u32 c = d - pAS_Info->f_out_bw;
1054 const u32 f = pAS_Info->f_zif_bw / 2;
Mauro Carvalho Chehabd0dcc2d2011-07-21 02:30:19 -03001055 const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001056 s32 f_nsLO1, f_nsLO2;
1057 s32 f_Spur;
1058 u32 ma, mb, mc, md, me, mf;
1059 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001060 *fm = 0;
1061
1062 /*
1063 ** For each edge (d, c & f), calculate a scale, based on the gcd
1064 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1065 ** gcd-based scale factor or f_Scale.
1066 */
1067 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001068 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001069 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001070 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001071 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001072 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001073 hgfs = gf_Scale / 2;
1074
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001075 n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001076
1077 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1078 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1079 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1080 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1081
1082 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1083 if (md >= pAS_Info->maxH1)
1084 break;
1085
1086 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1087 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1088
1089 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1090 if (md == ma)
1091 continue;
1092
1093 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1094 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1095 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001096 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1097 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001098 f_Spur =
1099 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1100 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1101
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001102 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1103 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001104 return 1;
1105 }
1106
1107 /* Location of Zero-IF-spur to be checked */
1108 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1109 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1110 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1111 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1112 if (me != mf) {
1113 f_nsLO1 = n * (f_LO1 / gf_Scale);
1114 f_nsLO2 = me * (f_LO2 / gf_Scale);
1115 f_Spur =
1116 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1117 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1118
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001119 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1120 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001121 return 1;
1122 }
1123
1124 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1125 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1126 if (ma != mb) {
1127 f_nsLO1 = n * (f_LO1 / gc_Scale);
1128 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1129 f_Spur =
1130 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1131 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1132
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001133 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1134 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001135 return 1;
1136 }
1137 }
1138
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001139 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001140 return 0;
1141}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001142
1143/*****************************************************************************
1144**
1145** Name: MT_AvoidSpurs
1146**
1147** Description: Main entry point to avoid spurs.
1148** Checks for existing spurs in present LO1, LO2 freqs
1149** and if present, chooses spur-free LO1, LO2 combination
1150** that tunes the same input/output frequencies.
1151**
1152** Revision History:
1153**
1154** SCR Date Author Description
1155** -------------------------------------------------------------------------
1156** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1157**
1158*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001159static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001160{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001161 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001162 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001163 pAS_Info->bSpurAvoided = 0;
1164 pAS_Info->nSpursFound = 0;
1165
1166 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001167 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001168
1169 /*
1170 ** Avoid LO Generated Spurs
1171 **
1172 ** Make sure that have no LO-related spurs within the IF output
1173 ** bandwidth.
1174 **
1175 ** If there is an LO spur in this band, start at the current IF1 frequency
1176 ** and work out until we find a spur-free frequency or run up against the
1177 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1178 ** will be unchanged if a spur-free setting is not found.
1179 */
1180 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1181 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001182 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1183 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1184 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1185 u32 delta_IF1;
1186 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001187
1188 /*
1189 ** Spur was found, attempt to find a spur-free 1st IF
1190 */
1191 do {
1192 pAS_Info->nSpursFound++;
1193
1194 /* Raise f_IF1_upper, if needed */
1195 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1196
1197 /* Choose next IF1 that is closest to f_IF1_CENTER */
1198 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1199
1200 if (new_IF1 > zfIF1) {
1201 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1202 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1203 } else {
1204 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1205 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1206 }
1207 zfIF1 = new_IF1;
1208
1209 if (zfIF1 > pAS_Info->f_if1_Center)
1210 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1211 else
1212 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1213 }
1214 /*
1215 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1216 ** and there is a spur in the band (again)
1217 */
1218 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1219 pAS_Info->f_if1_bw)
1220 && (pAS_Info->bSpurPresent =
1221 IsSpurInBand(pAS_Info, &fm, &fp)));
1222
1223 /*
1224 ** Use the LO-spur free values found. If the search went all the way to
1225 ** the 1st IF band edge and always found spurs, just leave the original
1226 ** choice. It's as "good" as any other.
1227 */
1228 if (pAS_Info->bSpurPresent == 1) {
1229 status |= MT2063_SPUR_PRESENT_ERR;
1230 pAS_Info->f_LO1 = zfLO1;
1231 pAS_Info->f_LO2 = zfLO2;
1232 } else
1233 pAS_Info->bSpurAvoided = 1;
1234 }
1235
1236 status |=
1237 ((pAS_Info->
1238 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1239
1240 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001241}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001242
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001243//end of mt2063_spuravoid.c
1244//=================================================================
1245//#################################################################
1246//=================================================================
1247
1248/*
1249** The expected version of MT_AvoidSpursData_t
1250** If the version is different, an updated file is needed from Microtune
1251*/
1252/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001253
1254typedef enum {
1255 MT2063_SET_ATTEN,
1256 MT2063_INCR_ATTEN,
1257 MT2063_DECR_ATTEN
1258} MT2063_ATTEN_CNTL_MODE;
1259
1260//#define TUNER_MT2063_OPTIMIZATION
1261/*
1262** Constants used by the tuning algorithm
1263*/
1264#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1265#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1266#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1267#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1268#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1269#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1270#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1271#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1272#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1273#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1274#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1275#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1276#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1277#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1278#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1279#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1280#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1281#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1282
1283/*
1284** Define the supported Part/Rev codes for the MT2063
1285*/
1286#define MT2063_B0 (0x9B)
1287#define MT2063_B1 (0x9C)
1288#define MT2063_B2 (0x9D)
1289#define MT2063_B3 (0x9E)
1290
1291/*
1292** The number of Tuner Registers
1293*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001294static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001295
1296#define USE_GLOBAL_TUNER 0
1297
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001298static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001299static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001300
1301/*
1302** Constants for setting receiver modes.
1303** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1304** (DNC1GC & DNC2GC are the values, which are used, when the specific
1305** DNC Output is selected, the other is always off)
1306**
1307** If PAL-L or L' is received, set:
1308** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1309**
1310** --------------+----------------------------------------------
1311** Mode 0 : | MT2063_CABLE_QAM
1312** Mode 1 : | MT2063_CABLE_ANALOG
1313** Mode 2 : | MT2063_OFFAIR_COFDM
1314** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1315** Mode 4 : | MT2063_OFFAIR_ANALOG
1316** Mode 5 : | MT2063_OFFAIR_8VSB
1317** --------------+----+----+----+----+-----+-----+--------------
1318** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1319** --------------+----+----+----+----+-----+-----+
1320**
1321**
1322*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001323static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1324static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1325static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1326static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1327static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1328static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1329static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1330static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1331static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1332static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1333static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1334static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1335static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1336static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001337
1338/*
1339** Local Function Prototypes - not available for external access.
1340*/
1341
1342/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001343static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1344 u32 f_LO_Step, u32 f_Ref);
1345static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1346 u32 f_LO_Step, u32 f_Ref);
1347static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1348 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001349
1350/******************************************************************************
1351**
1352** Name: MT2063_Open
1353**
1354** Description: Initialize the tuner's register values.
1355**
1356** Parameters: MT2063_Addr - Serial bus address of the tuner.
1357** hMT2063 - Tuner handle passed back.
1358** hUserData - User-defined data, if needed for the
1359** MT_ReadSub() & MT_WriteSub functions.
1360**
1361** Returns: status:
1362** MT_OK - No errors
1363** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1364** MT_TUNER_INIT_ERR - Tuner initialization failed
1365** MT_COMM_ERR - Serial bus communications error
1366** MT_ARG_NULL - Null pointer argument passed
1367** MT_TUNER_CNT_ERR - Too many tuners open
1368**
1369** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1370** MT_WriteSub - Write byte(s) of data to the two-wire bus
1371**
1372** Revision History:
1373**
1374** SCR Date Author Description
1375** -------------------------------------------------------------------------
1376** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1377**
1378******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001379static u32 MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001380{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001381 u32 status; /* Status to be returned. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001382 struct mt2063_state *state = fe->tuner_priv;
1383
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001384 state->rcvr_mode = MT2063_CABLE_QAM;
1385 if (state->MT2063_init != false) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001386 status = MT2063_ReInit(state);
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001387 if (status < 0)
1388 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001389 }
1390
Mauro Carvalho Chehabe930b3a2011-07-21 03:02:16 -03001391 state->MT2063_init = true;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001392 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001393}
1394
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001395/****************************************************************************
1396**
1397** Name: MT2063_GetLocked
1398**
1399** Description: Checks to see if LO1 and LO2 are locked.
1400**
1401** Parameters: h - Open handle to the tuner (from MT2063_Open).
1402**
1403** Returns: status:
1404** MT_OK - No errors
1405** MT_UPC_UNLOCK - Upconverter PLL unlocked
1406** MT_DNC_UNLOCK - Downconverter PLL unlocked
1407** MT_COMM_ERR - Serial bus communications error
1408** MT_INV_HANDLE - Invalid tuner handle
1409**
1410** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1411** MT_Sleep - Delay execution for x milliseconds
1412**
1413** Revision History:
1414**
1415** SCR Date Author Description
1416** -------------------------------------------------------------------------
1417** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1418**
1419****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001420static u32 MT2063_GetLocked(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001421{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001422 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1423 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1424 const u32 nMaxLoops = nMaxWait / nPollRate;
1425 const u8 LO1LK = 0x80;
1426 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001427 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001428 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001429
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001430 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001431 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001432 LO2LK = 0x40;
1433
1434 do {
1435 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001436 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001437 MT2063_REG_LO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001438 &state->reg[MT2063_REG_LO_STATUS], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001439
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001440 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001441 return (status);
1442
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001443 if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001444 (LO1LK | LO2LK)) {
1445 return (status);
1446 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001447 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001448 }
1449 while (++nDelays < nMaxLoops);
1450
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001451 if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001452 status |= MT2063_UPC_UNLOCK;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001453 if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001454 status |= MT2063_DNC_UNLOCK;
1455
1456 return (status);
1457}
1458
1459/****************************************************************************
1460**
1461** Name: MT2063_GetParam
1462**
1463** Description: Gets a tuning algorithm parameter.
1464**
1465** This function provides access to the internals of the
1466** tuning algorithm - mostly for testing purposes.
1467**
1468** Parameters: h - Tuner handle (returned by MT2063_Open)
1469** param - Tuning algorithm parameter
1470** (see enum MT2063_Param)
1471** pValue - ptr to returned value
1472**
1473** param Description
1474** ---------------------- --------------------------------
1475** MT2063_IC_ADDR Serial Bus address of this tuner
1476** MT2063_MAX_OPEN Max # of MT2063's allowed open
1477** MT2063_NUM_OPEN # of MT2063's open
1478** MT2063_SRO_FREQ crystal frequency
1479** MT2063_STEPSIZE minimum tuning step size
1480** MT2063_INPUT_FREQ input center frequency
1481** MT2063_LO1_FREQ LO1 Frequency
1482** MT2063_LO1_STEPSIZE LO1 minimum step size
1483** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1484** MT2063_IF1_ACTUAL Current 1st IF in use
1485** MT2063_IF1_REQUEST Requested 1st IF
1486** MT2063_IF1_CENTER Center of 1st IF SAW filter
1487** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1488** MT2063_ZIF_BW zero-IF bandwidth
1489** MT2063_LO2_FREQ LO2 Frequency
1490** MT2063_LO2_STEPSIZE LO2 minimum step size
1491** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1492** MT2063_OUTPUT_FREQ output center frequency
1493** MT2063_OUTPUT_BW output bandwidth
1494** MT2063_LO_SEPARATION min inter-tuner LO separation
1495** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1496** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1497** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1498** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1499** MT2063_NUM_SPURS # of spurs found/avoided
1500** MT2063_SPUR_AVOIDED >0 spurs avoided
1501** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1502** MT2063_RCVR_MODE Predefined modes.
1503** MT2063_ACLNA LNA attenuator gain code
1504** MT2063_ACRF RF attenuator gain code
1505** MT2063_ACFIF FIF attenuator gain code
1506** MT2063_ACLNA_MAX LNA attenuator limit
1507** MT2063_ACRF_MAX RF attenuator limit
1508** MT2063_ACFIF_MAX FIF attenuator limit
1509** MT2063_PD1 Actual value of PD1
1510** MT2063_PD2 Actual value of PD2
1511** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1512** MT2063_VGAGC VGA gain code
1513** MT2063_VGAOI VGA output current
1514** MT2063_TAGC TAGC setting
1515** MT2063_AMPGC AMP gain code
1516** MT2063_AVOID_DECT Avoid DECT Frequencies
1517** MT2063_CTFILT_SW Cleartune filter selection
1518**
1519** Usage: status |= MT2063_GetParam(hMT2063,
1520** MT2063_IF1_ACTUAL,
1521** &f_IF1_Actual);
1522**
1523** Returns: status:
1524** MT_OK - No errors
1525** MT_INV_HANDLE - Invalid tuner handle
1526** MT_ARG_NULL - Null pointer argument passed
1527** MT_ARG_RANGE - Invalid parameter requested
1528**
1529** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1530**
1531** See Also: MT2063_SetParam, MT2063_Open
1532**
1533** Revision History:
1534**
1535** SCR Date Author Description
1536** -------------------------------------------------------------------------
1537** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1538** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1539** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1540** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1541** in GetParam.
1542** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1543** Split SetParam up to ACLNA / ACLNA_MAX
1544** removed ACLNA_INRC/DECR (+RF & FIF)
1545** removed GCUAUTO / BYPATNDN/UP
1546** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1547** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1548** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1549**
1550****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001551static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001552{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001553 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001554 u32 Div;
1555 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001556
1557 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001558 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001559
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001560 switch (param) {
1561 /* Serial Bus address of this tuner */
1562 case MT2063_IC_ADDR:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001563 *pValue = state->config->tuner_address;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001564 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001565
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001566 /* Max # of MT2063's allowed to be open */
1567 case MT2063_MAX_OPEN:
1568 *pValue = nMT2063MaxTuners;
1569 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001570
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001571 /* # of MT2063's open */
1572 case MT2063_NUM_OPEN:
1573 *pValue = nMT2063OpenTuners;
1574 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001575
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001576 /* crystal frequency */
1577 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001578 *pValue = state->AS_Data.f_ref;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001579 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001580
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001581 /* minimum tuning step size */
1582 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001583 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001584 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001585
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001586 /* input center frequency */
1587 case MT2063_INPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001588 *pValue = state->AS_Data.f_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001589 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001590
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001591 /* LO1 Frequency */
1592 case MT2063_LO1_FREQ:
1593 {
1594 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1595 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001596 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001597 MT2063_REG_LO1C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001598 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001599 reg[MT2063_REG_LO1C_1], 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001600 Div = state->reg[MT2063_REG_LO1C_1];
1601 Num = state->reg[MT2063_REG_LO1C_2] & 0x3F;
1602 state->AS_Data.f_LO1 =
1603 (state->AS_Data.f_ref * Div) +
1604 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001605 f_ref, Num, 64);
1606 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001607 *pValue = state->AS_Data.f_LO1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001608 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001609
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001610 /* LO1 minimum step size */
1611 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001612 *pValue = state->AS_Data.f_LO1_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001613 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001614
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001615 /* LO1 FracN keep-out region */
1616 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001617 *pValue = state->AS_Data.f_LO1_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001618 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001619
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001620 /* Current 1st IF in use */
1621 case MT2063_IF1_ACTUAL:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001622 *pValue = state->f_IF1_actual;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001623 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001624
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001625 /* Requested 1st IF */
1626 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001627 *pValue = state->AS_Data.f_if1_Request;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001628 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001629
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001630 /* Center of 1st IF SAW filter */
1631 case MT2063_IF1_CENTER:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001632 *pValue = state->AS_Data.f_if1_Center;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001633 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001634
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001635 /* Bandwidth of 1st IF SAW filter */
1636 case MT2063_IF1_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001637 *pValue = state->AS_Data.f_if1_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001638 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001639
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001640 /* zero-IF bandwidth */
1641 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001642 *pValue = state->AS_Data.f_zif_bw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001643 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001644
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001645 /* LO2 Frequency */
1646 case MT2063_LO2_FREQ:
1647 {
1648 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1649 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001650 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001651 MT2063_REG_LO2C_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001652 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001653 reg[MT2063_REG_LO2C_1], 3);
1654 Div =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001655 (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001656 Num =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001657 ((state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001658 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001659 (state->
1660 reg[MT2063_REG_LO2C_2] << 4) | (state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001661 reg
1662 [MT2063_REG_LO2C_3]
1663 & 0x00F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001664 state->AS_Data.f_LO2 =
1665 (state->AS_Data.f_ref * Div) +
1666 MT2063_fLO_FractionalTerm(state->AS_Data.
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001667 f_ref, Num, 8191);
1668 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001669 *pValue = state->AS_Data.f_LO2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001670 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001671
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001672 /* LO2 minimum step size */
1673 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001674 *pValue = state->AS_Data.f_LO2_Step;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001675 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001676
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001677 /* LO2 FracN keep-out region */
1678 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001679 *pValue = state->AS_Data.f_LO2_FracN_Avoid;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001680 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001681
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001682 /* output center frequency */
1683 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001684 *pValue = state->AS_Data.f_out;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001685 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001686
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001687 /* output bandwidth */
1688 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001689 *pValue = state->AS_Data.f_out_bw - 750000;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001690 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001691
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001692 /* min inter-tuner LO separation */
1693 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001694 *pValue = state->AS_Data.f_min_LO_Separation;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001695 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001696
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001697 /* max # of intra-tuner harmonics */
1698 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001699 *pValue = state->AS_Data.maxH1;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001700 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001701
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001702 /* max # of inter-tuner harmonics */
1703 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001704 *pValue = state->AS_Data.maxH2;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001705 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001706
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001707 /* # of 1st IF exclusion zones */
1708 case MT2063_EXCL_ZONES:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001709 *pValue = state->AS_Data.nZones;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001710 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001711
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001712 /* # of spurs found/avoided */
1713 case MT2063_NUM_SPURS:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001714 *pValue = state->AS_Data.nSpursFound;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001715 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001716
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001717 /* >0 spurs avoided */
1718 case MT2063_SPUR_AVOIDED:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001719 *pValue = state->AS_Data.bSpurAvoided;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001720 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001721
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001722 /* >0 spurs in output (mathematically) */
1723 case MT2063_SPUR_PRESENT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001724 *pValue = state->AS_Data.bSpurPresent;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001725 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001726
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001727 /* Predefined receiver setup combination */
1728 case MT2063_RCVR_MODE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001729 *pValue = state->rcvr_mode;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001730 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001731
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001732 case MT2063_PD1:
1733 case MT2063_PD2: {
1734 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001735 u8 orig = (state->reg[MT2063_REG_BYP_CTRL]);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001736 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
1737 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001738
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001739 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001740
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001741 /* Initiate ADC output to reg 0x0A */
1742 if (reg != orig)
1743 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001744 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001745 MT2063_REG_BYP_CTRL,
1746 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001747
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001748 if (status < 0)
1749 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001750
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001751 for (i = 0; i < 8; i++) {
1752 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001753 mt2063_read(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001754 MT2063_REG_ADC_OUT,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001755 &state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001756 reg
1757 [MT2063_REG_ADC_OUT],
1758 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001759
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001760 if (status >= 0)
1761 *pValue +=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001762 state->
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001763 reg[MT2063_REG_ADC_OUT];
1764 else {
1765 if (i)
1766 *pValue /= i;
1767 return (status);
1768 }
1769 }
1770 *pValue /= 8; /* divide by number of reads */
1771 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001772
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001773 /* Restore value of Register BYP_CTRL */
1774 if (reg != orig)
1775 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001776 mt2063_write(state,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001777 MT2063_REG_BYP_CTRL,
1778 &orig, 1);
1779 }
1780 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001781
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001782 /* Get LNA attenuator code */
1783 case MT2063_ACLNA:
1784 {
1785 u8 val;
1786 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001787 MT2063_GetReg(state, MT2063_REG_XO_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001788 &val);
1789 *pValue = val & 0x1f;
1790 }
1791 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001792
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001793 /* Get RF attenuator code */
1794 case MT2063_ACRF:
1795 {
1796 u8 val;
1797 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001798 MT2063_GetReg(state, MT2063_REG_RF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001799 &val);
1800 *pValue = val & 0x1f;
1801 }
1802 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001803
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001804 /* Get FIF attenuator code */
1805 case MT2063_ACFIF:
1806 {
1807 u8 val;
1808 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001809 MT2063_GetReg(state, MT2063_REG_FIF_STATUS,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001810 &val);
1811 *pValue = val & 0x1f;
1812 }
1813 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001814
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001815 /* Get LNA attenuator limit */
1816 case MT2063_ACLNA_MAX:
1817 {
1818 u8 val;
1819 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001820 MT2063_GetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001821 &val);
1822 *pValue = val & 0x1f;
1823 }
1824 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001825
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001826 /* Get RF attenuator limit */
1827 case MT2063_ACRF_MAX:
1828 {
1829 u8 val;
1830 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001831 MT2063_GetReg(state, MT2063_REG_RF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001832 &val);
1833 *pValue = val & 0x1f;
1834 }
1835 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001836
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001837 /* Get FIF attenuator limit */
1838 case MT2063_ACFIF_MAX:
1839 {
1840 u8 val;
1841 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001842 MT2063_GetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001843 &val);
1844 *pValue = val & 0x1f;
1845 }
1846 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001847
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001848 /* Get current used DNC output */
1849 case MT2063_DNC_OUTPUT_ENABLE:
1850 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001851 if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
1852 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001853 *pValue =
1854 (u32) MT2063_DNC_NONE;
1855 else
1856 *pValue =
1857 (u32) MT2063_DNC_2;
1858 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001859
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001860 if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001861 *pValue =
1862 (u32) MT2063_DNC_1;
1863 else
1864 *pValue =
1865 (u32) MT2063_DNC_BOTH;
1866 }
1867 }
1868 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001869
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001870 /* Get VGA Gain Code */
1871 case MT2063_VGAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001872 *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001873 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001874
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001875 /* Get VGA bias current */
1876 case MT2063_VGAOI:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001877 *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001878 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001879
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001880 /* Get TAGC setting */
1881 case MT2063_TAGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001882 *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001883 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001884
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001885 /* Get AMP Gain Code */
1886 case MT2063_AMPGC:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001887 *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001888 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001889
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001890 /* Avoid DECT Frequencies */
1891 case MT2063_AVOID_DECT:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001892 *pValue = state->AS_Data.avoidDECT;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001893 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001894
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001895 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
1896 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001897 *pValue = state->ctfilt_sw;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001898 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001899
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001900 case MT2063_EOP:
1901 default:
1902 status |= -ERANGE;
1903 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001904 return (status);
1905}
1906
1907/****************************************************************************
1908**
1909** Name: MT2063_GetReg
1910**
1911** Description: Gets an MT2063 register.
1912**
1913** Parameters: h - Tuner handle (returned by MT2063_Open)
1914** reg - MT2063 register/subaddress location
1915** *val - MT2063 register/subaddress value
1916**
1917** Returns: status:
1918** MT_OK - No errors
1919** MT_COMM_ERR - Serial bus communications error
1920** MT_INV_HANDLE - Invalid tuner handle
1921** MT_ARG_NULL - Null pointer argument passed
1922** MT_ARG_RANGE - Argument out of range
1923**
1924** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1925**
1926** Use this function if you need to read a register from
1927** the MT2063.
1928**
1929** Revision History:
1930**
1931** SCR Date Author Description
1932** -------------------------------------------------------------------------
1933** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1934**
1935****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001936static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001937{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001938 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001939
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001940 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001941 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001942
1943 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001944 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001945
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03001946 status = mt2063_read(state, reg, &state->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001947
1948 return (status);
1949}
1950
1951/******************************************************************************
1952**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001953** Name: MT2063_SetReceiverMode
1954**
1955** Description: Set the MT2063 receiver mode
1956**
1957** --------------+----------------------------------------------
1958** Mode 0 : | MT2063_CABLE_QAM
1959** Mode 1 : | MT2063_CABLE_ANALOG
1960** Mode 2 : | MT2063_OFFAIR_COFDM
1961** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1962** Mode 4 : | MT2063_OFFAIR_ANALOG
1963** Mode 5 : | MT2063_OFFAIR_8VSB
1964** --------------+----+----+----+----+-----+--------------------
1965** (DNC1GC & DNC2GC are the values, which are used, when the specific
1966** DNC Output is selected, the other is always off)
1967**
1968** |<---------- Mode -------------->|
1969** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
1970** ------------+-----+-----+-----+-----+-----+-----+
1971** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
1972** LNARin | 0 | 0 | 3 | 3 | 3 | 3
1973** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
1974** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
1975** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
1976** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
1977** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
1978** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
1979** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
1980** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1981** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
1982** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
1983** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
1984** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
1985** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
1986**
1987**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03001988** Parameters: state - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001989** Mode - desired reciever mode
1990**
1991** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
1992**
1993** Returns: status:
1994** MT_OK - No errors
1995** MT_COMM_ERR - Serial bus communications error
1996**
1997** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
1998** Assumes that the tuner cache is valid.
1999**
2000** Revision History:
2001**
2002** SCR Date Author Description
2003** -------------------------------------------------------------------------
2004** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2005** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2006** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2007** modulation
2008** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2009** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2010** the same settings as with MT Launcher
2011** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2012** Add SetParam DNC_OUTPUT_ENABLE
2013** Removed VGAGC from receiver mode,
2014** default now 1
2015** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2016** Add SetParam AMPGC, removed from rcvr-mode
2017** Corrected names of GCU values
2018** reorganized receiver modes, removed,
2019** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2020** Actualized Receiver-Mode values
2021** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2022** N/A 11-27-2007 PINZ Improved buffered writing
2023** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2024** correct wakeup of the LNA after shutdown
2025** Set AFCsd = 1 as default
2026** Changed CAP1sel default
2027** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2028** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2029** Split SetParam up to ACLNA / ACLNA_MAX
2030** removed ACLNA_INRC/DECR (+RF & FIF)
2031** removed GCUAUTO / BYPATNDN/UP
2032**
2033******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002034static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002035 enum MT2063_RCVR_MODES Mode)
2036{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002037 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002038 u8 val;
2039 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002040
2041 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002042 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002043
2044 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002045 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002046 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002047 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002048 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002049 ? 0x40 :
2050 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002051 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2052 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002053 }
2054 }
2055
2056 /* LNARin */
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_LNA_RIN, LNARIN[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002059 }
2060
2061 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002062 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002063 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002064 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002065 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002066 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002067 if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002068 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002069 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002070 /* trigger FIFF calibration, needed after changing FIFFQ */
2071 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002072 (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002073 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002074 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002075 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002076 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002077 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002078 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002079 MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002080 }
2081 }
2082
2083 /* DNC1GC & DNC2GC */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002084 status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval);
2085 status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002086
2087 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002088 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002089 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002090 MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002091 }
2092
2093 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002094 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002095 status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002096 }
2097
2098 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002099 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002100 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002101 MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002102 }
2103
2104 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002105 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002106 status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002107 }
2108
2109 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002110 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002111 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002112 MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002113 }
2114
2115 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002116 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002117 status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002118 }
2119
2120 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002121 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002122 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002123 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002124 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002125 ? 0x80 :
2126 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002127 if (state->reg[MT2063_REG_LNA_TGT] != val) {
2128 status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002129 }
2130 }
2131
2132 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002133 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002134 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002135 (state->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002136 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002137 (FIFOVDIS[Mode] ? 0x80 : 0x00);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002138 if (state->reg[MT2063_REG_PD1_TGT] != val) {
2139 status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002140 }
2141 }
2142
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002143 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002144 state->rcvr_mode = Mode;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002145
2146 return (status);
2147}
2148
2149/******************************************************************************
2150**
2151** Name: MT2063_ReInit
2152**
2153** Description: Initialize the tuner's register values.
2154**
2155** Parameters: h - Tuner handle (returned by MT2063_Open)
2156**
2157** Returns: status:
2158** MT_OK - No errors
2159** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2160** MT_INV_HANDLE - Invalid tuner handle
2161** MT_COMM_ERR - Serial bus communications error
2162**
2163** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2164** MT_WriteSub - Write byte(s) of data to the two-wire bus
2165**
2166** Revision History:
2167**
2168** SCR Date Author Description
2169** -------------------------------------------------------------------------
2170** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2171** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2172** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2173** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2174** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2175** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2176** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2177** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2178** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2179** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2180** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2181**
2182******************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002183static u32 MT2063_ReInit(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002184{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002185 u8 all_resets = 0xF0; /* reset/load bits */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002186 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03002187 u8 *def = NULL;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002188 u32 FCRUN;
2189 s32 maxReads;
2190 u32 fcu_osc;
2191 u32 i;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002192 u8 MT2063B0_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002193 0x19, 0x05,
2194 0x1B, 0x1D,
2195 0x1C, 0x1F,
2196 0x1D, 0x0F,
2197 0x1E, 0x3F,
2198 0x1F, 0x0F,
2199 0x20, 0x3F,
2200 0x22, 0x21,
2201 0x23, 0x3F,
2202 0x24, 0x20,
2203 0x25, 0x3F,
2204 0x27, 0xEE,
2205 0x2C, 0x27, /* bit at 0x20 is cleared below */
2206 0x30, 0x03,
2207 0x2C, 0x07, /* bit at 0x20 is cleared here */
2208 0x2D, 0x87,
2209 0x2E, 0xAA,
2210 0x28, 0xE1, /* Set the FIFCrst bit here */
2211 0x28, 0xE0, /* Clear the FIFCrst bit here */
2212 0x00
2213 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002214 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002215 u8 MT2063B1_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002216 0x05, 0xF0,
2217 0x11, 0x10, /* New Enable AFCsd */
2218 0x19, 0x05,
2219 0x1A, 0x6C,
2220 0x1B, 0x24,
2221 0x1C, 0x28,
2222 0x1D, 0x8F,
2223 0x1E, 0x14,
2224 0x1F, 0x8F,
2225 0x20, 0x57,
2226 0x22, 0x21, /* New - ver 1.03 */
2227 0x23, 0x3C, /* New - ver 1.10 */
2228 0x24, 0x20, /* New - ver 1.03 */
2229 0x2C, 0x24, /* bit at 0x20 is cleared below */
2230 0x2D, 0x87, /* FIFFQ=0 */
2231 0x2F, 0xF3,
2232 0x30, 0x0C, /* New - ver 1.11 */
2233 0x31, 0x1B, /* New - ver 1.11 */
2234 0x2C, 0x04, /* bit at 0x20 is cleared here */
2235 0x28, 0xE1, /* Set the FIFCrst bit here */
2236 0x28, 0xE0, /* Clear the FIFCrst bit here */
2237 0x00
2238 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002239 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002240 u8 MT2063B3_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002241 0x05, 0xF0,
2242 0x19, 0x3D,
2243 0x2C, 0x24, /* bit at 0x20 is cleared below */
2244 0x2C, 0x04, /* bit at 0x20 is cleared here */
2245 0x28, 0xE1, /* Set the FIFCrst bit here */
2246 0x28, 0xE0, /* Clear the FIFCrst bit here */
2247 0x00
2248 };
2249
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002250 /* Read the Part/Rev code from the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002251 status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002252 if (status < 0)
2253 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002254
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002255 /* Check the part/rev code */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002256 if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2257 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2258 &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002259 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002260
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002261 /* Check the 2nd byte of the Part/Rev code from the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002262 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002263 MT2063_REG_RSVD_3B,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002264 &state->reg[MT2063_REG_RSVD_3B], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002265
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002266 if (status >= 0
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002267 &&((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002268 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002269
2270 /* Reset the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002271 status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002272 if (status < 0)
2273 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002274
2275 /* change all of the default values that vary from the HW reset values */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002276 /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2277 switch (state->reg[MT2063_REG_PART_REV]) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002278 case MT2063_B3:
2279 def = MT2063B3_defaults;
2280 break;
2281
2282 case MT2063_B1:
2283 def = MT2063B1_defaults;
2284 break;
2285
2286 case MT2063_B0:
2287 def = MT2063B0_defaults;
2288 break;
2289
2290 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002291 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002292 break;
2293 }
2294
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002295 while (status >= 0 && *def) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002296 u8 reg = *def++;
2297 u8 val = *def++;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002298 status = mt2063_write(state, reg, &val, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002299 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002300 if (status < 0)
2301 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002302
2303 /* Wait for FIFF location to complete. */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002304 FCRUN = 1;
2305 maxReads = 10;
2306 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
2307 msleep(2);
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002308 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002309 MT2063_REG_XO_STATUS,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002310 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002311 reg[MT2063_REG_XO_STATUS], 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002312 FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002313 }
2314
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002315 if (FCRUN != 0)
2316 return -ENODEV;
2317
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002318 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002319 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002320 &state->reg[MT2063_REG_FIFFC], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002321 if (status < 0)
2322 return status;
2323
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002324 /* Read back all the registers from the tuner */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002325 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002326 MT2063_REG_PART_REV,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002327 state->reg, MT2063_REG_END_REGS);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002328 if (status < 0)
2329 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002330
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002331 /* Initialize the tuner state. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002332 state->tuner_id = state->reg[MT2063_REG_PART_REV];
2333 state->AS_Data.f_ref = MT2063_REF_FREQ;
2334 state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
2335 ((u32) state->reg[MT2063_REG_FIFFC] + 640);
2336 state->AS_Data.f_if1_bw = MT2063_IF1_BW;
2337 state->AS_Data.f_out = 43750000UL;
2338 state->AS_Data.f_out_bw = 6750000UL;
2339 state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2340 state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
2341 state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2342 state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2343 state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2344 state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2345 state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
2346 state->AS_Data.f_LO1 = 2181000000UL;
2347 state->AS_Data.f_LO2 = 1486249786UL;
2348 state->f_IF1_actual = state->AS_Data.f_if1_Center;
2349 state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
2350 state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2351 state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2352 state->num_regs = MT2063_REG_END_REGS;
2353 state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2354 state->ctfilt_sw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002355
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002356 state->CTFiltMax[0] = 69230000;
2357 state->CTFiltMax[1] = 105770000;
2358 state->CTFiltMax[2] = 140350000;
2359 state->CTFiltMax[3] = 177110000;
2360 state->CTFiltMax[4] = 212860000;
2361 state->CTFiltMax[5] = 241130000;
2362 state->CTFiltMax[6] = 274370000;
2363 state->CTFiltMax[7] = 309820000;
2364 state->CTFiltMax[8] = 342450000;
2365 state->CTFiltMax[9] = 378870000;
2366 state->CTFiltMax[10] = 416210000;
2367 state->CTFiltMax[11] = 456500000;
2368 state->CTFiltMax[12] = 495790000;
2369 state->CTFiltMax[13] = 534530000;
2370 state->CTFiltMax[14] = 572610000;
2371 state->CTFiltMax[15] = 598970000;
2372 state->CTFiltMax[16] = 635910000;
2373 state->CTFiltMax[17] = 672130000;
2374 state->CTFiltMax[18] = 714840000;
2375 state->CTFiltMax[19] = 739660000;
2376 state->CTFiltMax[20] = 770410000;
2377 state->CTFiltMax[21] = 814660000;
2378 state->CTFiltMax[22] = 846950000;
2379 state->CTFiltMax[23] = 867820000;
2380 state->CTFiltMax[24] = 915980000;
2381 state->CTFiltMax[25] = 947450000;
2382 state->CTFiltMax[26] = 983110000;
2383 state->CTFiltMax[27] = 1021630000;
2384 state->CTFiltMax[28] = 1061870000;
2385 state->CTFiltMax[29] = 1098330000;
2386 state->CTFiltMax[30] = 1138990000;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002387
2388 /*
2389 ** Fetch the FCU osc value and use it and the fRef value to
2390 ** scale all of the Band Max values
2391 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002392
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002393 state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002394 status = mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002395 MT2063_REG_CTUNE_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002396 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002397 if (status < 0)
2398 return status;
2399 /* Read the ClearTune filter calibration value */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002400 status = mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002401 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002402 &state->reg[MT2063_REG_FIFFC], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002403 if (status < 0)
2404 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002405
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002406 fcu_osc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002407
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002408 state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002409 status = mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002410 MT2063_REG_CTUNE_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002411 &state->reg[MT2063_REG_CTUNE_CTRL], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002412 if (status < 0)
2413 return status;
2414
2415 /* Adjust each of the values in the ClearTune filter cross-over table */
2416 for (i = 0; i < 31; i++)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002417 state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002418
2419 return (status);
2420}
2421
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002422/****************************************************************************
2423**
2424** Name: MT2063_SetParam
2425**
2426** Description: Sets a tuning algorithm parameter.
2427**
2428** This function provides access to the internals of the
2429** tuning algorithm. You can override many of the tuning
2430** algorithm defaults using this function.
2431**
2432** Parameters: h - Tuner handle (returned by MT2063_Open)
2433** param - Tuning algorithm parameter
2434** (see enum MT2063_Param)
2435** nValue - value to be set
2436**
2437** param Description
2438** ---------------------- --------------------------------
2439** MT2063_SRO_FREQ crystal frequency
2440** MT2063_STEPSIZE minimum tuning step size
2441** MT2063_LO1_FREQ LO1 frequency
2442** MT2063_LO1_STEPSIZE LO1 minimum step size
2443** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2444** MT2063_IF1_REQUEST Requested 1st IF
2445** MT2063_ZIF_BW zero-IF bandwidth
2446** MT2063_LO2_FREQ LO2 frequency
2447** MT2063_LO2_STEPSIZE LO2 minimum step size
2448** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2449** MT2063_OUTPUT_FREQ output center frequency
2450** MT2063_OUTPUT_BW output bandwidth
2451** MT2063_LO_SEPARATION min inter-tuner LO separation
2452** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2453** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2454** MT2063_RCVR_MODE Predefined modes
2455** MT2063_LNA_RIN Set LNA Rin (*)
2456** MT2063_LNA_TGT Set target power level at LNA (*)
2457** MT2063_PD1_TGT Set target power level at PD1 (*)
2458** MT2063_PD2_TGT Set target power level at PD2 (*)
2459** MT2063_ACLNA_MAX LNA attenuator limit (*)
2460** MT2063_ACRF_MAX RF attenuator limit (*)
2461** MT2063_ACFIF_MAX FIF attenuator limit (*)
2462** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2463** MT2063_VGAGC VGA gain code
2464** MT2063_VGAOI VGA output current
2465** MT2063_TAGC TAGC setting
2466** MT2063_AMPGC AMP gain code
2467** MT2063_AVOID_DECT Avoid DECT Frequencies
2468** MT2063_CTFILT_SW Cleartune filter selection
2469**
2470** (*) This parameter is set by MT2063_RCVR_MODE, do not call
2471** additionally.
2472**
2473** Usage: status |= MT2063_SetParam(hMT2063,
2474** MT2063_STEPSIZE,
2475** 50000);
2476**
2477** Returns: status:
2478** MT_OK - No errors
2479** MT_INV_HANDLE - Invalid tuner handle
2480** MT_ARG_NULL - Null pointer argument passed
2481** MT_ARG_RANGE - Invalid parameter requested
2482** or set value out of range
2483** or non-writable parameter
2484**
2485** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2486**
2487** See Also: MT2063_GetParam, MT2063_Open
2488**
2489** Revision History:
2490**
2491** SCR Date Author Description
2492** -------------------------------------------------------------------------
2493** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2494** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2495** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2496** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2497** Split SetParam up to ACLNA / ACLNA_MAX
2498** removed ACLNA_INRC/DECR (+RF & FIF)
2499** removed GCUAUTO / BYPATNDN/UP
2500** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2501** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2502** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2503**
2504****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002505static u32 MT2063_SetParam(struct mt2063_state *state,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002506 enum MT2063_Param param,
2507 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002508{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002509 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002510 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002511
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002512 switch (param) {
2513 /* crystal frequency */
2514 case MT2063_SRO_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002515 state->AS_Data.f_ref = nValue;
2516 state->AS_Data.f_LO1_FracN_Avoid = 0;
2517 state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
2518 state->AS_Data.f_LO1_Step = nValue / 64;
2519 state->AS_Data.f_if1_Center =
2520 (state->AS_Data.f_ref / 8) *
2521 (state->reg[MT2063_REG_FIFFC] + 640);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002522 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002523
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002524 /* minimum tuning step size */
2525 case MT2063_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002526 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002527 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002528
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002529 /* LO1 frequency */
2530 case MT2063_LO1_FREQ:
2531 {
2532 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2533 /* Capture the Divider and Numerator portions of other LO */
2534 u8 tempLO2CQ[3];
2535 u8 tempLO2C[3];
2536 u8 tmpOneShot;
2537 u32 Div, FracN;
2538 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002539
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002540 /* Buffer the queue for restoration later and get actual LO2 values. */
2541 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002542 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002543 MT2063_REG_LO2CQ_1,
2544 &(tempLO2CQ[0]), 3);
2545 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002546 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002547 MT2063_REG_LO2C_1,
2548 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002549
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002550 /* clear the one-shot bits */
2551 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
2552 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002553
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002554 /* only write the queue values if they are different from the actual. */
2555 if ((tempLO2CQ[0] != tempLO2C[0]) ||
2556 (tempLO2CQ[1] != tempLO2C[1]) ||
2557 (tempLO2CQ[2] != tempLO2C[2])) {
2558 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002559 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002560 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002561 MT2063_REG_LO2CQ_1,
2562 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002563
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002564 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002565 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002566 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002567 tempLO2C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002568 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002569 tempLO2C[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002570 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002571 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002572 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002573 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002574 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002575
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002576 /* Calculate the Divider and Numberator components of LO1 */
2577 status =
2578 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002579 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002580 64,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002581 state->AS_Data.f_ref);
2582 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002583 (u8) (Div & 0x00FF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002584 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002585 (u8) (FracN);
2586 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002587 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002588 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002589 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002590 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002591
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002592 /* set the one-shot bit to load the pair of LO values */
2593 tmpOneShot = tempLO2CQ[2] | 0xE0;
2594 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002595 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002596 MT2063_REG_LO2CQ_3,
2597 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002598
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002599 /* only restore the queue values if they were different from the actual. */
2600 if (restore) {
2601 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002602 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002603 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002604 MT2063_REG_LO2CQ_1,
2605 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002606
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002607 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002608 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002609 tempLO2CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002610 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002611 tempLO2CQ[1];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002612 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002613 tempLO2CQ[2];
2614 }
2615
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002616 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002617 MT2063_LO1_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002618 &state->AS_Data.f_LO1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002619 }
2620 break;
2621
2622 /* LO1 minimum step size */
2623 case MT2063_LO1_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002624 state->AS_Data.f_LO1_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002625 break;
2626
2627 /* LO1 FracN keep-out region */
2628 case MT2063_LO1_FRACN_AVOID_PARAM:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002629 state->AS_Data.f_LO1_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002630 break;
2631
2632 /* Requested 1st IF */
2633 case MT2063_IF1_REQUEST:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002634 state->AS_Data.f_if1_Request = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002635 break;
2636
2637 /* zero-IF bandwidth */
2638 case MT2063_ZIF_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002639 state->AS_Data.f_zif_bw = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002640 break;
2641
2642 /* LO2 frequency */
2643 case MT2063_LO2_FREQ:
2644 {
2645 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
2646 /* Capture the Divider and Numerator portions of other LO */
2647 u8 tempLO1CQ[2];
2648 u8 tempLO1C[2];
2649 u32 Div2;
2650 u32 FracN2;
2651 u8 tmpOneShot;
2652 u8 restore = 0;
2653
2654 /* Buffer the queue for restoration later and get actual LO2 values. */
2655 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002656 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002657 MT2063_REG_LO1CQ_1,
2658 &(tempLO1CQ[0]), 2);
2659 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002660 mt2063_read(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002661 MT2063_REG_LO1C_1,
2662 &(tempLO1C[0]), 2);
2663
2664 /* only write the queue values if they are different from the actual. */
2665 if ((tempLO1CQ[0] != tempLO1C[0])
2666 || (tempLO1CQ[1] != tempLO1C[1])) {
2667 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002668 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002669 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002670 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002671 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002672
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002673 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002674 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002675 tempLO1C[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002676 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002677 tempLO1C[1];
2678 restore = 1;
2679 }
2680
2681 /* Calculate the Divider and Numberator components of LO2 */
2682 status =
2683 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002684 state->AS_Data.f_ref /
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002685 8191,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002686 state->AS_Data.f_ref);
2687 state->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002688 (u8) ((Div2 << 1) |
2689 ((FracN2 >> 12) & 0x01)) & 0xFF;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002690 state->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002691 (u8) ((FracN2 >> 4) & 0xFF);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002692 state->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002693 (u8) ((FracN2 & 0x0F));
2694 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002695 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002696 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002697 &state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002698 reg[MT2063_REG_LO1CQ_1], 3);
2699
2700 /* set the one-shot bit to load the LO values */
2701 tmpOneShot =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002702 state->reg[MT2063_REG_LO2CQ_3] | 0xE0;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002703 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002704 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002705 MT2063_REG_LO2CQ_3,
2706 &tmpOneShot, 1);
2707
2708 /* only restore LO1 queue value if they were different from the actual. */
2709 if (restore) {
2710 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002711 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03002712 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002713 MT2063_REG_LO1CQ_1,
2714 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002715
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002716 /* cache the bytes just written. */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002717 state->reg[MT2063_REG_LO1CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002718 tempLO1CQ[0];
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002719 state->reg[MT2063_REG_LO1CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002720 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002721 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002722
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002723 MT2063_GetParam(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002724 MT2063_LO2_FREQ,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002725 &state->AS_Data.f_LO2);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002726 }
2727 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002728
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002729 /* LO2 minimum step size */
2730 case MT2063_LO2_STEPSIZE:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002731 state->AS_Data.f_LO2_Step = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002732 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002733
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002734 /* LO2 FracN keep-out region */
2735 case MT2063_LO2_FRACN_AVOID:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002736 state->AS_Data.f_LO2_FracN_Avoid = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002737 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002738
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002739 /* output center frequency */
2740 case MT2063_OUTPUT_FREQ:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002741 state->AS_Data.f_out = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002742 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002743
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002744 /* output bandwidth */
2745 case MT2063_OUTPUT_BW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002746 state->AS_Data.f_out_bw = nValue + 750000;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002747 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002748
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002749 /* min inter-tuner LO separation */
2750 case MT2063_LO_SEPARATION:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002751 state->AS_Data.f_min_LO_Separation = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002752 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002753
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002754 /* max # of intra-tuner harmonics */
2755 case MT2063_MAX_HARM1:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002756 state->AS_Data.maxH1 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002757 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002758
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002759 /* max # of inter-tuner harmonics */
2760 case MT2063_MAX_HARM2:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002761 state->AS_Data.maxH2 = nValue;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002762 break;
2763
2764 case MT2063_RCVR_MODE:
2765 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002766 MT2063_SetReceiverMode(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002767 (enum MT2063_RCVR_MODES)
2768 nValue);
2769 break;
2770
2771 /* Set LNA Rin -- nValue is desired value */
2772 case MT2063_LNA_RIN:
2773 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002774 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002775 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
2776 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002777 if (state->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002778 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002779 MT2063_SetReg(state, MT2063_REG_CTRL_2C,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002780 val);
2781 }
2782 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002783
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002784 /* Set target power level at LNA -- nValue is desired value */
2785 case MT2063_LNA_TGT:
2786 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002787 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002788 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
2789 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002790 if (state->reg[MT2063_REG_LNA_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002791 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002792 MT2063_SetReg(state, MT2063_REG_LNA_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002793 val);
2794 }
2795 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002796
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002797 /* Set target power level at PD1 -- nValue is desired value */
2798 case MT2063_PD1_TGT:
2799 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002800 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002801 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
2802 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002803 if (state->reg[MT2063_REG_PD1_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002804 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002805 MT2063_SetReg(state, MT2063_REG_PD1_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002806 val);
2807 }
2808 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002809
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002810 /* Set target power level at PD2 -- nValue is desired value */
2811 case MT2063_PD2_TGT:
2812 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002813 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002814 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
2815 (nValue & 0x3F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002816 if (state->reg[MT2063_REG_PD2_TGT] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002817 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002818 MT2063_SetReg(state, MT2063_REG_PD2_TGT,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002819 val);
2820 }
2821 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002822
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002823 /* Set LNA atten limit -- nValue is desired value */
2824 case MT2063_ACLNA_MAX:
2825 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002826 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002827 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
2828 &
2829 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002830 if (state->reg[MT2063_REG_LNA_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002831 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002832 MT2063_SetReg(state, MT2063_REG_LNA_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002833 val);
2834 }
2835 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002836
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002837 /* Set RF atten limit -- nValue is desired value */
2838 case MT2063_ACRF_MAX:
2839 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002840 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002841 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
2842 &
2843 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002844 if (state->reg[MT2063_REG_RF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002845 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002846 MT2063_SetReg(state, MT2063_REG_RF_OV, val);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002847 }
2848 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002849
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002850 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
2851 case MT2063_ACFIF_MAX:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002852 if (state->reg[MT2063_REG_PART_REV] != MT2063_B3
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002853 && nValue > 5)
2854 nValue = 5;
2855 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002856 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002857 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
2858 &
2859 0x1F);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002860 if (state->reg[MT2063_REG_FIF_OV] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002861 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002862 MT2063_SetReg(state, MT2063_REG_FIF_OV,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002863 val);
2864 }
2865 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002866
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002867 case MT2063_DNC_OUTPUT_ENABLE:
2868 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03002869 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002870 case MT2063_DNC_NONE:
2871 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002872 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2873 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002874 val)
2875 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002876 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002877 MT2063_REG_DNC_GAIN,
2878 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002879
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002880 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2881 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002882 val)
2883 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002884 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002885 MT2063_REG_VGA_GAIN,
2886 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002887
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002888 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2889 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002890 val)
2891 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002892 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002893 MT2063_REG_RSVD_20,
2894 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002895
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002896 break;
2897 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002898 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002899 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002900 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2901 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002902 val)
2903 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002904 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002905 MT2063_REG_DNC_GAIN,
2906 val);
2907
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002908 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
2909 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002910 val)
2911 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002912 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002913 MT2063_REG_VGA_GAIN,
2914 val);
2915
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002916 val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
2917 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002918 val)
2919 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002920 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002921 MT2063_REG_RSVD_20,
2922 val);
2923
2924 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002925 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002926 case MT2063_DNC_2:
2927 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002928 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
2929 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002930 val)
2931 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002932 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002933 MT2063_REG_DNC_GAIN,
2934 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002935
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002936 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2937 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002938 val)
2939 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002940 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002941 MT2063_REG_VGA_GAIN,
2942 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002943
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002944 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2945 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002946 val)
2947 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002948 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002949 MT2063_REG_RSVD_20,
2950 val);
2951
2952 break;
2953 }
2954 case MT2063_DNC_BOTH:
2955 {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002956 val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */
2957 if (state->reg[MT2063_REG_DNC_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002958 val)
2959 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002960 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002961 MT2063_REG_DNC_GAIN,
2962 val);
2963
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002964 val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */
2965 if (state->reg[MT2063_REG_VGA_GAIN] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002966 val)
2967 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002968 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002969 MT2063_REG_VGA_GAIN,
2970 val);
2971
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002972 val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
2973 if (state->reg[MT2063_REG_RSVD_20] !=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002974 val)
2975 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002976 MT2063_SetReg(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002977 MT2063_REG_RSVD_20,
2978 val);
2979
2980 break;
2981 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002982 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002983 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002984 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002985 break;
2986
2987 case MT2063_VGAGC:
2988 /* Set VGA gain code */
2989 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002990 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002991 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
2992 ((nValue & 0x03) << 2);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002993 if (state->reg[MT2063_REG_VGA_GAIN] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002994 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03002995 MT2063_SetReg(state, MT2063_REG_VGA_GAIN,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002996 val);
2997 }
2998 break;
2999
3000 case MT2063_VGAOI:
3001 /* Set VGA bias current */
3002 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003003 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003004 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
3005 (nValue & 0x07);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003006 if (state->reg[MT2063_REG_RSVD_31] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003007 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003008 MT2063_SetReg(state, MT2063_REG_RSVD_31,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003009 val);
3010 }
3011 break;
3012
3013 case MT2063_TAGC:
3014 /* Set TAGC */
3015 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003016 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003017 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
3018 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003019 if (state->reg[MT2063_REG_RSVD_1E] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003020 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003021 MT2063_SetReg(state, MT2063_REG_RSVD_1E,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003022 val);
3023 }
3024 break;
3025
3026 case MT2063_AMPGC:
3027 /* Set Amp gain code */
3028 val =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003029 (state->
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003030 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
3031 (nValue & 0x03);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003032 if (state->reg[MT2063_REG_TEMP_SEL] != val) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003033 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003034 MT2063_SetReg(state, MT2063_REG_TEMP_SEL,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003035 val);
3036 }
3037 break;
3038
3039 /* Avoid DECT Frequencies */
3040 case MT2063_AVOID_DECT:
3041 {
3042 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3043 (enum MT2063_DECT_Avoid_Type)nValue;
3044 if ((newAvoidSetting >=
3045 MT2063_NO_DECT_AVOIDANCE)
3046 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003047 state->AS_Data.avoidDECT =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003048 newAvoidSetting;
3049 }
3050 }
3051 break;
3052
3053 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3054 case MT2063_CTFILT_SW:
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003055 state->ctfilt_sw = (nValue & 0x01);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003056 break;
3057
3058 /* These parameters are read-only */
3059 case MT2063_IC_ADDR:
3060 case MT2063_MAX_OPEN:
3061 case MT2063_NUM_OPEN:
3062 case MT2063_INPUT_FREQ:
3063 case MT2063_IF1_ACTUAL:
3064 case MT2063_IF1_CENTER:
3065 case MT2063_IF1_BW:
3066 case MT2063_AS_ALG:
3067 case MT2063_EXCL_ZONES:
3068 case MT2063_SPUR_AVOIDED:
3069 case MT2063_NUM_SPURS:
3070 case MT2063_SPUR_PRESENT:
3071 case MT2063_ACLNA:
3072 case MT2063_ACRF:
3073 case MT2063_ACFIF:
3074 case MT2063_EOP:
3075 default:
3076 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003077 }
3078 return (status);
3079}
3080
3081/****************************************************************************
3082**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003083** Name: MT2063_ClearPowerMaskBits
3084**
3085** Description: Clears the power-down mask bits for various sections of
3086** the MT2063
3087**
3088** Parameters: h - Tuner handle (returned by MT2063_Open)
3089** Bits - Mask bits to be cleared.
3090**
3091** See definition of MT2063_Mask_Bits type for description
3092** of each of the power bits.
3093**
3094** Returns: status:
3095** MT_OK - No errors
3096** MT_INV_HANDLE - Invalid tuner handle
3097** MT_COMM_ERR - Serial bus communications error
3098**
3099** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3100**
3101** Revision History:
3102**
3103** SCR Date Author Description
3104** -------------------------------------------------------------------------
3105** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3106**
3107****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003108static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003109{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003110 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003111
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003112 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3113 if ((Bits & 0xFF00) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003114 state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003115 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003116 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003117 MT2063_REG_PWR_2,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003118 &state->reg[MT2063_REG_PWR_2], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003119 }
3120 if ((Bits & 0xFF) != 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003121 state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003122 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003123 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003124 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003125 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003126 }
3127
3128 return (status);
3129}
3130
3131/****************************************************************************
3132**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003133** Name: MT2063_SoftwareShutdown
3134**
3135** Description: Enables or disables software shutdown function. When
3136** Shutdown==1, any section whose power mask is set will be
3137** shutdown.
3138**
3139** Parameters: h - Tuner handle (returned by MT2063_Open)
3140** Shutdown - 1 = shutdown the masked sections, otherwise
3141** power all sections on
3142**
3143** Returns: status:
3144** MT_OK - No errors
3145** MT_INV_HANDLE - Invalid tuner handle
3146** MT_COMM_ERR - Serial bus communications error
3147**
3148** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3149**
3150** Revision History:
3151**
3152** SCR Date Author Description
3153** -------------------------------------------------------------------------
3154** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3155** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3156** correct wakeup of the LNA
3157**
3158****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003159static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003160{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003161 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003162
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003163 if (Shutdown == 1)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003164 state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003165 else
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003166 state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003167
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003168 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003169 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003170 MT2063_REG_PWR_1,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003171 &state->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003172
3173 if (Shutdown != 1) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003174 state->reg[MT2063_REG_BYP_CTRL] =
3175 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003176 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003177 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003178 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003179 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003180 1);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003181 state->reg[MT2063_REG_BYP_CTRL] =
3182 (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003183 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003184 mt2063_write(state,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003185 MT2063_REG_BYP_CTRL,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003186 &state->reg[MT2063_REG_BYP_CTRL],
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003187 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003188 }
3189
3190 return (status);
3191}
3192
3193/****************************************************************************
3194**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003195** Name: MT2063_SetReg
3196**
3197** Description: Sets an MT2063 register.
3198**
3199** Parameters: h - Tuner handle (returned by MT2063_Open)
3200** reg - MT2063 register/subaddress location
3201** val - MT2063 register/subaddress value
3202**
3203** Returns: status:
3204** MT_OK - No errors
3205** MT_COMM_ERR - Serial bus communications error
3206** MT_INV_HANDLE - Invalid tuner handle
3207** MT_ARG_RANGE - Argument out of range
3208**
3209** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3210**
3211** Use this function if you need to override a default
3212** register value
3213**
3214** Revision History:
3215**
3216** SCR Date Author Description
3217** -------------------------------------------------------------------------
3218** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3219**
3220****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003221static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003222{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003223 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003224
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003225 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003226 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003227
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003228 status = mt2063_write(state, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003229 1);
3230 if (status >= 0)
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003231 state->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003232
3233 return (status);
3234}
3235
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003236static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003237{
3238 return f_ref * (f_LO / f_ref)
3239 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
3240}
3241
3242/****************************************************************************
3243**
3244** Name: fLO_FractionalTerm
3245**
3246** Description: Calculates the portion contributed by FracN / denom.
3247**
3248** This function preserves maximum precision without
3249** risk of overflow. It accurately calculates
3250** f_ref * num / denom to within 1 HZ with fixed math.
3251**
3252** Parameters: num - Fractional portion of the multiplier
3253** denom - denominator portion of the ratio
3254** This routine successfully handles denom values
3255** up to and including 2^18.
3256** f_Ref - SRO frequency. This calculation handles
3257** f_ref as two separate 14-bit fields.
3258** Therefore, a maximum value of 2^28-1
3259** may safely be used for f_ref. This is
3260** the genesis of the magic number "14" and the
3261** magic mask value of 0x03FFF.
3262**
3263** Returns: f_ref * num / denom
3264**
3265** Revision History:
3266**
3267** SCR Date Author Description
3268** -------------------------------------------------------------------------
3269** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3270**
3271****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003272static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
3273 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003274{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003275 u32 t1 = (f_ref >> 14) * num;
3276 u32 term1 = t1 / denom;
3277 u32 loss = t1 % denom;
3278 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003279 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
3280 return ((term1 << 14) + term2);
3281}
3282
3283/****************************************************************************
3284**
3285** Name: CalcLO1Mult
3286**
3287** Description: Calculates Integer divider value and the numerator
3288** value for a FracN PLL.
3289**
3290** This function assumes that the f_LO and f_Ref are
3291** evenly divisible by f_LO_Step.
3292**
3293** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3294** FracN - OUTPUT: Fractional portion of the multiplier
3295** f_LO - desired LO frequency.
3296** f_LO_Step - Minimum step size for the LO (in Hz).
3297** f_Ref - SRO frequency.
3298** f_Avoid - Range of PLL frequencies to avoid near
3299** integer multiples of f_Ref (in Hz).
3300**
3301** Returns: Recalculated LO frequency.
3302**
3303** Revision History:
3304**
3305** SCR Date Author Description
3306** -------------------------------------------------------------------------
3307** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3308**
3309****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003310static u32 MT2063_CalcLO1Mult(u32 * Div,
3311 u32 * FracN,
3312 u32 f_LO,
3313 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003314{
3315 /* Calculate the whole number portion of the divider */
3316 *Div = f_LO / f_Ref;
3317
3318 /* Calculate the numerator value (round to nearest f_LO_Step) */
3319 *FracN =
3320 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3321 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3322
3323 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
3324}
3325
3326/****************************************************************************
3327**
3328** Name: CalcLO2Mult
3329**
3330** Description: Calculates Integer divider value and the numerator
3331** value for a FracN PLL.
3332**
3333** This function assumes that the f_LO and f_Ref are
3334** evenly divisible by f_LO_Step.
3335**
3336** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3337** FracN - OUTPUT: Fractional portion of the multiplier
3338** f_LO - desired LO frequency.
3339** f_LO_Step - Minimum step size for the LO (in Hz).
3340** f_Ref - SRO frequency.
3341** f_Avoid - Range of PLL frequencies to avoid near
3342** integer multiples of f_Ref (in Hz).
3343**
3344** Returns: Recalculated LO frequency.
3345**
3346** Revision History:
3347**
3348** SCR Date Author Description
3349** -------------------------------------------------------------------------
3350** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3351**
3352****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003353static u32 MT2063_CalcLO2Mult(u32 * Div,
3354 u32 * FracN,
3355 u32 f_LO,
3356 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003357{
3358 /* Calculate the whole number portion of the divider */
3359 *Div = f_LO / f_Ref;
3360
3361 /* Calculate the numerator value (round to nearest f_LO_Step) */
3362 *FracN =
3363 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3364 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3365
3366 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
3367 8191);
3368}
3369
3370/****************************************************************************
3371**
3372** Name: FindClearTuneFilter
3373**
3374** Description: Calculate the corrrect ClearTune filter to be used for
3375** a given input frequency.
3376**
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003377** Parameters: state - ptr to tuner data structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003378** f_in - RF input center frequency (in Hz).
3379**
3380** Returns: ClearTune filter number (0-31)
3381**
3382** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3383**
3384** Revision History:
3385**
3386** SCR Date Author Description
3387** -------------------------------------------------------------------------
3388** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3389** cross-over frequency values.
3390**
3391****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003392static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003393{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003394 u32 RFBand;
3395 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003396
3397 /*
3398 ** Find RF Band setting
3399 */
3400 RFBand = 31; /* def when f_in > all */
3401 for (idx = 0; idx < 31; ++idx) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003402 if (state->CTFiltMax[idx] >= f_in) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003403 RFBand = idx;
3404 break;
3405 }
3406 }
3407 return (RFBand);
3408}
3409
3410/****************************************************************************
3411**
3412** Name: MT2063_Tune
3413**
3414** Description: Change the tuner's tuned frequency to RFin.
3415**
3416** Parameters: h - Open handle to the tuner (from MT2063_Open).
3417** f_in - RF input center frequency (in Hz).
3418**
3419** Returns: status:
3420** MT_OK - No errors
3421** MT_INV_HANDLE - Invalid tuner handle
3422** MT_UPC_UNLOCK - Upconverter PLL unlocked
3423** MT_DNC_UNLOCK - Downconverter PLL unlocked
3424** MT_COMM_ERR - Serial bus communications error
3425** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3426** MT_SPUR_PRESENT - LO spur possible in output
3427** MT_FIN_RANGE - Input freq out of range
3428** MT_FOUT_RANGE - Output freq out of range
3429** MT_UPC_RANGE - Upconverter freq out of range
3430** MT_DNC_RANGE - Downconverter freq out of range
3431**
3432** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
3433**
3434** MT_ReadSub - Read data from the two-wire serial bus
3435** MT_WriteSub - Write data to the two-wire serial bus
3436** MT_Sleep - Delay execution for x milliseconds
3437** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
3438**
3439** Revision History:
3440**
3441** SCR Date Author Description
3442** -------------------------------------------------------------------------
3443** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3444** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
3445** cross-over frequency values.
3446** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3447** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3448** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3449**
3450****************************************************************************/
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003451static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003452{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003453
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003454 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003455 u32 LO1; /* 1st LO register value */
3456 u32 Num1; /* Numerator for LO1 reg. value */
3457 u32 f_IF1; /* 1st IF requested */
3458 u32 LO2; /* 2nd LO register value */
3459 u32 Num2; /* Numerator for LO2 reg. value */
3460 u32 ofLO1, ofLO2; /* last time's LO frequencies */
3461 u32 ofin, ofout; /* last time's I/O frequencies */
3462 u8 fiffc = 0x80; /* FIFF center freq from tuner */
3463 u32 fiffof; /* Offset from FIFF center freq */
3464 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
3465 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
3466 u8 val;
3467 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003468
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003469 /* Check the input and output frequency ranges */
3470 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003471 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003472
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003473 if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
3474 || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003475 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003476
3477 /*
3478 ** Save original LO1 and LO2 register values
3479 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003480 ofLO1 = state->AS_Data.f_LO1;
3481 ofLO2 = state->AS_Data.f_LO2;
3482 ofin = state->AS_Data.f_in;
3483 ofout = state->AS_Data.f_out;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003484
3485 /*
3486 ** Find and set RF Band setting
3487 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003488 if (state->ctfilt_sw == 1) {
3489 val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
3490 if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003491 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003492 MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003493 }
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003494 val = state->reg[MT2063_REG_CTUNE_OV];
3495 RFBand = FindClearTuneFilter(state, f_in);
3496 state->reg[MT2063_REG_CTUNE_OV] =
3497 (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003498 | RFBand);
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003499 if (state->reg[MT2063_REG_CTUNE_OV] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003500 status |=
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003501 MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003502 }
3503 }
3504
3505 /*
3506 ** Read the FIFF Center Frequency from the tuner
3507 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003508 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003509 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003510 mt2063_read(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003511 MT2063_REG_FIFFC,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003512 &state->reg[MT2063_REG_FIFFC], 1);
3513 fiffc = state->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003514 }
3515 /*
3516 ** Assign in the requested values
3517 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003518 state->AS_Data.f_in = f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003519 /* Request a 1st IF such that LO1 is on a step size */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003520 state->AS_Data.f_if1_Request =
3521 MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
3522 state->AS_Data.f_LO1_Step,
3523 state->AS_Data.f_ref) - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003524
3525 /*
3526 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
3527 ** desired LO1 frequency
3528 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003529 MT2063_ResetExclZones(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003530
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003531 f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003532
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003533 state->AS_Data.f_LO1 =
3534 MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
3535 state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003536
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003537 state->AS_Data.f_LO2 =
3538 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3539 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003540
3541 /*
3542 ** Check for any LO spurs in the output bandwidth and adjust
3543 ** the LO settings to avoid them if needed
3544 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003545 status |= MT2063_AvoidSpurs(state, &state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003546 /*
3547 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
3548 ** Recalculate the LO frequencies and the values to be placed
3549 ** in the tuning registers.
3550 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003551 state->AS_Data.f_LO1 =
3552 MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
3553 state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
3554 state->AS_Data.f_LO2 =
3555 MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
3556 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
3557 state->AS_Data.f_LO2 =
3558 MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
3559 state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003560
3561 /*
3562 ** Check the upconverter and downconverter frequency ranges
3563 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003564 if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
3565 || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003566 status |= MT2063_UPC_RANGE;
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003567 if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
3568 || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003569 status |= MT2063_DNC_RANGE;
3570 /* LO2 Lock bit was in a different place for B0 version */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003571 if (state->tuner_id == MT2063_B0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003572 LO2LK = 0x40;
3573
3574 /*
3575 ** If we have the same LO frequencies and we're already locked,
3576 ** then skip re-programming the LO registers.
3577 */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003578 if ((ofLO1 != state->AS_Data.f_LO1)
3579 || (ofLO2 != state->AS_Data.f_LO2)
3580 || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003581 (LO1LK | LO2LK))) {
3582 /*
3583 ** Calculate the FIFFOF register value
3584 **
3585 ** IF1_Actual
3586 ** FIFFOF = ------------ - 8 * FIFFC - 4992
3587 ** f_ref/64
3588 */
3589 fiffof =
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003590 (state->AS_Data.f_LO1 -
3591 f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003592 4992;
3593 if (fiffof > 0xFF)
3594 fiffof = 0xFF;
3595
3596 /*
3597 ** Place all of the calculated values into the local tuner
3598 ** register fields.
3599 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003600 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003601 state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
3602 state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
3603 state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003604 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003605 state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
3606 state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003607
3608 /*
3609 ** Now write out the computed register values
3610 ** IMPORTANT: There is a required order for writing
3611 ** (0x05 must follow all the others).
3612 */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003613 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 -03003614 if (state->tuner_id == MT2063_B0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003615 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003616 status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003617 }
3618 /* Write out the FIFF offset only if it's changing */
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003619 if (state->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003620 (u8) fiffof) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003621 state->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003622 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003623 status |=
Mauro Carvalho Chehabe1de3d12011-07-21 02:46:49 -03003624 mt2063_write(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003625 MT2063_REG_FIFF_OFFSET,
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003626 &state->
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003627 reg[MT2063_REG_FIFF_OFFSET],
3628 1);
3629 }
3630 }
3631
3632 /*
3633 ** Check for LO's locking
3634 */
3635
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003636 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003637 status |= MT2063_GetLocked(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003638 }
3639 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003640 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003641 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003642 if (status >= 0) {
Mauro Carvalho Chehabdcd52d22011-07-21 02:25:39 -03003643 state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003644 }
3645 }
3646
3647 return (status);
3648}
3649
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003650static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003651 enum MTTune_atv_standard tv_type)
3652{
3653
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003654 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003655
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003656 s32 pict_car = 0;
3657 s32 pict2chanb_vsb = 0;
3658 s32 pict2chanb_snd = 0;
3659 s32 pict2snd1 = 0;
3660 s32 pict2snd2 = 0;
3661 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003662
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003663 s32 if_mid = 0;
3664 s32 rcvr_mode = 0;
3665 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003666
3667 switch (tv_type) {
3668 case MTTUNEA_PAL_B:{
3669 pict_car = 38900000;
3670 ch_bw = 8000000;
3671 pict2chanb_vsb = -1250000;
3672 pict2snd1 = 5500000;
3673 pict2snd2 = 5742000;
3674 rcvr_mode = 1;
3675 break;
3676 }
3677 case MTTUNEA_PAL_G:{
3678 pict_car = 38900000;
3679 ch_bw = 7000000;
3680 pict2chanb_vsb = -1250000;
3681 pict2snd1 = 5500000;
3682 pict2snd2 = 0;
3683 rcvr_mode = 1;
3684 break;
3685 }
3686 case MTTUNEA_PAL_I:{
3687 pict_car = 38900000;
3688 ch_bw = 8000000;
3689 pict2chanb_vsb = -1250000;
3690 pict2snd1 = 6000000;
3691 pict2snd2 = 0;
3692 rcvr_mode = 1;
3693 break;
3694 }
3695 case MTTUNEA_PAL_L:{
3696 pict_car = 38900000;
3697 ch_bw = 8000000;
3698 pict2chanb_vsb = -1250000;
3699 pict2snd1 = 6500000;
3700 pict2snd2 = 0;
3701 rcvr_mode = 1;
3702 break;
3703 }
3704 case MTTUNEA_PAL_MN:{
3705 pict_car = 38900000;
3706 ch_bw = 6000000;
3707 pict2chanb_vsb = -1250000;
3708 pict2snd1 = 4500000;
3709 pict2snd2 = 0;
3710 rcvr_mode = 1;
3711 break;
3712 }
3713 case MTTUNEA_PAL_DK:{
3714 pict_car = 38900000;
3715 ch_bw = 8000000;
3716 pict2chanb_vsb = -1250000;
3717 pict2snd1 = 6500000;
3718 pict2snd2 = 0;
3719 rcvr_mode = 1;
3720 break;
3721 }
3722 case MTTUNEA_DIGITAL:{
3723 pict_car = 36125000;
3724 ch_bw = 8000000;
3725 pict2chanb_vsb = -(ch_bw / 2);
3726 pict2snd1 = 0;
3727 pict2snd2 = 0;
3728 rcvr_mode = 2;
3729 break;
3730 }
3731 case MTTUNEA_FMRADIO:{
3732 pict_car = 38900000;
3733 ch_bw = 8000000;
3734 pict2chanb_vsb = -(ch_bw / 2);
3735 pict2snd1 = 0;
3736 pict2snd2 = 0;
3737 rcvr_mode = 4;
3738 //f_in -= 2900000;
3739 break;
3740 }
3741 case MTTUNEA_DVBC:{
3742 pict_car = 36125000;
3743 ch_bw = 8000000;
3744 pict2chanb_vsb = -(ch_bw / 2);
3745 pict2snd1 = 0;
3746 pict2snd2 = 0;
3747 rcvr_mode = MT2063_CABLE_QAM;
3748 break;
3749 }
3750 case MTTUNEA_DVBT:{
3751 pict_car = 36125000;
3752 ch_bw = bw_in; //8000000
3753 pict2chanb_vsb = -(ch_bw / 2);
3754 pict2snd1 = 0;
3755 pict2snd2 = 0;
3756 rcvr_mode = MT2063_OFFAIR_COFDM;
3757 break;
3758 }
3759 case MTTUNEA_UNKNOWN:
3760 break;
3761 default:
3762 break;
3763 }
3764
3765 pict2chanb_snd = pict2chanb_vsb - ch_bw;
3766 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
3767
3768 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
3769 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
3770 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
3771 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3772
3773 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
3774 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
3775 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
3776
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003777 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003778}
3779
3780static int mt2063_init(struct dvb_frontend *fe)
3781{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003782 u32 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003783 struct mt2063_state *state = fe->tuner_priv;
3784
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003785 status = MT2063_Open(fe);
3786 status |= MT2063_SoftwareShutdown(state, 1);
3787 status |= MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003788
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003789 if (0 != status) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003790 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
3791 status);
3792 return -1;
3793 }
3794
3795 return 0;
3796}
3797
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003798static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
3799{
3800 int rc = 0;
3801
3802 //get tuner lock status
3803
3804 return rc;
3805}
3806
3807static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003808 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003809{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003810 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003811
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003812 switch (param) {
3813 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003814 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003815 break;
3816 case DVBFE_TUNER_TUNERSTEP:
3817 break;
3818 case DVBFE_TUNER_IFFREQ:
3819 break;
3820 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003821 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003822 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003823 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003824 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003825 break;
3826 default:
3827 break;
3828 }
3829
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003830 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003831}
3832
3833static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003834 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003835{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003836 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003837 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003838
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003839 switch (param) {
3840 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003841 //set frequency
3842
3843 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003844 MT_Tune_atv(state,
3845 tunstate->frequency, tunstate->bandwidth,
3846 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003847
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003848 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003849 break;
3850 case DVBFE_TUNER_TUNERSTEP:
3851 break;
3852 case DVBFE_TUNER_IFFREQ:
3853 break;
3854 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003855 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003856 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003857 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003858 case DVBFE_TUNER_REFCLOCK:
3859
3860 break;
3861 case DVBFE_TUNER_OPEN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003862 status = MT2063_Open(fe);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003863 break;
3864 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003865 status = MT2063_SoftwareShutdown(state, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003866 break;
3867 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
3868 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003869 MT2063_ClearPowerMaskBits(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003870 MT2063_ALL_SD);
3871 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003872 default:
3873 break;
3874 }
3875
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003876 return (int)status;
3877}
3878
3879static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003880{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003881 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003882
3883 fe->tuner_priv = NULL;
3884 kfree(state);
3885
3886 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003887}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003888
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003889static struct dvb_tuner_ops mt2063_ops = {
3890 .info = {
3891 .name = "MT2063 Silicon Tuner",
3892 .frequency_min = 45000000,
3893 .frequency_max = 850000000,
3894 .frequency_step = 0,
3895 },
3896
3897 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03003898 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003899 .get_status = mt2063_get_status,
3900 .get_state = mt2063_get_state,
3901 .set_state = mt2063_set_state,
3902 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003903};
3904
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003905struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
3906 struct mt2063_config *config,
3907 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003908{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003909 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003910
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003911 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003912 if (state == NULL)
3913 goto error;
3914
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003915 state->config = config;
3916 state->i2c = i2c;
3917 state->frontend = fe;
3918 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003919 state->MT2063_init = false;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003920 fe->tuner_priv = state;
3921 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003922
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003923 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003924 return fe;
3925
3926error:
3927 kfree(state);
3928 return NULL;
3929}
3930
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003931EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03003932MODULE_PARM_DESC(verbose, "Set Verbosity level");
3933
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003934MODULE_AUTHOR("Henry");
3935MODULE_DESCRIPTION("MT2063 Silicon tuner");
3936MODULE_LICENSE("GPL");