Commit | Line | Data |
---|---|---|
223c7b05 MCC |
1 | #include <linux/init.h> |
2 | #include <linux/kernel.h> | |
3 | #include <linux/module.h> | |
4 | #include <linux/string.h> | |
0e301442 | 5 | |
0e301442 MCC |
6 | #include "mt2063.h" |
7 | ||
223c7b05 | 8 | static unsigned int verbose; |
0e301442 MCC |
9 | module_param(verbose, int, 0644); |
10 | ||
6d3d748a MCC |
11 | /* Internal structures and types */ |
12 | ||
29a0a4fe | 13 | /* FIXME: Those two error codes need conversion*/ |
6d3d748a MCC |
14 | /* Error: Upconverter PLL is not locked */ |
15 | #define MT2063_UPC_UNLOCK (0x80000002) | |
6d3d748a MCC |
16 | /* Error: Downconverter PLL is not locked */ |
17 | #define MT2063_DNC_UNLOCK (0x80000004) | |
29a0a4fe | 18 | |
fdf77a4f | 19 | /* Info: Unavoidable LO-related spur may be present in the output */ |
29a0a4fe | 20 | #define MT2063_SPUR_PRESENT_ERR (0x00800000) |
6d3d748a MCC |
21 | |
22 | /* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */ | |
23 | #define MT2063_SPUR_CNT_MASK (0x001f0000) | |
24 | #define MT2063_SPUR_SHIFT (16) | |
25 | ||
6d3d748a MCC |
26 | /* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */ |
27 | #define MT2063_UPC_RANGE (0x04000000) | |
28 | ||
29 | /* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */ | |
30 | #define MT2063_DNC_RANGE (0x08000000) | |
31 | ||
29a0a4fe MCC |
32 | /* |
33 | * Data Types | |
34 | */ | |
35 | ||
6d3d748a MCC |
36 | /* |
37 | * Constant defining the version of the following structure | |
38 | * and therefore the API for this code. | |
39 | * | |
40 | * When compiling the tuner driver, the preprocessor will | |
41 | * check against this version number to make sure that | |
42 | * it matches the version that the tuner driver knows about. | |
43 | */ | |
6d3d748a MCC |
44 | |
45 | /* DECT Frequency Avoidance */ | |
46 | #define MT2063_DECT_AVOID_US_FREQS 0x00000001 | |
47 | ||
48 | #define MT2063_DECT_AVOID_EURO_FREQS 0x00000002 | |
49 | ||
50 | #define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0) | |
51 | ||
52 | #define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0) | |
53 | ||
54 | enum MT2063_DECT_Avoid_Type { | |
55 | MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */ | |
56 | MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */ | |
57 | MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */ | |
58 | MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */ | |
59 | }; | |
60 | ||
61 | #define MT2063_MAX_ZONES 48 | |
62 | ||
6d3d748a MCC |
63 | struct MT2063_ExclZone_t { |
64 | u32 min_; | |
65 | u32 max_; | |
66 | struct MT2063_ExclZone_t *next_; | |
67 | }; | |
68 | ||
69 | /* | |
70 | * Structure of data needed for Spur Avoidance | |
71 | */ | |
72 | struct MT2063_AvoidSpursData_t { | |
6d3d748a MCC |
73 | u32 f_ref; |
74 | u32 f_in; | |
75 | u32 f_LO1; | |
76 | u32 f_if1_Center; | |
77 | u32 f_if1_Request; | |
78 | u32 f_if1_bw; | |
79 | u32 f_LO2; | |
80 | u32 f_out; | |
81 | u32 f_out_bw; | |
82 | u32 f_LO1_Step; | |
83 | u32 f_LO2_Step; | |
84 | u32 f_LO1_FracN_Avoid; | |
85 | u32 f_LO2_FracN_Avoid; | |
86 | u32 f_zif_bw; | |
87 | u32 f_min_LO_Separation; | |
88 | u32 maxH1; | |
89 | u32 maxH2; | |
90 | enum MT2063_DECT_Avoid_Type avoidDECT; | |
91 | u32 bSpurPresent; | |
92 | u32 bSpurAvoided; | |
93 | u32 nSpursFound; | |
94 | u32 nZones; | |
95 | struct MT2063_ExclZone_t *freeZones; | |
96 | struct MT2063_ExclZone_t *usedZones; | |
97 | struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES]; | |
98 | }; | |
99 | ||
6d3d748a MCC |
100 | /* |
101 | * Parameter for function MT2063_SetPowerMask that specifies the power down | |
102 | * of various sections of the MT2063. | |
103 | */ | |
104 | enum MT2063_Mask_Bits { | |
105 | MT2063_REG_SD = 0x0040, /* Shutdown regulator */ | |
106 | MT2063_SRO_SD = 0x0020, /* Shutdown SRO */ | |
107 | MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */ | |
108 | MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */ | |
109 | MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */ | |
110 | MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */ | |
111 | MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */ | |
112 | MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */ | |
113 | MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */ | |
114 | MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */ | |
115 | MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */ | |
116 | MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */ | |
117 | MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */ | |
118 | MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */ | |
119 | MT2063_NONE_SD = 0x0000 /* No shutdown bits */ | |
120 | }; | |
121 | ||
122 | /* | |
123 | * Parameter for function MT2063_GetParam & MT2063_SetParam that | |
124 | * specifies the tuning algorithm parameter to be read/written. | |
125 | */ | |
126 | enum MT2063_Param { | |
127 | /* tuner address set by MT2063_Open() */ | |
128 | MT2063_IC_ADDR, | |
129 | ||
130 | /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */ | |
131 | MT2063_MAX_OPEN, | |
132 | ||
133 | /* current number of open MT2063 tuners set by MT2063_Open() */ | |
134 | MT2063_NUM_OPEN, | |
135 | ||
136 | /* crystal frequency (default: 16000000 Hz) */ | |
137 | MT2063_SRO_FREQ, | |
138 | ||
139 | /* min tuning step size (default: 50000 Hz) */ | |
140 | MT2063_STEPSIZE, | |
141 | ||
142 | /* input center frequency set by MT2063_Tune() */ | |
143 | MT2063_INPUT_FREQ, | |
144 | ||
145 | /* LO1 Frequency set by MT2063_Tune() */ | |
146 | MT2063_LO1_FREQ, | |
147 | ||
148 | /* LO1 minimum step size (default: 250000 Hz) */ | |
149 | MT2063_LO1_STEPSIZE, | |
150 | ||
151 | /* LO1 FracN keep-out region (default: 999999 Hz) */ | |
152 | MT2063_LO1_FRACN_AVOID_PARAM, | |
153 | ||
154 | /* Current 1st IF in use set by MT2063_Tune() */ | |
155 | MT2063_IF1_ACTUAL, | |
156 | ||
157 | /* Requested 1st IF set by MT2063_Tune() */ | |
158 | MT2063_IF1_REQUEST, | |
159 | ||
160 | /* Center of 1st IF SAW filter (default: 1218000000 Hz) */ | |
161 | MT2063_IF1_CENTER, | |
162 | ||
163 | /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */ | |
164 | MT2063_IF1_BW, | |
165 | ||
166 | /* zero-IF bandwidth (default: 2000000 Hz) */ | |
167 | MT2063_ZIF_BW, | |
168 | ||
169 | /* LO2 Frequency set by MT2063_Tune() */ | |
170 | MT2063_LO2_FREQ, | |
171 | ||
172 | /* LO2 minimum step size (default: 50000 Hz) */ | |
173 | MT2063_LO2_STEPSIZE, | |
174 | ||
175 | /* LO2 FracN keep-out region (default: 374999 Hz) */ | |
176 | MT2063_LO2_FRACN_AVOID, | |
177 | ||
178 | /* output center frequency set by MT2063_Tune() */ | |
179 | MT2063_OUTPUT_FREQ, | |
180 | ||
181 | /* output bandwidth set by MT2063_Tune() */ | |
182 | MT2063_OUTPUT_BW, | |
183 | ||
184 | /* min inter-tuner LO separation (default: 1000000 Hz) */ | |
185 | MT2063_LO_SEPARATION, | |
186 | ||
187 | /* ID of avoid-spurs algorithm in use compile-time constant */ | |
188 | MT2063_AS_ALG, | |
189 | ||
190 | /* max # of intra-tuner harmonics (default: 15) */ | |
191 | MT2063_MAX_HARM1, | |
192 | ||
193 | /* max # of inter-tuner harmonics (default: 7) */ | |
194 | MT2063_MAX_HARM2, | |
195 | ||
196 | /* # of 1st IF exclusion zones used set by MT2063_Tune() */ | |
197 | MT2063_EXCL_ZONES, | |
198 | ||
199 | /* # of spurs found/avoided set by MT2063_Tune() */ | |
200 | MT2063_NUM_SPURS, | |
201 | ||
202 | /* >0 spurs avoided set by MT2063_Tune() */ | |
203 | MT2063_SPUR_AVOIDED, | |
204 | ||
205 | /* >0 spurs in output (mathematically) set by MT2063_Tune() */ | |
206 | MT2063_SPUR_PRESENT, | |
207 | ||
208 | /* Receiver Mode for some parameters. 1 is DVB-T */ | |
209 | MT2063_RCVR_MODE, | |
210 | ||
211 | /* directly set LNA attenuation, parameter is value to set */ | |
212 | MT2063_ACLNA, | |
213 | ||
214 | /* maximum LNA attenuation, parameter is value to set */ | |
215 | MT2063_ACLNA_MAX, | |
216 | ||
217 | /* directly set ATN attenuation. Paremeter is value to set. */ | |
218 | MT2063_ACRF, | |
219 | ||
220 | /* maxium ATN attenuation. Paremeter is value to set. */ | |
221 | MT2063_ACRF_MAX, | |
222 | ||
223 | /* directly set FIF attenuation. Paremeter is value to set. */ | |
224 | MT2063_ACFIF, | |
225 | ||
226 | /* maxium FIF attenuation. Paremeter is value to set. */ | |
227 | MT2063_ACFIF_MAX, | |
228 | ||
229 | /* LNA Rin */ | |
230 | MT2063_LNA_RIN, | |
231 | ||
232 | /* Power Detector LNA level target */ | |
233 | MT2063_LNA_TGT, | |
234 | ||
235 | /* Power Detector 1 level */ | |
236 | MT2063_PD1, | |
237 | ||
238 | /* Power Detector 1 level target */ | |
239 | MT2063_PD1_TGT, | |
240 | ||
241 | /* Power Detector 2 level */ | |
242 | MT2063_PD2, | |
243 | ||
244 | /* Power Detector 2 level target */ | |
245 | MT2063_PD2_TGT, | |
246 | ||
247 | /* Selects, which DNC is activ */ | |
248 | MT2063_DNC_OUTPUT_ENABLE, | |
249 | ||
250 | /* VGA gain code */ | |
251 | MT2063_VGAGC, | |
252 | ||
253 | /* VGA bias current */ | |
254 | MT2063_VGAOI, | |
255 | ||
256 | /* TAGC, determins the speed of the AGC */ | |
257 | MT2063_TAGC, | |
258 | ||
259 | /* AMP gain code */ | |
260 | MT2063_AMPGC, | |
261 | ||
262 | /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */ | |
263 | MT2063_AVOID_DECT, | |
264 | ||
265 | /* Cleartune filter selection: 0 - by IC (default), 1 - by software */ | |
266 | MT2063_CTFILT_SW, | |
267 | ||
268 | MT2063_EOP /* last entry in enumerated list */ | |
269 | }; | |
270 | ||
271 | /* | |
272 | * Parameter for selecting tuner mode | |
273 | */ | |
274 | enum MT2063_RCVR_MODES { | |
275 | MT2063_CABLE_QAM = 0, /* Digital cable */ | |
276 | MT2063_CABLE_ANALOG, /* Analog cable */ | |
277 | MT2063_OFFAIR_COFDM, /* Digital offair */ | |
278 | MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */ | |
279 | MT2063_OFFAIR_ANALOG, /* Analog offair */ | |
280 | MT2063_OFFAIR_8VSB, /* Analog offair */ | |
281 | MT2063_NUM_RCVR_MODES | |
282 | }; | |
283 | ||
284 | /* | |
285 | * Possible values for MT2063_DNC_OUTPUT | |
286 | */ | |
287 | enum MT2063_DNC_Output_Enable { | |
288 | MT2063_DNC_NONE = 0, | |
289 | MT2063_DNC_1, | |
290 | MT2063_DNC_2, | |
291 | MT2063_DNC_BOTH | |
292 | }; | |
293 | ||
294 | /* | |
295 | ** Two-wire serial bus subaddresses of the tuner registers. | |
296 | ** Also known as the tuner's register addresses. | |
297 | */ | |
298 | enum MT2063_Register_Offsets { | |
299 | MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */ | |
300 | MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */ | |
301 | MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */ | |
302 | MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */ | |
303 | MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */ | |
304 | MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */ | |
305 | MT2063_REG_RSVD_06, /* 0x06: Reserved */ | |
306 | MT2063_REG_LO_STATUS, /* 0x07: LO Status */ | |
307 | MT2063_REG_FIFFC, /* 0x08: FIFF Center */ | |
308 | MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */ | |
309 | MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */ | |
310 | MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */ | |
311 | MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */ | |
312 | MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */ | |
313 | MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */ | |
314 | MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */ | |
315 | MT2063_REG_RSVD_10, /* 0x10: Reserved */ | |
316 | MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */ | |
317 | MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */ | |
318 | MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */ | |
319 | MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */ | |
320 | MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */ | |
321 | MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */ | |
322 | MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */ | |
323 | MT2063_REG_RF_OV, /* 0x18: RF Attn Override */ | |
324 | MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */ | |
325 | MT2063_REG_LNA_TGT, /* 0x1A: Reserved */ | |
326 | MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */ | |
327 | MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */ | |
328 | MT2063_REG_RSVD_1D, /* 0x1D: Reserved */ | |
329 | MT2063_REG_RSVD_1E, /* 0x1E: Reserved */ | |
330 | MT2063_REG_RSVD_1F, /* 0x1F: Reserved */ | |
331 | MT2063_REG_RSVD_20, /* 0x20: Reserved */ | |
332 | MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */ | |
333 | MT2063_REG_RSVD_22, /* 0x22: Reserved */ | |
334 | MT2063_REG_RSVD_23, /* 0x23: Reserved */ | |
335 | MT2063_REG_RSVD_24, /* 0x24: Reserved */ | |
336 | MT2063_REG_RSVD_25, /* 0x25: Reserved */ | |
337 | MT2063_REG_RSVD_26, /* 0x26: Reserved */ | |
338 | MT2063_REG_RSVD_27, /* 0x27: Reserved */ | |
339 | MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */ | |
340 | MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */ | |
341 | MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */ | |
342 | MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */ | |
343 | MT2063_REG_CTRL_2C, /* 0x2C: Reserved */ | |
344 | MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */ | |
345 | MT2063_REG_RSVD_2E, /* 0x2E: Reserved */ | |
346 | MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */ | |
347 | MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */ | |
348 | MT2063_REG_RSVD_31, /* 0x31: Reserved */ | |
349 | MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */ | |
350 | MT2063_REG_RSVD_33, /* 0x33: Reserved */ | |
351 | MT2063_REG_RSVD_34, /* 0x34: Reserved */ | |
352 | MT2063_REG_RSVD_35, /* 0x35: Reserved */ | |
353 | MT2063_REG_RSVD_36, /* 0x36: Reserved */ | |
354 | MT2063_REG_RSVD_37, /* 0x37: Reserved */ | |
355 | MT2063_REG_RSVD_38, /* 0x38: Reserved */ | |
356 | MT2063_REG_RSVD_39, /* 0x39: Reserved */ | |
357 | MT2063_REG_RSVD_3A, /* 0x3A: Reserved */ | |
358 | MT2063_REG_RSVD_3B, /* 0x3B: Reserved */ | |
359 | MT2063_REG_RSVD_3C, /* 0x3C: Reserved */ | |
360 | MT2063_REG_END_REGS | |
361 | }; | |
362 | ||
6d3d748a MCC |
363 | enum MTTune_atv_standard { |
364 | MTTUNEA_UNKNOWN = 0, | |
365 | MTTUNEA_PAL_B, | |
366 | MTTUNEA_PAL_G, | |
367 | MTTUNEA_PAL_I, | |
368 | MTTUNEA_PAL_L, | |
369 | MTTUNEA_PAL_MN, | |
370 | MTTUNEA_PAL_DK, | |
371 | MTTUNEA_DIGITAL, | |
372 | MTTUNEA_FMRADIO, | |
373 | MTTUNEA_DVBC, | |
374 | MTTUNEA_DVBT | |
375 | }; | |
376 | ||
377 | ||
378 | struct mt2063_state { | |
379 | struct i2c_adapter *i2c; | |
380 | ||
381 | const struct mt2063_config *config; | |
382 | struct dvb_tuner_ops ops; | |
383 | struct dvb_frontend *frontend; | |
384 | struct tuner_state status; | |
6d3d748a MCC |
385 | |
386 | enum MTTune_atv_standard tv_type; | |
387 | u32 frequency; | |
388 | u32 srate; | |
389 | u32 bandwidth; | |
390 | u32 reference; | |
51f0f7b3 MCC |
391 | |
392 | u32 tuner_id; | |
393 | struct MT2063_AvoidSpursData_t AS_Data; | |
394 | u32 f_IF1_actual; | |
395 | u32 rcvr_mode; | |
396 | u32 ctfilt_sw; | |
397 | u32 CTFiltMax[31]; | |
398 | u32 num_regs; | |
399 | u8 reg[MT2063_REG_END_REGS]; | |
6d3d748a | 400 | }; |
0ff48432 | 401 | |
bf97555e MCC |
402 | /* Prototypes */ |
403 | static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info, | |
404 | u32 f_min, u32 f_max); | |
dcd52d20 MCC |
405 | static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val); |
406 | static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 * pValue); | |
407 | static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val); | |
408 | static u32 MT2063_SetParam(struct mt2063_state *state, enum MT2063_Param param, | |
29a0a4fe | 409 | enum MT2063_DNC_Output_Enable nValue); |
8c64f932 MCC |
410 | static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown); |
411 | static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits); | |
412 | ||
bf97555e | 413 | |
0ff48432 MCC |
414 | /*****************/ |
415 | /* From drivers/media/common/tuners/mt2063_cfg.h */ | |
416 | ||
f867695a | 417 | unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in, |
51f0f7b3 MCC |
418 | u32 bw_in, |
419 | enum MTTune_atv_standard tv_type) | |
0ff48432 | 420 | { |
0ff48432 MCC |
421 | struct dvb_frontend_ops *frontend_ops = NULL; |
422 | struct dvb_tuner_ops *tuner_ops = NULL; | |
423 | struct tuner_state t_state; | |
51f0f7b3 | 424 | struct mt2063_state *state = fe->tuner_priv; |
0ff48432 MCC |
425 | int err = 0; |
426 | ||
427 | t_state.frequency = f_in; | |
428 | t_state.bandwidth = bw_in; | |
51f0f7b3 | 429 | state->tv_type = tv_type; |
0ff48432 MCC |
430 | if (&fe->ops) |
431 | frontend_ops = &fe->ops; | |
432 | if (&frontend_ops->tuner_ops) | |
433 | tuner_ops = &frontend_ops->tuner_ops; | |
434 | if (tuner_ops->set_state) { | |
435 | if ((err = | |
436 | tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, | |
437 | &t_state)) < 0) { | |
438 | printk("%s: Invalid parameter\n", __func__); | |
439 | return err; | |
440 | } | |
441 | } | |
442 | ||
443 | return err; | |
444 | } | |
445 | ||
f867695a | 446 | unsigned int mt2063_lockStatus(struct dvb_frontend *fe) |
0ff48432 MCC |
447 | { |
448 | struct dvb_frontend_ops *frontend_ops = &fe->ops; | |
449 | struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; | |
450 | struct tuner_state t_state; | |
451 | int err = 0; | |
452 | ||
453 | if (&fe->ops) | |
454 | frontend_ops = &fe->ops; | |
455 | if (&frontend_ops->tuner_ops) | |
456 | tuner_ops = &frontend_ops->tuner_ops; | |
457 | if (tuner_ops->get_state) { | |
458 | if ((err = | |
459 | tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK, | |
460 | &t_state)) < 0) { | |
461 | printk("%s: Invalid parameter\n", __func__); | |
462 | return err; | |
463 | } | |
464 | } | |
465 | return err; | |
466 | } | |
467 | ||
0ff48432 | 468 | |
f867695a | 469 | unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe) |
0ff48432 | 470 | { |
8c64f932 | 471 | struct mt2063_state *state = fe->tuner_priv; |
0ff48432 MCC |
472 | struct dvb_frontend_ops *frontend_ops = &fe->ops; |
473 | struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; | |
0ff48432 MCC |
474 | int err = 0; |
475 | ||
476 | if (&fe->ops) | |
477 | frontend_ops = &fe->ops; | |
478 | if (&frontend_ops->tuner_ops) | |
479 | tuner_ops = &frontend_ops->tuner_ops; | |
480 | if (tuner_ops->set_state) { | |
8c64f932 MCC |
481 | err = MT2063_SoftwareShutdown(state, 1); |
482 | if (err < 0) { | |
0ff48432 MCC |
483 | printk("%s: Invalid parameter\n", __func__); |
484 | return err; | |
485 | } | |
486 | } | |
487 | ||
488 | return err; | |
489 | } | |
490 | ||
f867695a | 491 | unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe) |
0ff48432 | 492 | { |
8c64f932 | 493 | struct mt2063_state *state = fe->tuner_priv; |
0ff48432 MCC |
494 | struct dvb_frontend_ops *frontend_ops = &fe->ops; |
495 | struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; | |
0ff48432 MCC |
496 | int err = 0; |
497 | ||
498 | if (&fe->ops) | |
499 | frontend_ops = &fe->ops; | |
500 | if (&frontend_ops->tuner_ops) | |
501 | tuner_ops = &frontend_ops->tuner_ops; | |
502 | if (tuner_ops->set_state) { | |
8c64f932 MCC |
503 | err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD); |
504 | if (err < 0) { | |
0ff48432 MCC |
505 | printk("%s: Invalid parameter\n", __func__); |
506 | return err; | |
507 | } | |
508 | } | |
509 | ||
510 | return err; | |
511 | } | |
512 | ||
e1de3d18 MCC |
513 | /* |
514 | * mt2063_write - Write data into the I2C bus | |
515 | */ | |
516 | static u32 mt2063_write(struct mt2063_state *state, | |
517 | u8 reg, u8 *data, u32 len) | |
0e301442 | 518 | { |
e1de3d18 | 519 | struct dvb_frontend *fe = state->frontend; |
0e301442 | 520 | int ret; |
e1de3d18 | 521 | u8 buf[60]; |
0e301442 MCC |
522 | struct i2c_msg msg = { |
523 | .addr = state->config->tuner_address, | |
524 | .flags = 0, | |
525 | .buf = buf, | |
526 | .len = len + 1 | |
527 | }; | |
528 | ||
e1de3d18 | 529 | msg.buf[0] = reg; |
0e301442 MCC |
530 | memcpy(msg.buf + 1, data, len); |
531 | ||
e1de3d18 | 532 | fe->ops.i2c_gate_ctrl(fe, 1); |
0e301442 | 533 | ret = i2c_transfer(state->i2c, &msg, 1); |
e1de3d18 | 534 | fe->ops.i2c_gate_ctrl(fe, 0); |
0e301442 MCC |
535 | |
536 | if (ret < 0) | |
537 | printk("mt2063_writeregs error ret=%d\n", ret); | |
538 | ||
539 | return ret; | |
540 | } | |
541 | ||
e1de3d18 MCC |
542 | /* |
543 | * mt2063_read - Read data from the I2C bus | |
544 | */ | |
545 | static u32 mt2063_read(struct mt2063_state *state, | |
51f0f7b3 | 546 | u8 subAddress, u8 *pData, u32 cnt) |
0e301442 | 547 | { |
51f0f7b3 MCC |
548 | u32 status = 0; /* Status to be returned */ |
549 | struct dvb_frontend *fe = state->frontend; | |
550 | u32 i = 0; | |
551 | ||
e1de3d18 | 552 | fe->ops.i2c_gate_ctrl(fe, 1); |
0e301442 MCC |
553 | |
554 | for (i = 0; i < cnt; i++) { | |
e1de3d18 MCC |
555 | int ret; |
556 | u8 b0[] = { subAddress + i }; | |
557 | struct i2c_msg msg[] = { | |
558 | { | |
559 | .addr = state->config->tuner_address, | |
560 | .flags = I2C_M_RD, | |
561 | .buf = b0, | |
562 | .len = 1 | |
563 | }, { | |
564 | .addr = state->config->tuner_address, | |
565 | .flags = I2C_M_RD, | |
566 | .buf = pData + 1, | |
567 | .len = 1 | |
568 | } | |
569 | }; | |
570 | ||
571 | ret = i2c_transfer(state->i2c, msg, 2); | |
572 | if (ret < 0) | |
0e301442 | 573 | break; |
0e301442 | 574 | } |
e1de3d18 | 575 | fe->ops.i2c_gate_ctrl(fe, 0); |
0e301442 MCC |
576 | return (status); |
577 | } | |
578 | ||
e930b3a0 MCC |
579 | /* |
580 | * FIXME: Is this really needed? | |
581 | */ | |
f867695a | 582 | static int MT2063_Sleep(struct dvb_frontend *fe) |
0e301442 MCC |
583 | { |
584 | /* | |
585 | ** ToDo: Add code here to implement a OS blocking | |
586 | ** for a period of "nMinDelayTime" milliseconds. | |
587 | */ | |
f867695a MCC |
588 | msleep(10); |
589 | ||
590 | return 0; | |
0e301442 MCC |
591 | } |
592 | ||
e930b3a0 MCC |
593 | /* |
594 | * Microtune spur avoidance | |
595 | */ | |
0e301442 MCC |
596 | |
597 | /* Implement ceiling, floor functions. */ | |
598 | #define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0)) | |
0e301442 | 599 | #define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d)) |
0e301442 MCC |
600 | |
601 | struct MT2063_FIFZone_t { | |
cfde8925 MCC |
602 | s32 min_; |
603 | s32 max_; | |
0e301442 MCC |
604 | }; |
605 | ||
0e301442 MCC |
606 | /* |
607 | ** Reset all exclusion zones. | |
608 | ** Add zones to protect the PLL FracN regions near zero | |
609 | ** | |
610 | ** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT | |
611 | ** frequencies into MT_ResetExclZones(). | |
612 | */ | |
bf97555e | 613 | static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info) |
0e301442 | 614 | { |
cfde8925 | 615 | u32 center; |
0e301442 MCC |
616 | |
617 | pAS_Info->nZones = 0; /* this clears the used list */ | |
618 | pAS_Info->usedZones = NULL; /* reset ptr */ | |
619 | pAS_Info->freeZones = NULL; /* reset ptr */ | |
620 | ||
621 | center = | |
622 | pAS_Info->f_ref * | |
623 | ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 + | |
624 | pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in; | |
625 | while (center < | |
626 | pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 + | |
627 | pAS_Info->f_LO1_FracN_Avoid) { | |
628 | /* Exclude LO1 FracN */ | |
629 | MT2063_AddExclZone(pAS_Info, | |
630 | center - pAS_Info->f_LO1_FracN_Avoid, | |
631 | center - 1); | |
632 | MT2063_AddExclZone(pAS_Info, center + 1, | |
633 | center + pAS_Info->f_LO1_FracN_Avoid); | |
634 | center += pAS_Info->f_ref; | |
635 | } | |
636 | ||
637 | center = | |
638 | pAS_Info->f_ref * | |
639 | ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 - | |
640 | pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out; | |
641 | while (center < | |
642 | pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 + | |
643 | pAS_Info->f_LO2_FracN_Avoid) { | |
644 | /* Exclude LO2 FracN */ | |
645 | MT2063_AddExclZone(pAS_Info, | |
646 | center - pAS_Info->f_LO2_FracN_Avoid, | |
647 | center - 1); | |
648 | MT2063_AddExclZone(pAS_Info, center + 1, | |
649 | center + pAS_Info->f_LO2_FracN_Avoid); | |
650 | center += pAS_Info->f_ref; | |
651 | } | |
652 | ||
653 | if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) { | |
654 | /* Exclude LO1 values that conflict with DECT channels */ | |
655 | MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */ | |
656 | MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */ | |
657 | MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */ | |
658 | MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */ | |
659 | MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */ | |
660 | } | |
661 | ||
662 | if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) { | |
663 | MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */ | |
664 | MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */ | |
665 | MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */ | |
666 | MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */ | |
667 | MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */ | |
668 | MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */ | |
669 | MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */ | |
670 | MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */ | |
671 | MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */ | |
672 | MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */ | |
673 | } | |
0e301442 MCC |
674 | } |
675 | ||
676 | static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t | |
677 | *pAS_Info, | |
678 | struct MT2063_ExclZone_t *pPrevNode) | |
679 | { | |
680 | struct MT2063_ExclZone_t *pNode; | |
681 | /* Check for a node in the free list */ | |
682 | if (pAS_Info->freeZones != NULL) { | |
683 | /* Use one from the free list */ | |
684 | pNode = pAS_Info->freeZones; | |
685 | pAS_Info->freeZones = pNode->next_; | |
686 | } else { | |
687 | /* Grab a node from the array */ | |
688 | pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones]; | |
689 | } | |
690 | ||
691 | if (pPrevNode != NULL) { | |
692 | pNode->next_ = pPrevNode->next_; | |
693 | pPrevNode->next_ = pNode; | |
694 | } else { /* insert at the beginning of the list */ | |
695 | ||
696 | pNode->next_ = pAS_Info->usedZones; | |
697 | pAS_Info->usedZones = pNode; | |
698 | } | |
699 | ||
700 | pAS_Info->nZones++; | |
701 | return pNode; | |
702 | } | |
703 | ||
704 | static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t | |
705 | *pAS_Info, | |
706 | struct MT2063_ExclZone_t *pPrevNode, | |
707 | struct MT2063_ExclZone_t | |
708 | *pNodeToRemove) | |
709 | { | |
710 | struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_; | |
711 | ||
712 | /* Make previous node point to the subsequent node */ | |
713 | if (pPrevNode != NULL) | |
714 | pPrevNode->next_ = pNext; | |
715 | ||
716 | /* Add pNodeToRemove to the beginning of the freeZones */ | |
717 | pNodeToRemove->next_ = pAS_Info->freeZones; | |
718 | pAS_Info->freeZones = pNodeToRemove; | |
719 | ||
720 | /* Decrement node count */ | |
721 | pAS_Info->nZones--; | |
722 | ||
723 | return pNext; | |
724 | } | |
725 | ||
726 | /***************************************************************************** | |
727 | ** | |
728 | ** Name: MT_AddExclZone | |
729 | ** | |
730 | ** Description: Add (and merge) an exclusion zone into the list. | |
731 | ** If the range (f_min, f_max) is totally outside the | |
732 | ** 1st IF BW, ignore the entry. | |
733 | ** If the range (f_min, f_max) is negative, ignore the entry. | |
734 | ** | |
735 | ** Revision History: | |
736 | ** | |
737 | ** SCR Date Author Description | |
738 | ** ------------------------------------------------------------------------- | |
739 | ** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range | |
740 | ** (f_min, f_max) < 0, ignore the entry. | |
741 | ** | |
742 | *****************************************************************************/ | |
bf97555e | 743 | static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info, |
cfde8925 | 744 | u32 f_min, u32 f_max) |
0e301442 MCC |
745 | { |
746 | struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones; | |
747 | struct MT2063_ExclZone_t *pPrev = NULL; | |
748 | struct MT2063_ExclZone_t *pNext = NULL; | |
749 | ||
750 | /* Check to see if this overlaps the 1st IF filter */ | |
751 | if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2))) | |
752 | && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2))) | |
753 | && (f_min < f_max)) { | |
754 | /* | |
755 | ** 1 2 3 4 5 6 | |
756 | ** | |
757 | ** New entry: |---| |--| |--| |-| |---| |--| | |
758 | ** or or or or or | |
759 | ** Existing: |--| |--| |--| |---| |-| |--| | |
760 | */ | |
761 | ||
762 | /* Check for our place in the list */ | |
763 | while ((pNode != NULL) && (pNode->max_ < f_min)) { | |
764 | pPrev = pNode; | |
765 | pNode = pNode->next_; | |
766 | } | |
767 | ||
768 | if ((pNode != NULL) && (pNode->min_ < f_max)) { | |
769 | /* Combine me with pNode */ | |
770 | if (f_min < pNode->min_) | |
771 | pNode->min_ = f_min; | |
772 | if (f_max > pNode->max_) | |
773 | pNode->max_ = f_max; | |
774 | } else { | |
775 | pNode = InsertNode(pAS_Info, pPrev); | |
776 | pNode->min_ = f_min; | |
777 | pNode->max_ = f_max; | |
778 | } | |
779 | ||
780 | /* Look for merging possibilities */ | |
781 | pNext = pNode->next_; | |
782 | while ((pNext != NULL) && (pNext->min_ < pNode->max_)) { | |
783 | if (pNext->max_ > pNode->max_) | |
784 | pNode->max_ = pNext->max_; | |
785 | pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */ | |
786 | } | |
787 | } | |
788 | } | |
789 | ||
790 | /***************************************************************************** | |
791 | ** | |
792 | ** Name: MT_ChooseFirstIF | |
793 | ** | |
794 | ** Description: Choose the best available 1st IF | |
795 | ** If f_Desired is not excluded, choose that first. | |
796 | ** Otherwise, return the value closest to f_Center that is | |
797 | ** not excluded | |
798 | ** | |
799 | ** Revision History: | |
800 | ** | |
801 | ** SCR Date Author Description | |
802 | ** ------------------------------------------------------------------------- | |
803 | ** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from | |
804 | ** tuner DLL. | |
805 | ** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+) | |
806 | ** Added logic to force f_Center within 1/2 f_Step. | |
807 | ** | |
808 | *****************************************************************************/ | |
bf97555e | 809 | static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info) |
0e301442 MCC |
810 | { |
811 | /* | |
812 | ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step". | |
813 | ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum | |
814 | ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step. | |
815 | ** However, the sum must be. | |
816 | */ | |
cfde8925 | 817 | const u32 f_Desired = |
0e301442 MCC |
818 | pAS_Info->f_LO1_Step * |
819 | ((pAS_Info->f_if1_Request + pAS_Info->f_in + | |
820 | pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) - | |
821 | pAS_Info->f_in; | |
cfde8925 | 822 | const u32 f_Step = |
0e301442 MCC |
823 | (pAS_Info->f_LO1_Step > |
824 | pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info-> | |
825 | f_LO2_Step; | |
cfde8925 MCC |
826 | u32 f_Center; |
827 | ||
828 | s32 i; | |
829 | s32 j = 0; | |
830 | u32 bDesiredExcluded = 0; | |
831 | u32 bZeroExcluded = 0; | |
832 | s32 tmpMin, tmpMax; | |
833 | s32 bestDiff; | |
0e301442 MCC |
834 | struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones; |
835 | struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES]; | |
836 | ||
837 | if (pAS_Info->nZones == 0) | |
838 | return f_Desired; | |
839 | ||
840 | /* f_Center needs to be an integer multiple of f_Step away from f_Desired */ | |
841 | if (pAS_Info->f_if1_Center > f_Desired) | |
842 | f_Center = | |
843 | f_Desired + | |
844 | f_Step * | |
845 | ((pAS_Info->f_if1_Center - f_Desired + | |
846 | f_Step / 2) / f_Step); | |
847 | else | |
848 | f_Center = | |
849 | f_Desired - | |
850 | f_Step * | |
851 | ((f_Desired - pAS_Info->f_if1_Center + | |
852 | f_Step / 2) / f_Step); | |
853 | ||
854 | //assert; | |
cfde8925 | 855 | //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2)) |
0e301442 MCC |
856 | // return 0; |
857 | ||
858 | /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */ | |
859 | while (pNode != NULL) { | |
860 | /* floor function */ | |
861 | tmpMin = | |
cfde8925 | 862 | floor((s32) (pNode->min_ - f_Center), (s32) f_Step); |
0e301442 MCC |
863 | |
864 | /* ceil function */ | |
865 | tmpMax = | |
cfde8925 | 866 | ceil((s32) (pNode->max_ - f_Center), (s32) f_Step); |
0e301442 MCC |
867 | |
868 | if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired)) | |
869 | bDesiredExcluded = 1; | |
870 | ||
871 | if ((tmpMin < 0) && (tmpMax > 0)) | |
872 | bZeroExcluded = 1; | |
873 | ||
874 | /* See if this zone overlaps the previous */ | |
875 | if ((j > 0) && (tmpMin < zones[j - 1].max_)) | |
876 | zones[j - 1].max_ = tmpMax; | |
877 | else { | |
878 | /* Add new zone */ | |
879 | //assert(j<MT2063_MAX_ZONES); | |
880 | //if (j>=MT2063_MAX_ZONES) | |
881 | //break; | |
882 | ||
883 | zones[j].min_ = tmpMin; | |
884 | zones[j].max_ = tmpMax; | |
885 | j++; | |
886 | } | |
887 | pNode = pNode->next_; | |
888 | } | |
889 | ||
890 | /* | |
891 | ** If the desired is okay, return with it | |
892 | */ | |
893 | if (bDesiredExcluded == 0) | |
894 | return f_Desired; | |
895 | ||
896 | /* | |
897 | ** If the desired is excluded and the center is okay, return with it | |
898 | */ | |
899 | if (bZeroExcluded == 0) | |
900 | return f_Center; | |
901 | ||
902 | /* Find the value closest to 0 (f_Center) */ | |
903 | bestDiff = zones[0].min_; | |
904 | for (i = 0; i < j; i++) { | |
905 | if (abs(zones[i].min_) < abs(bestDiff)) | |
906 | bestDiff = zones[i].min_; | |
907 | if (abs(zones[i].max_) < abs(bestDiff)) | |
908 | bestDiff = zones[i].max_; | |
909 | } | |
910 | ||
911 | if (bestDiff < 0) | |
cfde8925 | 912 | return f_Center - ((u32) (-bestDiff) * f_Step); |
0e301442 MCC |
913 | |
914 | return f_Center + (bestDiff * f_Step); | |
915 | } | |
916 | ||
917 | /**************************************************************************** | |
918 | ** | |
919 | ** Name: gcd | |
920 | ** | |
921 | ** Description: Uses Euclid's algorithm | |
922 | ** | |
923 | ** Parameters: u, v - unsigned values whose GCD is desired. | |
924 | ** | |
925 | ** Global: None | |
926 | ** | |
927 | ** Returns: greatest common divisor of u and v, if either value | |
928 | ** is 0, the other value is returned as the result. | |
929 | ** | |
930 | ** Dependencies: None. | |
931 | ** | |
932 | ** Revision History: | |
933 | ** | |
934 | ** SCR Date Author Description | |
935 | ** ------------------------------------------------------------------------- | |
936 | ** N/A 06-01-2004 JWS Original | |
937 | ** N/A 08-03-2004 DAD Changed to Euclid's since it can handle | |
938 | ** unsigned numbers. | |
939 | ** | |
940 | ****************************************************************************/ | |
cfde8925 | 941 | static u32 MT2063_gcd(u32 u, u32 v) |
0e301442 | 942 | { |
cfde8925 | 943 | u32 r; |
0e301442 MCC |
944 | |
945 | while (v != 0) { | |
946 | r = u % v; | |
947 | u = v; | |
948 | v = r; | |
949 | } | |
950 | ||
951 | return u; | |
952 | } | |
953 | ||
954 | /**************************************************************************** | |
955 | ** | |
956 | ** Name: umax | |
957 | ** | |
958 | ** Description: Implements a simple maximum function for unsigned numbers. | |
959 | ** Implemented as a function rather than a macro to avoid | |
960 | ** multiple evaluation of the calling parameters. | |
961 | ** | |
962 | ** Parameters: a, b - Values to be compared | |
963 | ** | |
964 | ** Global: None | |
965 | ** | |
966 | ** Returns: larger of the input values. | |
967 | ** | |
968 | ** Dependencies: None. | |
969 | ** | |
970 | ** Revision History: | |
971 | ** | |
972 | ** SCR Date Author Description | |
973 | ** ------------------------------------------------------------------------- | |
974 | ** N/A 06-02-2004 JWS Original | |
975 | ** | |
976 | ****************************************************************************/ | |
cfde8925 | 977 | static u32 MT2063_umax(u32 a, u32 b) |
0e301442 MCC |
978 | { |
979 | return (a >= b) ? a : b; | |
980 | } | |
981 | ||
0e301442 MCC |
982 | /**************************************************************************** |
983 | ** | |
984 | ** Name: IsSpurInBand | |
985 | ** | |
986 | ** Description: Checks to see if a spur will be present within the IF's | |
987 | ** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW) | |
988 | ** | |
989 | ** ma mb mc md | |
990 | ** <--+-+-+-------------------+-------------------+-+-+--> | |
991 | ** | ^ 0 ^ | | |
992 | ** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^ | |
993 | ** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2 | |
994 | ** | |
995 | ** Note that some equations are doubled to prevent round-off | |
996 | ** problems when calculating fIFBW/2 | |
997 | ** | |
998 | ** Parameters: pAS_Info - Avoid Spurs information block | |
999 | ** fm - If spur, amount f_IF1 has to move negative | |
1000 | ** fp - If spur, amount f_IF1 has to move positive | |
1001 | ** | |
1002 | ** Global: None | |
1003 | ** | |
1004 | ** Returns: 1 if an LO spur would be present, otherwise 0. | |
1005 | ** | |
1006 | ** Dependencies: None. | |
1007 | ** | |
1008 | ** Revision History: | |
1009 | ** | |
1010 | ** SCR Date Author Description | |
1011 | ** ------------------------------------------------------------------------- | |
1012 | ** N/A 11-28-2002 DAD Implemented algorithm from applied patent | |
1013 | ** | |
1014 | ****************************************************************************/ | |
cfde8925 MCC |
1015 | static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info, |
1016 | u32 * fm, u32 * fp) | |
0e301442 MCC |
1017 | { |
1018 | /* | |
1019 | ** Calculate LO frequency settings. | |
1020 | */ | |
cfde8925 MCC |
1021 | u32 n, n0; |
1022 | const u32 f_LO1 = pAS_Info->f_LO1; | |
1023 | const u32 f_LO2 = pAS_Info->f_LO2; | |
1024 | const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2; | |
1025 | const u32 c = d - pAS_Info->f_out_bw; | |
1026 | const u32 f = pAS_Info->f_zif_bw / 2; | |
d0dcc2da | 1027 | const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1; |
cfde8925 MCC |
1028 | s32 f_nsLO1, f_nsLO2; |
1029 | s32 f_Spur; | |
1030 | u32 ma, mb, mc, md, me, mf; | |
1031 | u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs; | |
0e301442 MCC |
1032 | *fm = 0; |
1033 | ||
1034 | /* | |
1035 | ** For each edge (d, c & f), calculate a scale, based on the gcd | |
1036 | ** of f_LO1, f_LO2 and the edge value. Use the larger of this | |
1037 | ** gcd-based scale factor or f_Scale. | |
1038 | */ | |
1039 | lo_gcd = MT2063_gcd(f_LO1, f_LO2); | |
cfde8925 | 1040 | gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale); |
0e301442 | 1041 | hgds = gd_Scale / 2; |
cfde8925 | 1042 | gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale); |
0e301442 | 1043 | hgcs = gc_Scale / 2; |
cfde8925 | 1044 | gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale); |
0e301442 MCC |
1045 | hgfs = gf_Scale / 2; |
1046 | ||
e930b3a0 | 1047 | n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2); |
0e301442 MCC |
1048 | |
1049 | /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */ | |
1050 | for (n = n0; n <= pAS_Info->maxH1; ++n) { | |
1051 | md = (n * ((f_LO1 + hgds) / gd_Scale) - | |
1052 | ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale); | |
1053 | ||
1054 | /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */ | |
1055 | if (md >= pAS_Info->maxH1) | |
1056 | break; | |
1057 | ||
1058 | ma = (n * ((f_LO1 + hgds) / gd_Scale) + | |
1059 | ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale); | |
1060 | ||
1061 | /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */ | |
1062 | if (md == ma) | |
1063 | continue; | |
1064 | ||
1065 | mc = (n * ((f_LO1 + hgcs) / gc_Scale) - | |
1066 | ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale); | |
1067 | if (mc != md) { | |
cfde8925 MCC |
1068 | f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale)); |
1069 | f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale)); | |
0e301442 MCC |
1070 | f_Spur = |
1071 | (gc_Scale * (f_nsLO1 - f_nsLO2)) + | |
1072 | n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale); | |
1073 | ||
cfde8925 MCC |
1074 | *fp = ((f_Spur - (s32) c) / (mc - n)) + 1; |
1075 | *fm = (((s32) d - f_Spur) / (mc - n)) + 1; | |
0e301442 MCC |
1076 | return 1; |
1077 | } | |
1078 | ||
1079 | /* Location of Zero-IF-spur to be checked */ | |
1080 | me = (n * ((f_LO1 + hgfs) / gf_Scale) + | |
1081 | ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale); | |
1082 | mf = (n * ((f_LO1 + hgfs) / gf_Scale) - | |
1083 | ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale); | |
1084 | if (me != mf) { | |
1085 | f_nsLO1 = n * (f_LO1 / gf_Scale); | |
1086 | f_nsLO2 = me * (f_LO2 / gf_Scale); | |
1087 | f_Spur = | |
1088 | (gf_Scale * (f_nsLO1 - f_nsLO2)) + | |
1089 | n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale); | |
1090 | ||
cfde8925 MCC |
1091 | *fp = ((f_Spur + (s32) f) / (me - n)) + 1; |
1092 | *fm = (((s32) f - f_Spur) / (me - n)) + 1; | |
0e301442 MCC |
1093 | return 1; |
1094 | } | |
1095 | ||
1096 | mb = (n * ((f_LO1 + hgcs) / gc_Scale) + | |
1097 | ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale); | |
1098 | if (ma != mb) { | |
1099 | f_nsLO1 = n * (f_LO1 / gc_Scale); | |
1100 | f_nsLO2 = ma * (f_LO2 / gc_Scale); | |
1101 | f_Spur = | |
1102 | (gc_Scale * (f_nsLO1 - f_nsLO2)) + | |
1103 | n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale); | |
1104 | ||
cfde8925 MCC |
1105 | *fp = (((s32) d + f_Spur) / (ma - n)) + 1; |
1106 | *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1; | |
0e301442 MCC |
1107 | return 1; |
1108 | } | |
1109 | } | |
1110 | ||
0e301442 MCC |
1111 | /* No spurs found */ |
1112 | return 0; | |
1113 | } | |
1114 | ||
1115 | /***************************************************************************** | |
1116 | ** | |
1117 | ** Name: MT_AvoidSpurs | |
1118 | ** | |
1119 | ** Description: Main entry point to avoid spurs. | |
1120 | ** Checks for existing spurs in present LO1, LO2 freqs | |
1121 | ** and if present, chooses spur-free LO1, LO2 combination | |
1122 | ** that tunes the same input/output frequencies. | |
1123 | ** | |
1124 | ** Revision History: | |
1125 | ** | |
1126 | ** SCR Date Author Description | |
1127 | ** ------------------------------------------------------------------------- | |
1128 | ** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0. | |
1129 | ** | |
1130 | *****************************************************************************/ | |
bf97555e | 1131 | static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info) |
0e301442 | 1132 | { |
fdf77a4f | 1133 | u32 status = 0; |
cfde8925 | 1134 | u32 fm, fp; /* restricted range on LO's */ |
0e301442 MCC |
1135 | pAS_Info->bSpurAvoided = 0; |
1136 | pAS_Info->nSpursFound = 0; | |
1137 | ||
1138 | if (pAS_Info->maxH1 == 0) | |
fdf77a4f | 1139 | return 0; |
0e301442 MCC |
1140 | |
1141 | /* | |
1142 | ** Avoid LO Generated Spurs | |
1143 | ** | |
1144 | ** Make sure that have no LO-related spurs within the IF output | |
1145 | ** bandwidth. | |
1146 | ** | |
1147 | ** If there is an LO spur in this band, start at the current IF1 frequency | |
1148 | ** and work out until we find a spur-free frequency or run up against the | |
1149 | ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they | |
1150 | ** will be unchanged if a spur-free setting is not found. | |
1151 | */ | |
1152 | pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp); | |
1153 | if (pAS_Info->bSpurPresent) { | |
cfde8925 MCC |
1154 | u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */ |
1155 | u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */ | |
1156 | u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */ | |
1157 | u32 delta_IF1; | |
1158 | u32 new_IF1; | |
0e301442 MCC |
1159 | |
1160 | /* | |
1161 | ** Spur was found, attempt to find a spur-free 1st IF | |
1162 | */ | |
1163 | do { | |
1164 | pAS_Info->nSpursFound++; | |
1165 | ||
1166 | /* Raise f_IF1_upper, if needed */ | |
1167 | MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp); | |
1168 | ||
1169 | /* Choose next IF1 that is closest to f_IF1_CENTER */ | |
1170 | new_IF1 = MT2063_ChooseFirstIF(pAS_Info); | |
1171 | ||
1172 | if (new_IF1 > zfIF1) { | |
1173 | pAS_Info->f_LO1 += (new_IF1 - zfIF1); | |
1174 | pAS_Info->f_LO2 += (new_IF1 - zfIF1); | |
1175 | } else { | |
1176 | pAS_Info->f_LO1 -= (zfIF1 - new_IF1); | |
1177 | pAS_Info->f_LO2 -= (zfIF1 - new_IF1); | |
1178 | } | |
1179 | zfIF1 = new_IF1; | |
1180 | ||
1181 | if (zfIF1 > pAS_Info->f_if1_Center) | |
1182 | delta_IF1 = zfIF1 - pAS_Info->f_if1_Center; | |
1183 | else | |
1184 | delta_IF1 = pAS_Info->f_if1_Center - zfIF1; | |
1185 | } | |
1186 | /* | |
1187 | ** Continue while the new 1st IF is still within the 1st IF bandwidth | |
1188 | ** and there is a spur in the band (again) | |
1189 | */ | |
1190 | while ((2 * delta_IF1 + pAS_Info->f_out_bw <= | |
1191 | pAS_Info->f_if1_bw) | |
1192 | && (pAS_Info->bSpurPresent = | |
1193 | IsSpurInBand(pAS_Info, &fm, &fp))); | |
1194 | ||
1195 | /* | |
1196 | ** Use the LO-spur free values found. If the search went all the way to | |
1197 | ** the 1st IF band edge and always found spurs, just leave the original | |
1198 | ** choice. It's as "good" as any other. | |
1199 | */ | |
1200 | if (pAS_Info->bSpurPresent == 1) { | |
1201 | status |= MT2063_SPUR_PRESENT_ERR; | |
1202 | pAS_Info->f_LO1 = zfLO1; | |
1203 | pAS_Info->f_LO2 = zfLO2; | |
1204 | } else | |
1205 | pAS_Info->bSpurAvoided = 1; | |
1206 | } | |
1207 | ||
1208 | status |= | |
1209 | ((pAS_Info-> | |
1210 | nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK); | |
1211 | ||
1212 | return (status); | |
1213 | } | |
1214 | ||
0e301442 MCC |
1215 | //end of mt2063_spuravoid.c |
1216 | //================================================================= | |
1217 | //################################################################# | |
1218 | //================================================================= | |
1219 | ||
1220 | /* | |
1221 | ** The expected version of MT_AvoidSpursData_t | |
1222 | ** If the version is different, an updated file is needed from Microtune | |
1223 | */ | |
1224 | /* Expecting version 1.21 of the Spur Avoidance API */ | |
0e301442 MCC |
1225 | |
1226 | typedef enum { | |
1227 | MT2063_SET_ATTEN, | |
1228 | MT2063_INCR_ATTEN, | |
1229 | MT2063_DECR_ATTEN | |
1230 | } MT2063_ATTEN_CNTL_MODE; | |
1231 | ||
1232 | //#define TUNER_MT2063_OPTIMIZATION | |
1233 | /* | |
1234 | ** Constants used by the tuning algorithm | |
1235 | */ | |
1236 | #define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */ | |
1237 | #define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */ | |
1238 | #define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */ | |
1239 | #define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */ | |
1240 | #define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */ | |
1241 | #define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */ | |
1242 | #define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */ | |
1243 | #define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */ | |
1244 | #define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */ | |
1245 | #define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */ | |
1246 | #define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */ | |
1247 | #define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */ | |
1248 | #define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */ | |
1249 | #define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */ | |
1250 | #define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */ | |
1251 | #define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */ | |
1252 | #define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */ | |
1253 | #define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */ | |
1254 | ||
1255 | /* | |
1256 | ** Define the supported Part/Rev codes for the MT2063 | |
1257 | */ | |
1258 | #define MT2063_B0 (0x9B) | |
1259 | #define MT2063_B1 (0x9C) | |
1260 | #define MT2063_B2 (0x9D) | |
1261 | #define MT2063_B3 (0x9E) | |
1262 | ||
1263 | /* | |
1264 | ** The number of Tuner Registers | |
1265 | */ | |
cfde8925 | 1266 | static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS; |
0e301442 MCC |
1267 | |
1268 | #define USE_GLOBAL_TUNER 0 | |
1269 | ||
a0813ea3 | 1270 | static u32 nMT2063MaxTuners = 1; |
cfde8925 | 1271 | static u32 nMT2063OpenTuners = 0; |
0e301442 MCC |
1272 | |
1273 | /* | |
1274 | ** Constants for setting receiver modes. | |
1275 | ** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES) | |
1276 | ** (DNC1GC & DNC2GC are the values, which are used, when the specific | |
1277 | ** DNC Output is selected, the other is always off) | |
1278 | ** | |
1279 | ** If PAL-L or L' is received, set: | |
1280 | ** MT2063_SetParam(hMT2063,MT2063_TAGC,1); | |
1281 | ** | |
1282 | ** --------------+---------------------------------------------- | |
1283 | ** Mode 0 : | MT2063_CABLE_QAM | |
1284 | ** Mode 1 : | MT2063_CABLE_ANALOG | |
1285 | ** Mode 2 : | MT2063_OFFAIR_COFDM | |
1286 | ** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS | |
1287 | ** Mode 4 : | MT2063_OFFAIR_ANALOG | |
1288 | ** Mode 5 : | MT2063_OFFAIR_8VSB | |
1289 | ** --------------+----+----+----+----+-----+-----+-------------- | |
1290 | ** Mode | 0 | 1 | 2 | 3 | 4 | 5 | | |
1291 | ** --------------+----+----+----+----+-----+-----+ | |
1292 | ** | |
1293 | ** | |
1294 | */ | |
cfde8925 MCC |
1295 | static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 }; |
1296 | static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 }; | |
1297 | static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 }; | |
1298 | static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 }; | |
1299 | static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 }; | |
1300 | static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 }; | |
1301 | static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 }; | |
1302 | static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 }; | |
1303 | static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 }; | |
1304 | static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 }; | |
1305 | static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 }; | |
1306 | static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 }; | |
1307 | static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 }; | |
1308 | static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 }; | |
0e301442 MCC |
1309 | |
1310 | /* | |
1311 | ** Local Function Prototypes - not available for external access. | |
1312 | */ | |
1313 | ||
1314 | /* Forward declaration(s): */ | |
cfde8925 MCC |
1315 | static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO, |
1316 | u32 f_LO_Step, u32 f_Ref); | |
1317 | static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO, | |
1318 | u32 f_LO_Step, u32 f_Ref); | |
1319 | static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, | |
1320 | u32 denom); | |
0e301442 | 1321 | |
0e301442 MCC |
1322 | /**************************************************************************** |
1323 | ** | |
1324 | ** Name: MT2063_GetLocked | |
1325 | ** | |
1326 | ** Description: Checks to see if LO1 and LO2 are locked. | |
1327 | ** | |
1328 | ** Parameters: h - Open handle to the tuner (from MT2063_Open). | |
1329 | ** | |
1330 | ** Returns: status: | |
1331 | ** MT_OK - No errors | |
1332 | ** MT_UPC_UNLOCK - Upconverter PLL unlocked | |
1333 | ** MT_DNC_UNLOCK - Downconverter PLL unlocked | |
1334 | ** MT_COMM_ERR - Serial bus communications error | |
1335 | ** MT_INV_HANDLE - Invalid tuner handle | |
1336 | ** | |
1337 | ** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus | |
1338 | ** MT_Sleep - Delay execution for x milliseconds | |
1339 | ** | |
1340 | ** Revision History: | |
1341 | ** | |
1342 | ** SCR Date Author Description | |
1343 | ** ------------------------------------------------------------------------- | |
1344 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
1345 | ** | |
1346 | ****************************************************************************/ | |
dcd52d20 | 1347 | static u32 MT2063_GetLocked(struct mt2063_state *state) |
0e301442 | 1348 | { |
cfde8925 MCC |
1349 | const u32 nMaxWait = 100; /* wait a maximum of 100 msec */ |
1350 | const u32 nPollRate = 2; /* poll status bits every 2 ms */ | |
1351 | const u32 nMaxLoops = nMaxWait / nPollRate; | |
1352 | const u8 LO1LK = 0x80; | |
1353 | u8 LO2LK = 0x08; | |
fdf77a4f | 1354 | u32 status = 0; /* Status to be returned */ |
cfde8925 | 1355 | u32 nDelays = 0; |
0e301442 | 1356 | |
0e301442 | 1357 | /* LO2 Lock bit was in a different place for B0 version */ |
dcd52d20 | 1358 | if (state->tuner_id == MT2063_B0) |
0e301442 MCC |
1359 | LO2LK = 0x40; |
1360 | ||
1361 | do { | |
1362 | status |= | |
e1de3d18 | 1363 | mt2063_read(state, |
0e301442 | 1364 | MT2063_REG_LO_STATUS, |
dcd52d20 | 1365 | &state->reg[MT2063_REG_LO_STATUS], 1); |
0e301442 | 1366 | |
fdf77a4f | 1367 | if (status < 0) |
0e301442 MCC |
1368 | return (status); |
1369 | ||
dcd52d20 | 1370 | if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) == |
0e301442 MCC |
1371 | (LO1LK | LO2LK)) { |
1372 | return (status); | |
1373 | } | |
bf97555e | 1374 | msleep(nPollRate); /* Wait between retries */ |
0e301442 MCC |
1375 | } |
1376 | while (++nDelays < nMaxLoops); | |
1377 | ||
dcd52d20 | 1378 | if ((state->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00) |
0e301442 | 1379 | status |= MT2063_UPC_UNLOCK; |
dcd52d20 | 1380 | if ((state->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00) |
0e301442 MCC |
1381 | status |= MT2063_DNC_UNLOCK; |
1382 | ||
1383 | return (status); | |
1384 | } | |
1385 | ||
1386 | /**************************************************************************** | |
1387 | ** | |
1388 | ** Name: MT2063_GetParam | |
1389 | ** | |
1390 | ** Description: Gets a tuning algorithm parameter. | |
1391 | ** | |
1392 | ** This function provides access to the internals of the | |
1393 | ** tuning algorithm - mostly for testing purposes. | |
1394 | ** | |
1395 | ** Parameters: h - Tuner handle (returned by MT2063_Open) | |
1396 | ** param - Tuning algorithm parameter | |
1397 | ** (see enum MT2063_Param) | |
1398 | ** pValue - ptr to returned value | |
1399 | ** | |
1400 | ** param Description | |
1401 | ** ---------------------- -------------------------------- | |
1402 | ** MT2063_IC_ADDR Serial Bus address of this tuner | |
1403 | ** MT2063_MAX_OPEN Max # of MT2063's allowed open | |
1404 | ** MT2063_NUM_OPEN # of MT2063's open | |
1405 | ** MT2063_SRO_FREQ crystal frequency | |
1406 | ** MT2063_STEPSIZE minimum tuning step size | |
1407 | ** MT2063_INPUT_FREQ input center frequency | |
1408 | ** MT2063_LO1_FREQ LO1 Frequency | |
1409 | ** MT2063_LO1_STEPSIZE LO1 minimum step size | |
1410 | ** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region | |
1411 | ** MT2063_IF1_ACTUAL Current 1st IF in use | |
1412 | ** MT2063_IF1_REQUEST Requested 1st IF | |
1413 | ** MT2063_IF1_CENTER Center of 1st IF SAW filter | |
1414 | ** MT2063_IF1_BW Bandwidth of 1st IF SAW filter | |
1415 | ** MT2063_ZIF_BW zero-IF bandwidth | |
1416 | ** MT2063_LO2_FREQ LO2 Frequency | |
1417 | ** MT2063_LO2_STEPSIZE LO2 minimum step size | |
1418 | ** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region | |
1419 | ** MT2063_OUTPUT_FREQ output center frequency | |
1420 | ** MT2063_OUTPUT_BW output bandwidth | |
1421 | ** MT2063_LO_SEPARATION min inter-tuner LO separation | |
1422 | ** MT2063_AS_ALG ID of avoid-spurs algorithm in use | |
1423 | ** MT2063_MAX_HARM1 max # of intra-tuner harmonics | |
1424 | ** MT2063_MAX_HARM2 max # of inter-tuner harmonics | |
1425 | ** MT2063_EXCL_ZONES # of 1st IF exclusion zones | |
1426 | ** MT2063_NUM_SPURS # of spurs found/avoided | |
1427 | ** MT2063_SPUR_AVOIDED >0 spurs avoided | |
1428 | ** MT2063_SPUR_PRESENT >0 spurs in output (mathematically) | |
1429 | ** MT2063_RCVR_MODE Predefined modes. | |
1430 | ** MT2063_ACLNA LNA attenuator gain code | |
1431 | ** MT2063_ACRF RF attenuator gain code | |
1432 | ** MT2063_ACFIF FIF attenuator gain code | |
1433 | ** MT2063_ACLNA_MAX LNA attenuator limit | |
1434 | ** MT2063_ACRF_MAX RF attenuator limit | |
1435 | ** MT2063_ACFIF_MAX FIF attenuator limit | |
1436 | ** MT2063_PD1 Actual value of PD1 | |
1437 | ** MT2063_PD2 Actual value of PD2 | |
1438 | ** MT2063_DNC_OUTPUT_ENABLE DNC output selection | |
1439 | ** MT2063_VGAGC VGA gain code | |
1440 | ** MT2063_VGAOI VGA output current | |
1441 | ** MT2063_TAGC TAGC setting | |
1442 | ** MT2063_AMPGC AMP gain code | |
1443 | ** MT2063_AVOID_DECT Avoid DECT Frequencies | |
1444 | ** MT2063_CTFILT_SW Cleartune filter selection | |
1445 | ** | |
1446 | ** Usage: status |= MT2063_GetParam(hMT2063, | |
1447 | ** MT2063_IF1_ACTUAL, | |
1448 | ** &f_IF1_Actual); | |
1449 | ** | |
1450 | ** Returns: status: | |
1451 | ** MT_OK - No errors | |
1452 | ** MT_INV_HANDLE - Invalid tuner handle | |
1453 | ** MT_ARG_NULL - Null pointer argument passed | |
1454 | ** MT_ARG_RANGE - Invalid parameter requested | |
1455 | ** | |
1456 | ** Dependencies: USERS MUST CALL MT2063_Open() FIRST! | |
1457 | ** | |
1458 | ** See Also: MT2063_SetParam, MT2063_Open | |
1459 | ** | |
1460 | ** Revision History: | |
1461 | ** | |
1462 | ** SCR Date Author Description | |
1463 | ** ------------------------------------------------------------------------- | |
1464 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
1465 | ** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ | |
1466 | ** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC | |
1467 | ** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW | |
1468 | ** in GetParam. | |
1469 | ** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT | |
1470 | ** Split SetParam up to ACLNA / ACLNA_MAX | |
1471 | ** removed ACLNA_INRC/DECR (+RF & FIF) | |
1472 | ** removed GCUAUTO / BYPATNDN/UP | |
1473 | ** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs. | |
1474 | ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. | |
1475 | ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW | |
1476 | ** | |
1477 | ****************************************************************************/ | |
dcd52d20 | 1478 | static u32 MT2063_GetParam(struct mt2063_state *state, enum MT2063_Param param, u32 *pValue) |
0e301442 | 1479 | { |
fdf77a4f | 1480 | u32 status = 0; /* Status to be returned */ |
cfde8925 MCC |
1481 | u32 Div; |
1482 | u32 Num; | |
0e301442 MCC |
1483 | |
1484 | if (pValue == NULL) | |
fdf77a4f | 1485 | return -EINVAL; |
0e301442 | 1486 | |
51f0f7b3 MCC |
1487 | switch (param) { |
1488 | /* Serial Bus address of this tuner */ | |
1489 | case MT2063_IC_ADDR: | |
dcd52d20 | 1490 | *pValue = state->config->tuner_address; |
51f0f7b3 MCC |
1491 | break; |
1492 | ||
1493 | /* Max # of MT2063's allowed to be open */ | |
1494 | case MT2063_MAX_OPEN: | |
1495 | *pValue = nMT2063MaxTuners; | |
1496 | break; | |
1497 | ||
1498 | /* # of MT2063's open */ | |
1499 | case MT2063_NUM_OPEN: | |
1500 | *pValue = nMT2063OpenTuners; | |
1501 | break; | |
1502 | ||
1503 | /* crystal frequency */ | |
1504 | case MT2063_SRO_FREQ: | |
dcd52d20 | 1505 | *pValue = state->AS_Data.f_ref; |
51f0f7b3 MCC |
1506 | break; |
1507 | ||
1508 | /* minimum tuning step size */ | |
1509 | case MT2063_STEPSIZE: | |
dcd52d20 | 1510 | *pValue = state->AS_Data.f_LO2_Step; |
51f0f7b3 MCC |
1511 | break; |
1512 | ||
1513 | /* input center frequency */ | |
1514 | case MT2063_INPUT_FREQ: | |
dcd52d20 | 1515 | *pValue = state->AS_Data.f_in; |
51f0f7b3 MCC |
1516 | break; |
1517 | ||
1518 | /* LO1 Frequency */ | |
1519 | case MT2063_LO1_FREQ: | |
1520 | { | |
1521 | /* read the actual tuner register values for LO1C_1 and LO1C_2 */ | |
1522 | status |= | |
e1de3d18 | 1523 | mt2063_read(state, |
51f0f7b3 | 1524 | MT2063_REG_LO1C_1, |
dcd52d20 | 1525 | &state-> |
51f0f7b3 | 1526 | reg[MT2063_REG_LO1C_1], 2); |
dcd52d20 MCC |
1527 | Div = state->reg[MT2063_REG_LO1C_1]; |
1528 | Num = state->reg[MT2063_REG_LO1C_2] & 0x3F; | |
1529 | state->AS_Data.f_LO1 = | |
1530 | (state->AS_Data.f_ref * Div) + | |
1531 | MT2063_fLO_FractionalTerm(state->AS_Data. | |
51f0f7b3 MCC |
1532 | f_ref, Num, 64); |
1533 | } | |
dcd52d20 | 1534 | *pValue = state->AS_Data.f_LO1; |
51f0f7b3 MCC |
1535 | break; |
1536 | ||
1537 | /* LO1 minimum step size */ | |
1538 | case MT2063_LO1_STEPSIZE: | |
dcd52d20 | 1539 | *pValue = state->AS_Data.f_LO1_Step; |
51f0f7b3 MCC |
1540 | break; |
1541 | ||
1542 | /* LO1 FracN keep-out region */ | |
1543 | case MT2063_LO1_FRACN_AVOID_PARAM: | |
dcd52d20 | 1544 | *pValue = state->AS_Data.f_LO1_FracN_Avoid; |
51f0f7b3 MCC |
1545 | break; |
1546 | ||
1547 | /* Current 1st IF in use */ | |
1548 | case MT2063_IF1_ACTUAL: | |
dcd52d20 | 1549 | *pValue = state->f_IF1_actual; |
51f0f7b3 MCC |
1550 | break; |
1551 | ||
1552 | /* Requested 1st IF */ | |
1553 | case MT2063_IF1_REQUEST: | |
dcd52d20 | 1554 | *pValue = state->AS_Data.f_if1_Request; |
51f0f7b3 MCC |
1555 | break; |
1556 | ||
1557 | /* Center of 1st IF SAW filter */ | |
1558 | case MT2063_IF1_CENTER: | |
dcd52d20 | 1559 | *pValue = state->AS_Data.f_if1_Center; |
51f0f7b3 MCC |
1560 | break; |
1561 | ||
1562 | /* Bandwidth of 1st IF SAW filter */ | |
1563 | case MT2063_IF1_BW: | |
dcd52d20 | 1564 | *pValue = state->AS_Data.f_if1_bw; |
51f0f7b3 MCC |
1565 | break; |
1566 | ||
1567 | /* zero-IF bandwidth */ | |
1568 | case MT2063_ZIF_BW: | |
dcd52d20 | 1569 | *pValue = state->AS_Data.f_zif_bw; |
51f0f7b3 MCC |
1570 | break; |
1571 | ||
1572 | /* LO2 Frequency */ | |
1573 | case MT2063_LO2_FREQ: | |
1574 | { | |
1575 | /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */ | |
1576 | status |= | |
e1de3d18 | 1577 | mt2063_read(state, |
51f0f7b3 | 1578 | MT2063_REG_LO2C_1, |
dcd52d20 | 1579 | &state-> |
51f0f7b3 MCC |
1580 | reg[MT2063_REG_LO2C_1], 3); |
1581 | Div = | |
dcd52d20 | 1582 | (state->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1; |
51f0f7b3 | 1583 | Num = |
dcd52d20 | 1584 | ((state-> |
51f0f7b3 | 1585 | reg[MT2063_REG_LO2C_1] & 0x01) << 12) | |
dcd52d20 MCC |
1586 | (state-> |
1587 | reg[MT2063_REG_LO2C_2] << 4) | (state-> | |
51f0f7b3 MCC |
1588 | reg |
1589 | [MT2063_REG_LO2C_3] | |
1590 | & 0x00F); | |
dcd52d20 MCC |
1591 | state->AS_Data.f_LO2 = |
1592 | (state->AS_Data.f_ref * Div) + | |
1593 | MT2063_fLO_FractionalTerm(state->AS_Data. | |
51f0f7b3 MCC |
1594 | f_ref, Num, 8191); |
1595 | } | |
dcd52d20 | 1596 | *pValue = state->AS_Data.f_LO2; |
51f0f7b3 MCC |
1597 | break; |
1598 | ||
1599 | /* LO2 minimum step size */ | |
1600 | case MT2063_LO2_STEPSIZE: | |
dcd52d20 | 1601 | *pValue = state->AS_Data.f_LO2_Step; |
51f0f7b3 MCC |
1602 | break; |
1603 | ||
1604 | /* LO2 FracN keep-out region */ | |
1605 | case MT2063_LO2_FRACN_AVOID: | |
dcd52d20 | 1606 | *pValue = state->AS_Data.f_LO2_FracN_Avoid; |
51f0f7b3 MCC |
1607 | break; |
1608 | ||
1609 | /* output center frequency */ | |
1610 | case MT2063_OUTPUT_FREQ: | |
dcd52d20 | 1611 | *pValue = state->AS_Data.f_out; |
51f0f7b3 MCC |
1612 | break; |
1613 | ||
1614 | /* output bandwidth */ | |
1615 | case MT2063_OUTPUT_BW: | |
dcd52d20 | 1616 | *pValue = state->AS_Data.f_out_bw - 750000; |
51f0f7b3 MCC |
1617 | break; |
1618 | ||
1619 | /* min inter-tuner LO separation */ | |
1620 | case MT2063_LO_SEPARATION: | |
dcd52d20 | 1621 | *pValue = state->AS_Data.f_min_LO_Separation; |
51f0f7b3 MCC |
1622 | break; |
1623 | ||
51f0f7b3 MCC |
1624 | /* max # of intra-tuner harmonics */ |
1625 | case MT2063_MAX_HARM1: | |
dcd52d20 | 1626 | *pValue = state->AS_Data.maxH1; |
51f0f7b3 MCC |
1627 | break; |
1628 | ||
1629 | /* max # of inter-tuner harmonics */ | |
1630 | case MT2063_MAX_HARM2: | |
dcd52d20 | 1631 | *pValue = state->AS_Data.maxH2; |
51f0f7b3 MCC |
1632 | break; |
1633 | ||
1634 | /* # of 1st IF exclusion zones */ | |
1635 | case MT2063_EXCL_ZONES: | |
dcd52d20 | 1636 | *pValue = state->AS_Data.nZones; |
51f0f7b3 MCC |
1637 | break; |
1638 | ||
1639 | /* # of spurs found/avoided */ | |
1640 | case MT2063_NUM_SPURS: | |
dcd52d20 | 1641 | *pValue = state->AS_Data.nSpursFound; |
51f0f7b3 MCC |
1642 | break; |
1643 | ||
1644 | /* >0 spurs avoided */ | |
1645 | case MT2063_SPUR_AVOIDED: | |
dcd52d20 | 1646 | *pValue = state->AS_Data.bSpurAvoided; |
51f0f7b3 MCC |
1647 | break; |
1648 | ||
1649 | /* >0 spurs in output (mathematically) */ | |
1650 | case MT2063_SPUR_PRESENT: | |
dcd52d20 | 1651 | *pValue = state->AS_Data.bSpurPresent; |
51f0f7b3 MCC |
1652 | break; |
1653 | ||
1654 | /* Predefined receiver setup combination */ | |
1655 | case MT2063_RCVR_MODE: | |
dcd52d20 | 1656 | *pValue = state->rcvr_mode; |
51f0f7b3 MCC |
1657 | break; |
1658 | ||
1659 | case MT2063_PD1: | |
1660 | case MT2063_PD2: { | |
1661 | u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */ | |
dcd52d20 | 1662 | u8 orig = (state->reg[MT2063_REG_BYP_CTRL]); |
51f0f7b3 MCC |
1663 | u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */ |
1664 | int i; | |
1665 | ||
1666 | *pValue = 0; | |
1667 | ||
1668 | /* Initiate ADC output to reg 0x0A */ | |
1669 | if (reg != orig) | |
1670 | status |= | |
e1de3d18 | 1671 | mt2063_write(state, |
51f0f7b3 MCC |
1672 | MT2063_REG_BYP_CTRL, |
1673 | ®, 1); | |
1674 | ||
1675 | if (status < 0) | |
1676 | return (status); | |
1677 | ||
1678 | for (i = 0; i < 8; i++) { | |
1679 | status |= | |
e1de3d18 | 1680 | mt2063_read(state, |
51f0f7b3 | 1681 | MT2063_REG_ADC_OUT, |
dcd52d20 | 1682 | &state-> |
51f0f7b3 MCC |
1683 | reg |
1684 | [MT2063_REG_ADC_OUT], | |
1685 | 1); | |
1686 | ||
1687 | if (status >= 0) | |
1688 | *pValue += | |
dcd52d20 | 1689 | state-> |
51f0f7b3 MCC |
1690 | reg[MT2063_REG_ADC_OUT]; |
1691 | else { | |
1692 | if (i) | |
1693 | *pValue /= i; | |
1694 | return (status); | |
1695 | } | |
1696 | } | |
1697 | *pValue /= 8; /* divide by number of reads */ | |
1698 | *pValue >>= 2; /* only want 6 MSB's out of 8 */ | |
1699 | ||
1700 | /* Restore value of Register BYP_CTRL */ | |
1701 | if (reg != orig) | |
1702 | status |= | |
e1de3d18 | 1703 | mt2063_write(state, |
51f0f7b3 MCC |
1704 | MT2063_REG_BYP_CTRL, |
1705 | &orig, 1); | |
1706 | } | |
1707 | break; | |
1708 | ||
1709 | /* Get LNA attenuator code */ | |
1710 | case MT2063_ACLNA: | |
1711 | { | |
1712 | u8 val; | |
1713 | status |= | |
dcd52d20 | 1714 | MT2063_GetReg(state, MT2063_REG_XO_STATUS, |
51f0f7b3 MCC |
1715 | &val); |
1716 | *pValue = val & 0x1f; | |
1717 | } | |
1718 | break; | |
1719 | ||
1720 | /* Get RF attenuator code */ | |
1721 | case MT2063_ACRF: | |
1722 | { | |
1723 | u8 val; | |
1724 | status |= | |
dcd52d20 | 1725 | MT2063_GetReg(state, MT2063_REG_RF_STATUS, |
51f0f7b3 MCC |
1726 | &val); |
1727 | *pValue = val & 0x1f; | |
1728 | } | |
1729 | break; | |
fdf77a4f | 1730 | |
51f0f7b3 MCC |
1731 | /* Get FIF attenuator code */ |
1732 | case MT2063_ACFIF: | |
1733 | { | |
1734 | u8 val; | |
1735 | status |= | |
dcd52d20 | 1736 | MT2063_GetReg(state, MT2063_REG_FIF_STATUS, |
51f0f7b3 MCC |
1737 | &val); |
1738 | *pValue = val & 0x1f; | |
1739 | } | |
1740 | break; | |
1741 | ||
1742 | /* Get LNA attenuator limit */ | |
1743 | case MT2063_ACLNA_MAX: | |
1744 | { | |
1745 | u8 val; | |
1746 | status |= | |
dcd52d20 | 1747 | MT2063_GetReg(state, MT2063_REG_LNA_OV, |
51f0f7b3 MCC |
1748 | &val); |
1749 | *pValue = val & 0x1f; | |
1750 | } | |
1751 | break; | |
1752 | ||
1753 | /* Get RF attenuator limit */ | |
1754 | case MT2063_ACRF_MAX: | |
1755 | { | |
1756 | u8 val; | |
1757 | status |= | |
dcd52d20 | 1758 | MT2063_GetReg(state, MT2063_REG_RF_OV, |
51f0f7b3 MCC |
1759 | &val); |
1760 | *pValue = val & 0x1f; | |
1761 | } | |
1762 | break; | |
1763 | ||
1764 | /* Get FIF attenuator limit */ | |
1765 | case MT2063_ACFIF_MAX: | |
1766 | { | |
1767 | u8 val; | |
1768 | status |= | |
dcd52d20 | 1769 | MT2063_GetReg(state, MT2063_REG_FIF_OV, |
51f0f7b3 MCC |
1770 | &val); |
1771 | *pValue = val & 0x1f; | |
1772 | } | |
1773 | break; | |
1774 | ||
1775 | /* Get current used DNC output */ | |
1776 | case MT2063_DNC_OUTPUT_ENABLE: | |
1777 | { | |
dcd52d20 MCC |
1778 | if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */ |
1779 | if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */ | |
51f0f7b3 MCC |
1780 | *pValue = |
1781 | (u32) MT2063_DNC_NONE; | |
1782 | else | |
1783 | *pValue = | |
1784 | (u32) MT2063_DNC_2; | |
1785 | } else { /* DNC1 is on */ | |
1786 | ||
dcd52d20 | 1787 | if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */ |
51f0f7b3 MCC |
1788 | *pValue = |
1789 | (u32) MT2063_DNC_1; | |
1790 | else | |
1791 | *pValue = | |
1792 | (u32) MT2063_DNC_BOTH; | |
1793 | } | |
1794 | } | |
1795 | break; | |
1796 | ||
1797 | /* Get VGA Gain Code */ | |
1798 | case MT2063_VGAGC: | |
dcd52d20 | 1799 | *pValue = ((state->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2); |
51f0f7b3 MCC |
1800 | break; |
1801 | ||
1802 | /* Get VGA bias current */ | |
1803 | case MT2063_VGAOI: | |
dcd52d20 | 1804 | *pValue = (state->reg[MT2063_REG_RSVD_31] & 0x07); |
51f0f7b3 MCC |
1805 | break; |
1806 | ||
1807 | /* Get TAGC setting */ | |
1808 | case MT2063_TAGC: | |
dcd52d20 | 1809 | *pValue = (state->reg[MT2063_REG_RSVD_1E] & 0x03); |
51f0f7b3 MCC |
1810 | break; |
1811 | ||
1812 | /* Get AMP Gain Code */ | |
1813 | case MT2063_AMPGC: | |
dcd52d20 | 1814 | *pValue = (state->reg[MT2063_REG_TEMP_SEL] & 0x03); |
51f0f7b3 MCC |
1815 | break; |
1816 | ||
1817 | /* Avoid DECT Frequencies */ | |
1818 | case MT2063_AVOID_DECT: | |
dcd52d20 | 1819 | *pValue = state->AS_Data.avoidDECT; |
51f0f7b3 MCC |
1820 | break; |
1821 | ||
1822 | /* Cleartune filter selection: 0 - by IC (default), 1 - by software */ | |
1823 | case MT2063_CTFILT_SW: | |
dcd52d20 | 1824 | *pValue = state->ctfilt_sw; |
51f0f7b3 MCC |
1825 | break; |
1826 | ||
1827 | case MT2063_EOP: | |
1828 | default: | |
1829 | status |= -ERANGE; | |
1830 | } | |
0e301442 MCC |
1831 | return (status); |
1832 | } | |
1833 | ||
1834 | /**************************************************************************** | |
1835 | ** | |
1836 | ** Name: MT2063_GetReg | |
1837 | ** | |
1838 | ** Description: Gets an MT2063 register. | |
1839 | ** | |
1840 | ** Parameters: h - Tuner handle (returned by MT2063_Open) | |
1841 | ** reg - MT2063 register/subaddress location | |
1842 | ** *val - MT2063 register/subaddress value | |
1843 | ** | |
1844 | ** Returns: status: | |
1845 | ** MT_OK - No errors | |
1846 | ** MT_COMM_ERR - Serial bus communications error | |
1847 | ** MT_INV_HANDLE - Invalid tuner handle | |
1848 | ** MT_ARG_NULL - Null pointer argument passed | |
1849 | ** MT_ARG_RANGE - Argument out of range | |
1850 | ** | |
1851 | ** Dependencies: USERS MUST CALL MT2063_Open() FIRST! | |
1852 | ** | |
1853 | ** Use this function if you need to read a register from | |
1854 | ** the MT2063. | |
1855 | ** | |
1856 | ** Revision History: | |
1857 | ** | |
1858 | ** SCR Date Author Description | |
1859 | ** ------------------------------------------------------------------------- | |
1860 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
1861 | ** | |
1862 | ****************************************************************************/ | |
dcd52d20 | 1863 | static u32 MT2063_GetReg(struct mt2063_state *state, u8 reg, u8 * val) |
0e301442 | 1864 | { |
fdf77a4f | 1865 | u32 status = 0; /* Status to be returned */ |
0e301442 | 1866 | |
0e301442 | 1867 | if (val == NULL) |
fdf77a4f | 1868 | return -EINVAL; |
0e301442 MCC |
1869 | |
1870 | if (reg >= MT2063_REG_END_REGS) | |
fdf77a4f | 1871 | return -ERANGE; |
0e301442 | 1872 | |
e1de3d18 | 1873 | status = mt2063_read(state, reg, &state->reg[reg], 1); |
0e301442 MCC |
1874 | |
1875 | return (status); | |
1876 | } | |
1877 | ||
0e301442 MCC |
1878 | /****************************************************************************** |
1879 | ** | |
1880 | ** Name: MT2063_SetReceiverMode | |
1881 | ** | |
1882 | ** Description: Set the MT2063 receiver mode | |
1883 | ** | |
1884 | ** --------------+---------------------------------------------- | |
1885 | ** Mode 0 : | MT2063_CABLE_QAM | |
1886 | ** Mode 1 : | MT2063_CABLE_ANALOG | |
1887 | ** Mode 2 : | MT2063_OFFAIR_COFDM | |
1888 | ** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS | |
1889 | ** Mode 4 : | MT2063_OFFAIR_ANALOG | |
1890 | ** Mode 5 : | MT2063_OFFAIR_8VSB | |
1891 | ** --------------+----+----+----+----+-----+-------------------- | |
1892 | ** (DNC1GC & DNC2GC are the values, which are used, when the specific | |
1893 | ** DNC Output is selected, the other is always off) | |
1894 | ** | |
1895 | ** |<---------- Mode -------------->| | |
1896 | ** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 | | |
1897 | ** ------------+-----+-----+-----+-----+-----+-----+ | |
1898 | ** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF | |
1899 | ** LNARin | 0 | 0 | 3 | 3 | 3 | 3 | |
1900 | ** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1 | |
1901 | ** FIFFq | 0 | 0 | 0 | 0 | 0 | 0 | |
1902 | ** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0 | |
1903 | ** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0 | |
1904 | ** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1 | |
1905 | ** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31 | |
1906 | ** LNA Target | 44 | 43 | 43 | 43 | 43 | 43 | |
1907 | ** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0 | |
1908 | ** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31 | |
1909 | ** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38 | |
1910 | ** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0 | |
1911 | ** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5 | |
1912 | ** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42 | |
1913 | ** | |
1914 | ** | |
dcd52d20 | 1915 | ** Parameters: state - ptr to mt2063_state structure |
0e301442 MCC |
1916 | ** Mode - desired reciever mode |
1917 | ** | |
1918 | ** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode); | |
1919 | ** | |
1920 | ** Returns: status: | |
1921 | ** MT_OK - No errors | |
1922 | ** MT_COMM_ERR - Serial bus communications error | |
1923 | ** | |
1924 | ** Dependencies: MT2063_SetReg - Write a byte of data to a HW register. | |
1925 | ** Assumes that the tuner cache is valid. | |
1926 | ** | |
1927 | ** Revision History: | |
1928 | ** | |
1929 | ** SCR Date Author Description | |
1930 | ** ------------------------------------------------------------------------- | |
1931 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
1932 | ** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered | |
1933 | ** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive | |
1934 | ** modulation | |
1935 | ** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE) | |
1936 | ** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have | |
1937 | ** the same settings as with MT Launcher | |
1938 | ** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI | |
1939 | ** Add SetParam DNC_OUTPUT_ENABLE | |
1940 | ** Removed VGAGC from receiver mode, | |
1941 | ** default now 1 | |
1942 | ** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode | |
1943 | ** Add SetParam AMPGC, removed from rcvr-mode | |
1944 | ** Corrected names of GCU values | |
1945 | ** reorganized receiver modes, removed, | |
1946 | ** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE) | |
1947 | ** Actualized Receiver-Mode values | |
1948 | ** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values | |
1949 | ** N/A 11-27-2007 PINZ Improved buffered writing | |
1950 | ** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for | |
1951 | ** correct wakeup of the LNA after shutdown | |
1952 | ** Set AFCsd = 1 as default | |
1953 | ** Changed CAP1sel default | |
1954 | ** 01-14-2008 PINZ Ver 1.11: Updated gain settings | |
1955 | ** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT | |
1956 | ** Split SetParam up to ACLNA / ACLNA_MAX | |
1957 | ** removed ACLNA_INRC/DECR (+RF & FIF) | |
1958 | ** removed GCUAUTO / BYPATNDN/UP | |
1959 | ** | |
1960 | ******************************************************************************/ | |
dcd52d20 | 1961 | static u32 MT2063_SetReceiverMode(struct mt2063_state *state, |
0e301442 MCC |
1962 | enum MT2063_RCVR_MODES Mode) |
1963 | { | |
fdf77a4f | 1964 | u32 status = 0; /* Status to be returned */ |
cfde8925 MCC |
1965 | u8 val; |
1966 | u32 longval; | |
0e301442 MCC |
1967 | |
1968 | if (Mode >= MT2063_NUM_RCVR_MODES) | |
fdf77a4f | 1969 | status = -ERANGE; |
0e301442 MCC |
1970 | |
1971 | /* RFAGCen */ | |
fdf77a4f | 1972 | if (status >= 0) { |
0e301442 | 1973 | val = |
dcd52d20 | 1974 | (state-> |
cfde8925 | 1975 | reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode] |
0e301442 MCC |
1976 | ? 0x40 : |
1977 | 0x00); | |
dcd52d20 MCC |
1978 | if (state->reg[MT2063_REG_PD1_TGT] != val) { |
1979 | status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val); | |
0e301442 MCC |
1980 | } |
1981 | } | |
1982 | ||
1983 | /* LNARin */ | |
fdf77a4f | 1984 | if (status >= 0) { |
dcd52d20 | 1985 | status |= MT2063_SetParam(state, MT2063_LNA_RIN, LNARIN[Mode]); |
0e301442 MCC |
1986 | } |
1987 | ||
1988 | /* FIFFQEN and FIFFQ */ | |
fdf77a4f | 1989 | if (status >= 0) { |
0e301442 | 1990 | val = |
dcd52d20 | 1991 | (state-> |
cfde8925 | 1992 | reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) | |
0e301442 | 1993 | (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4); |
dcd52d20 | 1994 | if (state->reg[MT2063_REG_FIFF_CTRL2] != val) { |
0e301442 | 1995 | status |= |
dcd52d20 | 1996 | MT2063_SetReg(state, MT2063_REG_FIFF_CTRL2, val); |
0e301442 MCC |
1997 | /* trigger FIFF calibration, needed after changing FIFFQ */ |
1998 | val = | |
dcd52d20 | 1999 | (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01); |
0e301442 | 2000 | status |= |
dcd52d20 | 2001 | MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val); |
0e301442 | 2002 | val = |
dcd52d20 | 2003 | (state-> |
cfde8925 | 2004 | reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01); |
0e301442 | 2005 | status |= |
dcd52d20 | 2006 | MT2063_SetReg(state, MT2063_REG_FIFF_CTRL, val); |
0e301442 MCC |
2007 | } |
2008 | } | |
2009 | ||
2010 | /* DNC1GC & DNC2GC */ | |
dcd52d20 MCC |
2011 | status |= MT2063_GetParam(state, MT2063_DNC_OUTPUT_ENABLE, &longval); |
2012 | status |= MT2063_SetParam(state, MT2063_DNC_OUTPUT_ENABLE, longval); | |
0e301442 MCC |
2013 | |
2014 | /* acLNAmax */ | |
fdf77a4f | 2015 | if (status >= 0) { |
0e301442 | 2016 | status |= |
dcd52d20 | 2017 | MT2063_SetParam(state, MT2063_ACLNA_MAX, ACLNAMAX[Mode]); |
0e301442 MCC |
2018 | } |
2019 | ||
2020 | /* LNATGT */ | |
fdf77a4f | 2021 | if (status >= 0) { |
dcd52d20 | 2022 | status |= MT2063_SetParam(state, MT2063_LNA_TGT, LNATGT[Mode]); |
0e301442 MCC |
2023 | } |
2024 | ||
2025 | /* ACRF */ | |
fdf77a4f | 2026 | if (status >= 0) { |
0e301442 | 2027 | status |= |
dcd52d20 | 2028 | MT2063_SetParam(state, MT2063_ACRF_MAX, ACRFMAX[Mode]); |
0e301442 MCC |
2029 | } |
2030 | ||
2031 | /* PD1TGT */ | |
fdf77a4f | 2032 | if (status >= 0) { |
dcd52d20 | 2033 | status |= MT2063_SetParam(state, MT2063_PD1_TGT, PD1TGT[Mode]); |
0e301442 MCC |
2034 | } |
2035 | ||
2036 | /* FIFATN */ | |
fdf77a4f | 2037 | if (status >= 0) { |
0e301442 | 2038 | status |= |
dcd52d20 | 2039 | MT2063_SetParam(state, MT2063_ACFIF_MAX, ACFIFMAX[Mode]); |
0e301442 MCC |
2040 | } |
2041 | ||
2042 | /* PD2TGT */ | |
fdf77a4f | 2043 | if (status >= 0) { |
dcd52d20 | 2044 | status |= MT2063_SetParam(state, MT2063_PD2_TGT, PD2TGT[Mode]); |
0e301442 MCC |
2045 | } |
2046 | ||
2047 | /* Ignore ATN Overload */ | |
fdf77a4f | 2048 | if (status >= 0) { |
0e301442 | 2049 | val = |
dcd52d20 | 2050 | (state-> |
cfde8925 | 2051 | reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode] |
0e301442 MCC |
2052 | ? 0x80 : |
2053 | 0x00); | |
dcd52d20 MCC |
2054 | if (state->reg[MT2063_REG_LNA_TGT] != val) { |
2055 | status |= MT2063_SetReg(state, MT2063_REG_LNA_TGT, val); | |
0e301442 MCC |
2056 | } |
2057 | } | |
2058 | ||
2059 | /* Ignore FIF Overload */ | |
fdf77a4f | 2060 | if (status >= 0) { |
0e301442 | 2061 | val = |
dcd52d20 | 2062 | (state-> |
cfde8925 | 2063 | reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) | |
0e301442 | 2064 | (FIFOVDIS[Mode] ? 0x80 : 0x00); |
dcd52d20 MCC |
2065 | if (state->reg[MT2063_REG_PD1_TGT] != val) { |
2066 | status |= MT2063_SetReg(state, MT2063_REG_PD1_TGT, val); | |
0e301442 MCC |
2067 | } |
2068 | } | |
2069 | ||
fdf77a4f | 2070 | if (status >= 0) |
dcd52d20 | 2071 | state->rcvr_mode = Mode; |
0e301442 MCC |
2072 | |
2073 | return (status); | |
2074 | } | |
2075 | ||
0e301442 MCC |
2076 | /**************************************************************************** |
2077 | ** | |
2078 | ** Name: MT2063_SetParam | |
2079 | ** | |
2080 | ** Description: Sets a tuning algorithm parameter. | |
2081 | ** | |
2082 | ** This function provides access to the internals of the | |
2083 | ** tuning algorithm. You can override many of the tuning | |
2084 | ** algorithm defaults using this function. | |
2085 | ** | |
2086 | ** Parameters: h - Tuner handle (returned by MT2063_Open) | |
2087 | ** param - Tuning algorithm parameter | |
2088 | ** (see enum MT2063_Param) | |
2089 | ** nValue - value to be set | |
2090 | ** | |
2091 | ** param Description | |
2092 | ** ---------------------- -------------------------------- | |
2093 | ** MT2063_SRO_FREQ crystal frequency | |
2094 | ** MT2063_STEPSIZE minimum tuning step size | |
2095 | ** MT2063_LO1_FREQ LO1 frequency | |
2096 | ** MT2063_LO1_STEPSIZE LO1 minimum step size | |
2097 | ** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region | |
2098 | ** MT2063_IF1_REQUEST Requested 1st IF | |
2099 | ** MT2063_ZIF_BW zero-IF bandwidth | |
2100 | ** MT2063_LO2_FREQ LO2 frequency | |
2101 | ** MT2063_LO2_STEPSIZE LO2 minimum step size | |
2102 | ** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region | |
2103 | ** MT2063_OUTPUT_FREQ output center frequency | |
2104 | ** MT2063_OUTPUT_BW output bandwidth | |
2105 | ** MT2063_LO_SEPARATION min inter-tuner LO separation | |
2106 | ** MT2063_MAX_HARM1 max # of intra-tuner harmonics | |
2107 | ** MT2063_MAX_HARM2 max # of inter-tuner harmonics | |
2108 | ** MT2063_RCVR_MODE Predefined modes | |
2109 | ** MT2063_LNA_RIN Set LNA Rin (*) | |
2110 | ** MT2063_LNA_TGT Set target power level at LNA (*) | |
2111 | ** MT2063_PD1_TGT Set target power level at PD1 (*) | |
2112 | ** MT2063_PD2_TGT Set target power level at PD2 (*) | |
2113 | ** MT2063_ACLNA_MAX LNA attenuator limit (*) | |
2114 | ** MT2063_ACRF_MAX RF attenuator limit (*) | |
2115 | ** MT2063_ACFIF_MAX FIF attenuator limit (*) | |
2116 | ** MT2063_DNC_OUTPUT_ENABLE DNC output selection | |
2117 | ** MT2063_VGAGC VGA gain code | |
2118 | ** MT2063_VGAOI VGA output current | |
2119 | ** MT2063_TAGC TAGC setting | |
2120 | ** MT2063_AMPGC AMP gain code | |
2121 | ** MT2063_AVOID_DECT Avoid DECT Frequencies | |
2122 | ** MT2063_CTFILT_SW Cleartune filter selection | |
2123 | ** | |
2124 | ** (*) This parameter is set by MT2063_RCVR_MODE, do not call | |
2125 | ** additionally. | |
2126 | ** | |
2127 | ** Usage: status |= MT2063_SetParam(hMT2063, | |
2128 | ** MT2063_STEPSIZE, | |
2129 | ** 50000); | |
2130 | ** | |
2131 | ** Returns: status: | |
2132 | ** MT_OK - No errors | |
2133 | ** MT_INV_HANDLE - Invalid tuner handle | |
2134 | ** MT_ARG_NULL - Null pointer argument passed | |
2135 | ** MT_ARG_RANGE - Invalid parameter requested | |
2136 | ** or set value out of range | |
2137 | ** or non-writable parameter | |
2138 | ** | |
2139 | ** Dependencies: USERS MUST CALL MT2063_Open() FIRST! | |
2140 | ** | |
2141 | ** See Also: MT2063_GetParam, MT2063_Open | |
2142 | ** | |
2143 | ** Revision History: | |
2144 | ** | |
2145 | ** SCR Date Author Description | |
2146 | ** ------------------------------------------------------------------------- | |
2147 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
2148 | ** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ | |
2149 | ** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC | |
2150 | ** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT | |
2151 | ** Split SetParam up to ACLNA / ACLNA_MAX | |
2152 | ** removed ACLNA_INRC/DECR (+RF & FIF) | |
2153 | ** removed GCUAUTO / BYPATNDN/UP | |
2154 | ** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs. | |
2155 | ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. | |
2156 | ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW | |
2157 | ** | |
2158 | ****************************************************************************/ | |
dcd52d20 | 2159 | static u32 MT2063_SetParam(struct mt2063_state *state, |
29a0a4fe MCC |
2160 | enum MT2063_Param param, |
2161 | enum MT2063_DNC_Output_Enable nValue) | |
223c7b05 | 2162 | { |
fdf77a4f | 2163 | u32 status = 0; /* Status to be returned */ |
cfde8925 | 2164 | u8 val = 0; |
0e301442 | 2165 | |
fdf77a4f MCC |
2166 | switch (param) { |
2167 | /* crystal frequency */ | |
2168 | case MT2063_SRO_FREQ: | |
dcd52d20 MCC |
2169 | state->AS_Data.f_ref = nValue; |
2170 | state->AS_Data.f_LO1_FracN_Avoid = 0; | |
2171 | state->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1; | |
2172 | state->AS_Data.f_LO1_Step = nValue / 64; | |
2173 | state->AS_Data.f_if1_Center = | |
2174 | (state->AS_Data.f_ref / 8) * | |
2175 | (state->reg[MT2063_REG_FIFFC] + 640); | |
fdf77a4f | 2176 | break; |
0e301442 | 2177 | |
fdf77a4f MCC |
2178 | /* minimum tuning step size */ |
2179 | case MT2063_STEPSIZE: | |
dcd52d20 | 2180 | state->AS_Data.f_LO2_Step = nValue; |
fdf77a4f | 2181 | break; |
0e301442 | 2182 | |
fdf77a4f MCC |
2183 | /* LO1 frequency */ |
2184 | case MT2063_LO1_FREQ: | |
2185 | { | |
2186 | /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */ | |
2187 | /* Capture the Divider and Numerator portions of other LO */ | |
2188 | u8 tempLO2CQ[3]; | |
2189 | u8 tempLO2C[3]; | |
2190 | u8 tmpOneShot; | |
2191 | u32 Div, FracN; | |
2192 | u8 restore = 0; | |
2193 | ||
2194 | /* Buffer the queue for restoration later and get actual LO2 values. */ | |
2195 | status |= | |
e1de3d18 | 2196 | mt2063_read(state, |
fdf77a4f MCC |
2197 | MT2063_REG_LO2CQ_1, |
2198 | &(tempLO2CQ[0]), 3); | |
2199 | status |= | |
e1de3d18 | 2200 | mt2063_read(state, |
fdf77a4f MCC |
2201 | MT2063_REG_LO2C_1, |
2202 | &(tempLO2C[0]), 3); | |
2203 | ||
2204 | /* clear the one-shot bits */ | |
2205 | tempLO2CQ[2] = tempLO2CQ[2] & 0x0F; | |
2206 | tempLO2C[2] = tempLO2C[2] & 0x0F; | |
2207 | ||
2208 | /* only write the queue values if they are different from the actual. */ | |
2209 | if ((tempLO2CQ[0] != tempLO2C[0]) || | |
2210 | (tempLO2CQ[1] != tempLO2C[1]) || | |
2211 | (tempLO2CQ[2] != tempLO2C[2])) { | |
2212 | /* put actual LO2 value into queue (with 0 in one-shot bits) */ | |
0e301442 | 2213 | status |= |
e1de3d18 | 2214 | mt2063_write(state, |
fdf77a4f MCC |
2215 | MT2063_REG_LO2CQ_1, |
2216 | &(tempLO2C[0]), 3); | |
0e301442 | 2217 | |
fdf77a4f | 2218 | if (status == 0) { |
0e301442 | 2219 | /* cache the bytes just written. */ |
dcd52d20 | 2220 | state->reg[MT2063_REG_LO2CQ_1] = |
fdf77a4f | 2221 | tempLO2C[0]; |
dcd52d20 | 2222 | state->reg[MT2063_REG_LO2CQ_2] = |
fdf77a4f | 2223 | tempLO2C[1]; |
dcd52d20 | 2224 | state->reg[MT2063_REG_LO2CQ_3] = |
fdf77a4f | 2225 | tempLO2C[2]; |
0e301442 | 2226 | } |
fdf77a4f | 2227 | restore = 1; |
0e301442 | 2228 | } |
0e301442 | 2229 | |
fdf77a4f MCC |
2230 | /* Calculate the Divider and Numberator components of LO1 */ |
2231 | status = | |
2232 | MT2063_CalcLO1Mult(&Div, &FracN, nValue, | |
dcd52d20 | 2233 | state->AS_Data.f_ref / |
fdf77a4f | 2234 | 64, |
dcd52d20 MCC |
2235 | state->AS_Data.f_ref); |
2236 | state->reg[MT2063_REG_LO1CQ_1] = | |
fdf77a4f | 2237 | (u8) (Div & 0x00FF); |
dcd52d20 | 2238 | state->reg[MT2063_REG_LO1CQ_2] = |
fdf77a4f MCC |
2239 | (u8) (FracN); |
2240 | status |= | |
e1de3d18 | 2241 | mt2063_write(state, |
fdf77a4f | 2242 | MT2063_REG_LO1CQ_1, |
dcd52d20 | 2243 | &state-> |
fdf77a4f MCC |
2244 | reg[MT2063_REG_LO1CQ_1], 2); |
2245 | ||
2246 | /* set the one-shot bit to load the pair of LO values */ | |
2247 | tmpOneShot = tempLO2CQ[2] | 0xE0; | |
2248 | status |= | |
e1de3d18 | 2249 | mt2063_write(state, |
fdf77a4f MCC |
2250 | MT2063_REG_LO2CQ_3, |
2251 | &tmpOneShot, 1); | |
2252 | ||
2253 | /* only restore the queue values if they were different from the actual. */ | |
2254 | if (restore) { | |
2255 | /* put actual LO2 value into queue (0 in one-shot bits) */ | |
2256 | status |= | |
e1de3d18 | 2257 | mt2063_write(state, |
fdf77a4f MCC |
2258 | MT2063_REG_LO2CQ_1, |
2259 | &(tempLO2CQ[0]), 3); | |
0e301442 | 2260 | |
fdf77a4f | 2261 | /* cache the bytes just written. */ |
dcd52d20 | 2262 | state->reg[MT2063_REG_LO2CQ_1] = |
fdf77a4f | 2263 | tempLO2CQ[0]; |
dcd52d20 | 2264 | state->reg[MT2063_REG_LO2CQ_2] = |
fdf77a4f | 2265 | tempLO2CQ[1]; |
dcd52d20 | 2266 | state->reg[MT2063_REG_LO2CQ_3] = |
fdf77a4f MCC |
2267 | tempLO2CQ[2]; |
2268 | } | |
0e301442 | 2269 | |
dcd52d20 | 2270 | MT2063_GetParam(state, |
fdf77a4f | 2271 | MT2063_LO1_FREQ, |
dcd52d20 | 2272 | &state->AS_Data.f_LO1); |
fdf77a4f MCC |
2273 | } |
2274 | break; | |
0e301442 | 2275 | |
fdf77a4f MCC |
2276 | /* LO1 minimum step size */ |
2277 | case MT2063_LO1_STEPSIZE: | |
dcd52d20 | 2278 | state->AS_Data.f_LO1_Step = nValue; |
fdf77a4f | 2279 | break; |
0e301442 | 2280 | |
fdf77a4f MCC |
2281 | /* LO1 FracN keep-out region */ |
2282 | case MT2063_LO1_FRACN_AVOID_PARAM: | |
dcd52d20 | 2283 | state->AS_Data.f_LO1_FracN_Avoid = nValue; |
fdf77a4f | 2284 | break; |
0e301442 | 2285 | |
fdf77a4f MCC |
2286 | /* Requested 1st IF */ |
2287 | case MT2063_IF1_REQUEST: | |
dcd52d20 | 2288 | state->AS_Data.f_if1_Request = nValue; |
fdf77a4f | 2289 | break; |
0e301442 | 2290 | |
fdf77a4f MCC |
2291 | /* zero-IF bandwidth */ |
2292 | case MT2063_ZIF_BW: | |
dcd52d20 | 2293 | state->AS_Data.f_zif_bw = nValue; |
fdf77a4f MCC |
2294 | break; |
2295 | ||
2296 | /* LO2 frequency */ | |
2297 | case MT2063_LO2_FREQ: | |
2298 | { | |
2299 | /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */ | |
2300 | /* Capture the Divider and Numerator portions of other LO */ | |
2301 | u8 tempLO1CQ[2]; | |
2302 | u8 tempLO1C[2]; | |
2303 | u32 Div2; | |
2304 | u32 FracN2; | |
2305 | u8 tmpOneShot; | |
2306 | u8 restore = 0; | |
2307 | ||
2308 | /* Buffer the queue for restoration later and get actual LO2 values. */ | |
2309 | status |= | |
e1de3d18 | 2310 | mt2063_read(state, |
fdf77a4f MCC |
2311 | MT2063_REG_LO1CQ_1, |
2312 | &(tempLO1CQ[0]), 2); | |
2313 | status |= | |
e1de3d18 | 2314 | mt2063_read(state, |
fdf77a4f MCC |
2315 | MT2063_REG_LO1C_1, |
2316 | &(tempLO1C[0]), 2); | |
2317 | ||
2318 | /* only write the queue values if they are different from the actual. */ | |
2319 | if ((tempLO1CQ[0] != tempLO1C[0]) | |
2320 | || (tempLO1CQ[1] != tempLO1C[1])) { | |
2321 | /* put actual LO1 value into queue */ | |
0e301442 | 2322 | status |= |
e1de3d18 | 2323 | mt2063_write(state, |
0e301442 | 2324 | MT2063_REG_LO1CQ_1, |
fdf77a4f MCC |
2325 | &(tempLO1C[0]), 2); |
2326 | ||
2327 | /* cache the bytes just written. */ | |
dcd52d20 | 2328 | state->reg[MT2063_REG_LO1CQ_1] = |
fdf77a4f | 2329 | tempLO1C[0]; |
dcd52d20 | 2330 | state->reg[MT2063_REG_LO1CQ_2] = |
fdf77a4f MCC |
2331 | tempLO1C[1]; |
2332 | restore = 1; | |
2333 | } | |
0e301442 | 2334 | |
fdf77a4f MCC |
2335 | /* Calculate the Divider and Numberator components of LO2 */ |
2336 | status = | |
2337 | MT2063_CalcLO2Mult(&Div2, &FracN2, nValue, | |
dcd52d20 | 2338 | state->AS_Data.f_ref / |
fdf77a4f | 2339 | 8191, |
dcd52d20 MCC |
2340 | state->AS_Data.f_ref); |
2341 | state->reg[MT2063_REG_LO2CQ_1] = | |
fdf77a4f MCC |
2342 | (u8) ((Div2 << 1) | |
2343 | ((FracN2 >> 12) & 0x01)) & 0xFF; | |
dcd52d20 | 2344 | state->reg[MT2063_REG_LO2CQ_2] = |
fdf77a4f | 2345 | (u8) ((FracN2 >> 4) & 0xFF); |
dcd52d20 | 2346 | state->reg[MT2063_REG_LO2CQ_3] = |
fdf77a4f MCC |
2347 | (u8) ((FracN2 & 0x0F)); |
2348 | status |= | |
e1de3d18 | 2349 | mt2063_write(state, |
fdf77a4f | 2350 | MT2063_REG_LO1CQ_1, |
dcd52d20 | 2351 | &state-> |
fdf77a4f MCC |
2352 | reg[MT2063_REG_LO1CQ_1], 3); |
2353 | ||
2354 | /* set the one-shot bit to load the LO values */ | |
2355 | tmpOneShot = | |
dcd52d20 | 2356 | state->reg[MT2063_REG_LO2CQ_3] | 0xE0; |
fdf77a4f | 2357 | status |= |
e1de3d18 | 2358 | mt2063_write(state, |
fdf77a4f MCC |
2359 | MT2063_REG_LO2CQ_3, |
2360 | &tmpOneShot, 1); | |
2361 | ||
2362 | /* only restore LO1 queue value if they were different from the actual. */ | |
2363 | if (restore) { | |
2364 | /* put previous LO1 queue value back into queue */ | |
0e301442 | 2365 | status |= |
e1de3d18 | 2366 | mt2063_write(state, |
fdf77a4f MCC |
2367 | MT2063_REG_LO1CQ_1, |
2368 | &(tempLO1CQ[0]), 2); | |
0e301442 | 2369 | |
fdf77a4f | 2370 | /* cache the bytes just written. */ |
dcd52d20 | 2371 | state->reg[MT2063_REG_LO1CQ_1] = |
fdf77a4f | 2372 | tempLO1CQ[0]; |
dcd52d20 | 2373 | state->reg[MT2063_REG_LO1CQ_2] = |
fdf77a4f MCC |
2374 | tempLO1CQ[1]; |
2375 | } | |
0e301442 | 2376 | |
dcd52d20 | 2377 | MT2063_GetParam(state, |
fdf77a4f | 2378 | MT2063_LO2_FREQ, |
dcd52d20 | 2379 | &state->AS_Data.f_LO2); |
fdf77a4f MCC |
2380 | } |
2381 | break; | |
0e301442 | 2382 | |
fdf77a4f MCC |
2383 | /* LO2 minimum step size */ |
2384 | case MT2063_LO2_STEPSIZE: | |
dcd52d20 | 2385 | state->AS_Data.f_LO2_Step = nValue; |
fdf77a4f | 2386 | break; |
0e301442 | 2387 | |
fdf77a4f MCC |
2388 | /* LO2 FracN keep-out region */ |
2389 | case MT2063_LO2_FRACN_AVOID: | |
dcd52d20 | 2390 | state->AS_Data.f_LO2_FracN_Avoid = nValue; |
fdf77a4f | 2391 | break; |
0e301442 | 2392 | |
fdf77a4f MCC |
2393 | /* output center frequency */ |
2394 | case MT2063_OUTPUT_FREQ: | |
dcd52d20 | 2395 | state->AS_Data.f_out = nValue; |
fdf77a4f | 2396 | break; |
0e301442 | 2397 | |
fdf77a4f MCC |
2398 | /* output bandwidth */ |
2399 | case MT2063_OUTPUT_BW: | |
dcd52d20 | 2400 | state->AS_Data.f_out_bw = nValue + 750000; |
fdf77a4f | 2401 | break; |
0e301442 | 2402 | |
fdf77a4f MCC |
2403 | /* min inter-tuner LO separation */ |
2404 | case MT2063_LO_SEPARATION: | |
dcd52d20 | 2405 | state->AS_Data.f_min_LO_Separation = nValue; |
fdf77a4f | 2406 | break; |
0e301442 | 2407 | |
fdf77a4f MCC |
2408 | /* max # of intra-tuner harmonics */ |
2409 | case MT2063_MAX_HARM1: | |
dcd52d20 | 2410 | state->AS_Data.maxH1 = nValue; |
fdf77a4f | 2411 | break; |
0e301442 | 2412 | |
fdf77a4f MCC |
2413 | /* max # of inter-tuner harmonics */ |
2414 | case MT2063_MAX_HARM2: | |
dcd52d20 | 2415 | state->AS_Data.maxH2 = nValue; |
fdf77a4f | 2416 | break; |
0e301442 | 2417 | |
fdf77a4f MCC |
2418 | case MT2063_RCVR_MODE: |
2419 | status |= | |
dcd52d20 | 2420 | MT2063_SetReceiverMode(state, |
fdf77a4f MCC |
2421 | (enum MT2063_RCVR_MODES) |
2422 | nValue); | |
2423 | break; | |
0e301442 | 2424 | |
fdf77a4f MCC |
2425 | /* Set LNA Rin -- nValue is desired value */ |
2426 | case MT2063_LNA_RIN: | |
2427 | val = | |
dcd52d20 | 2428 | (state-> |
fdf77a4f MCC |
2429 | reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) | |
2430 | (nValue & 0x03); | |
dcd52d20 | 2431 | if (state->reg[MT2063_REG_CTRL_2C] != val) { |
0e301442 | 2432 | status |= |
dcd52d20 | 2433 | MT2063_SetReg(state, MT2063_REG_CTRL_2C, |
fdf77a4f MCC |
2434 | val); |
2435 | } | |
2436 | break; | |
0e301442 | 2437 | |
fdf77a4f MCC |
2438 | /* Set target power level at LNA -- nValue is desired value */ |
2439 | case MT2063_LNA_TGT: | |
2440 | val = | |
dcd52d20 | 2441 | (state-> |
fdf77a4f MCC |
2442 | reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) | |
2443 | (nValue & 0x3F); | |
dcd52d20 | 2444 | if (state->reg[MT2063_REG_LNA_TGT] != val) { |
fdf77a4f | 2445 | status |= |
dcd52d20 | 2446 | MT2063_SetReg(state, MT2063_REG_LNA_TGT, |
fdf77a4f MCC |
2447 | val); |
2448 | } | |
2449 | break; | |
0e301442 | 2450 | |
fdf77a4f MCC |
2451 | /* Set target power level at PD1 -- nValue is desired value */ |
2452 | case MT2063_PD1_TGT: | |
2453 | val = | |
dcd52d20 | 2454 | (state-> |
fdf77a4f MCC |
2455 | reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) | |
2456 | (nValue & 0x3F); | |
dcd52d20 | 2457 | if (state->reg[MT2063_REG_PD1_TGT] != val) { |
fdf77a4f | 2458 | status |= |
dcd52d20 | 2459 | MT2063_SetReg(state, MT2063_REG_PD1_TGT, |
fdf77a4f MCC |
2460 | val); |
2461 | } | |
2462 | break; | |
0e301442 | 2463 | |
fdf77a4f MCC |
2464 | /* Set target power level at PD2 -- nValue is desired value */ |
2465 | case MT2063_PD2_TGT: | |
2466 | val = | |
dcd52d20 | 2467 | (state-> |
fdf77a4f MCC |
2468 | reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) | |
2469 | (nValue & 0x3F); | |
dcd52d20 | 2470 | if (state->reg[MT2063_REG_PD2_TGT] != val) { |
fdf77a4f | 2471 | status |= |
dcd52d20 | 2472 | MT2063_SetReg(state, MT2063_REG_PD2_TGT, |
fdf77a4f MCC |
2473 | val); |
2474 | } | |
2475 | break; | |
0e301442 | 2476 | |
fdf77a4f MCC |
2477 | /* Set LNA atten limit -- nValue is desired value */ |
2478 | case MT2063_ACLNA_MAX: | |
2479 | val = | |
dcd52d20 | 2480 | (state-> |
fdf77a4f MCC |
2481 | reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue |
2482 | & | |
2483 | 0x1F); | |
dcd52d20 | 2484 | if (state->reg[MT2063_REG_LNA_OV] != val) { |
fdf77a4f | 2485 | status |= |
dcd52d20 | 2486 | MT2063_SetReg(state, MT2063_REG_LNA_OV, |
fdf77a4f MCC |
2487 | val); |
2488 | } | |
2489 | break; | |
0e301442 | 2490 | |
fdf77a4f MCC |
2491 | /* Set RF atten limit -- nValue is desired value */ |
2492 | case MT2063_ACRF_MAX: | |
2493 | val = | |
dcd52d20 | 2494 | (state-> |
fdf77a4f MCC |
2495 | reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue |
2496 | & | |
2497 | 0x1F); | |
dcd52d20 | 2498 | if (state->reg[MT2063_REG_RF_OV] != val) { |
fdf77a4f | 2499 | status |= |
dcd52d20 | 2500 | MT2063_SetReg(state, MT2063_REG_RF_OV, val); |
fdf77a4f MCC |
2501 | } |
2502 | break; | |
0e301442 | 2503 | |
fdf77a4f MCC |
2504 | /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */ |
2505 | case MT2063_ACFIF_MAX: | |
dcd52d20 | 2506 | if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 |
fdf77a4f MCC |
2507 | && nValue > 5) |
2508 | nValue = 5; | |
2509 | val = | |
dcd52d20 | 2510 | (state-> |
fdf77a4f MCC |
2511 | reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue |
2512 | & | |
2513 | 0x1F); | |
dcd52d20 | 2514 | if (state->reg[MT2063_REG_FIF_OV] != val) { |
fdf77a4f | 2515 | status |= |
dcd52d20 | 2516 | MT2063_SetReg(state, MT2063_REG_FIF_OV, |
fdf77a4f MCC |
2517 | val); |
2518 | } | |
2519 | break; | |
0e301442 | 2520 | |
fdf77a4f MCC |
2521 | case MT2063_DNC_OUTPUT_ENABLE: |
2522 | /* selects, which DNC output is used */ | |
29a0a4fe | 2523 | switch (nValue) { |
fdf77a4f MCC |
2524 | case MT2063_DNC_NONE: |
2525 | { | |
dcd52d20 MCC |
2526 | val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */ |
2527 | if (state->reg[MT2063_REG_DNC_GAIN] != | |
fdf77a4f MCC |
2528 | val) |
2529 | status |= | |
dcd52d20 | 2530 | MT2063_SetReg(state, |
fdf77a4f MCC |
2531 | MT2063_REG_DNC_GAIN, |
2532 | val); | |
2533 | ||
dcd52d20 MCC |
2534 | val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */ |
2535 | if (state->reg[MT2063_REG_VGA_GAIN] != | |
fdf77a4f MCC |
2536 | val) |
2537 | status |= | |
dcd52d20 | 2538 | MT2063_SetReg(state, |
fdf77a4f MCC |
2539 | MT2063_REG_VGA_GAIN, |
2540 | val); | |
2541 | ||
dcd52d20 MCC |
2542 | val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */ |
2543 | if (state->reg[MT2063_REG_RSVD_20] != | |
fdf77a4f MCC |
2544 | val) |
2545 | status |= | |
dcd52d20 | 2546 | MT2063_SetReg(state, |
fdf77a4f MCC |
2547 | MT2063_REG_RSVD_20, |
2548 | val); | |
0e301442 | 2549 | |
0e301442 MCC |
2550 | break; |
2551 | } | |
fdf77a4f MCC |
2552 | case MT2063_DNC_1: |
2553 | { | |
dcd52d20 MCC |
2554 | val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */ |
2555 | if (state->reg[MT2063_REG_DNC_GAIN] != | |
fdf77a4f MCC |
2556 | val) |
2557 | status |= | |
dcd52d20 | 2558 | MT2063_SetReg(state, |
fdf77a4f MCC |
2559 | MT2063_REG_DNC_GAIN, |
2560 | val); | |
0e301442 | 2561 | |
dcd52d20 MCC |
2562 | val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */ |
2563 | if (state->reg[MT2063_REG_VGA_GAIN] != | |
fdf77a4f MCC |
2564 | val) |
2565 | status |= | |
dcd52d20 | 2566 | MT2063_SetReg(state, |
fdf77a4f MCC |
2567 | MT2063_REG_VGA_GAIN, |
2568 | val); | |
0e301442 | 2569 | |
dcd52d20 MCC |
2570 | val = (state->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */ |
2571 | if (state->reg[MT2063_REG_RSVD_20] != | |
fdf77a4f MCC |
2572 | val) |
2573 | status |= | |
dcd52d20 | 2574 | MT2063_SetReg(state, |
fdf77a4f MCC |
2575 | MT2063_REG_RSVD_20, |
2576 | val); | |
0e301442 | 2577 | |
fdf77a4f | 2578 | break; |
0e301442 | 2579 | } |
fdf77a4f MCC |
2580 | case MT2063_DNC_2: |
2581 | { | |
dcd52d20 MCC |
2582 | val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */ |
2583 | if (state->reg[MT2063_REG_DNC_GAIN] != | |
fdf77a4f MCC |
2584 | val) |
2585 | status |= | |
dcd52d20 | 2586 | MT2063_SetReg(state, |
fdf77a4f MCC |
2587 | MT2063_REG_DNC_GAIN, |
2588 | val); | |
0e301442 | 2589 | |
dcd52d20 MCC |
2590 | val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */ |
2591 | if (state->reg[MT2063_REG_VGA_GAIN] != | |
fdf77a4f MCC |
2592 | val) |
2593 | status |= | |
dcd52d20 | 2594 | MT2063_SetReg(state, |
fdf77a4f MCC |
2595 | MT2063_REG_VGA_GAIN, |
2596 | val); | |
2597 | ||
dcd52d20 MCC |
2598 | val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */ |
2599 | if (state->reg[MT2063_REG_RSVD_20] != | |
fdf77a4f MCC |
2600 | val) |
2601 | status |= | |
dcd52d20 | 2602 | MT2063_SetReg(state, |
fdf77a4f MCC |
2603 | MT2063_REG_RSVD_20, |
2604 | val); | |
0e301442 | 2605 | |
fdf77a4f MCC |
2606 | break; |
2607 | } | |
2608 | case MT2063_DNC_BOTH: | |
0e301442 | 2609 | { |
dcd52d20 MCC |
2610 | val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03); /* Set DNC1GC=x */ |
2611 | if (state->reg[MT2063_REG_DNC_GAIN] != | |
fdf77a4f MCC |
2612 | val) |
2613 | status |= | |
dcd52d20 | 2614 | MT2063_SetReg(state, |
fdf77a4f MCC |
2615 | MT2063_REG_DNC_GAIN, |
2616 | val); | |
2617 | ||
dcd52d20 MCC |
2618 | val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03); /* Set DNC2GC=x */ |
2619 | if (state->reg[MT2063_REG_VGA_GAIN] != | |
fdf77a4f MCC |
2620 | val) |
2621 | status |= | |
dcd52d20 | 2622 | MT2063_SetReg(state, |
fdf77a4f MCC |
2623 | MT2063_REG_VGA_GAIN, |
2624 | val); | |
2625 | ||
dcd52d20 MCC |
2626 | val = (state->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */ |
2627 | if (state->reg[MT2063_REG_RSVD_20] != | |
fdf77a4f MCC |
2628 | val) |
2629 | status |= | |
dcd52d20 | 2630 | MT2063_SetReg(state, |
fdf77a4f MCC |
2631 | MT2063_REG_RSVD_20, |
2632 | val); | |
2633 | ||
2634 | break; | |
0e301442 | 2635 | } |
fdf77a4f | 2636 | default: |
0e301442 | 2637 | break; |
fdf77a4f MCC |
2638 | } |
2639 | break; | |
0e301442 | 2640 | |
fdf77a4f MCC |
2641 | case MT2063_VGAGC: |
2642 | /* Set VGA gain code */ | |
2643 | val = | |
dcd52d20 | 2644 | (state-> |
fdf77a4f MCC |
2645 | reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) | |
2646 | ((nValue & 0x03) << 2); | |
dcd52d20 | 2647 | if (state->reg[MT2063_REG_VGA_GAIN] != val) { |
fdf77a4f | 2648 | status |= |
dcd52d20 | 2649 | MT2063_SetReg(state, MT2063_REG_VGA_GAIN, |
fdf77a4f MCC |
2650 | val); |
2651 | } | |
2652 | break; | |
0e301442 | 2653 | |
fdf77a4f MCC |
2654 | case MT2063_VGAOI: |
2655 | /* Set VGA bias current */ | |
2656 | val = | |
dcd52d20 | 2657 | (state-> |
fdf77a4f MCC |
2658 | reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) | |
2659 | (nValue & 0x07); | |
dcd52d20 | 2660 | if (state->reg[MT2063_REG_RSVD_31] != val) { |
fdf77a4f | 2661 | status |= |
dcd52d20 | 2662 | MT2063_SetReg(state, MT2063_REG_RSVD_31, |
fdf77a4f | 2663 | val); |
223c7b05 | 2664 | } |
fdf77a4f MCC |
2665 | break; |
2666 | ||
2667 | case MT2063_TAGC: | |
2668 | /* Set TAGC */ | |
2669 | val = | |
dcd52d20 | 2670 | (state-> |
fdf77a4f MCC |
2671 | reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) | |
2672 | (nValue & 0x03); | |
dcd52d20 | 2673 | if (state->reg[MT2063_REG_RSVD_1E] != val) { |
fdf77a4f | 2674 | status |= |
dcd52d20 | 2675 | MT2063_SetReg(state, MT2063_REG_RSVD_1E, |
fdf77a4f MCC |
2676 | val); |
2677 | } | |
2678 | break; | |
2679 | ||
2680 | case MT2063_AMPGC: | |
2681 | /* Set Amp gain code */ | |
2682 | val = | |
dcd52d20 | 2683 | (state-> |
fdf77a4f MCC |
2684 | reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) | |
2685 | (nValue & 0x03); | |
dcd52d20 | 2686 | if (state->reg[MT2063_REG_TEMP_SEL] != val) { |
fdf77a4f | 2687 | status |= |
dcd52d20 | 2688 | MT2063_SetReg(state, MT2063_REG_TEMP_SEL, |
fdf77a4f MCC |
2689 | val); |
2690 | } | |
2691 | break; | |
2692 | ||
2693 | /* Avoid DECT Frequencies */ | |
2694 | case MT2063_AVOID_DECT: | |
2695 | { | |
2696 | enum MT2063_DECT_Avoid_Type newAvoidSetting = | |
2697 | (enum MT2063_DECT_Avoid_Type)nValue; | |
2698 | if ((newAvoidSetting >= | |
2699 | MT2063_NO_DECT_AVOIDANCE) | |
2700 | && (newAvoidSetting <= MT2063_AVOID_BOTH)) { | |
dcd52d20 | 2701 | state->AS_Data.avoidDECT = |
fdf77a4f MCC |
2702 | newAvoidSetting; |
2703 | } | |
2704 | } | |
2705 | break; | |
2706 | ||
2707 | /* Cleartune filter selection: 0 - by IC (default), 1 - by software */ | |
2708 | case MT2063_CTFILT_SW: | |
dcd52d20 | 2709 | state->ctfilt_sw = (nValue & 0x01); |
fdf77a4f MCC |
2710 | break; |
2711 | ||
2712 | /* These parameters are read-only */ | |
2713 | case MT2063_IC_ADDR: | |
2714 | case MT2063_MAX_OPEN: | |
2715 | case MT2063_NUM_OPEN: | |
2716 | case MT2063_INPUT_FREQ: | |
2717 | case MT2063_IF1_ACTUAL: | |
2718 | case MT2063_IF1_CENTER: | |
2719 | case MT2063_IF1_BW: | |
2720 | case MT2063_AS_ALG: | |
2721 | case MT2063_EXCL_ZONES: | |
2722 | case MT2063_SPUR_AVOIDED: | |
2723 | case MT2063_NUM_SPURS: | |
2724 | case MT2063_SPUR_PRESENT: | |
2725 | case MT2063_ACLNA: | |
2726 | case MT2063_ACRF: | |
2727 | case MT2063_ACFIF: | |
2728 | case MT2063_EOP: | |
2729 | default: | |
2730 | status |= -ERANGE; | |
0e301442 MCC |
2731 | } |
2732 | return (status); | |
2733 | } | |
2734 | ||
0e301442 MCC |
2735 | /**************************************************************************** |
2736 | ** | |
2737 | ** Name: MT2063_ClearPowerMaskBits | |
2738 | ** | |
2739 | ** Description: Clears the power-down mask bits for various sections of | |
2740 | ** the MT2063 | |
2741 | ** | |
2742 | ** Parameters: h - Tuner handle (returned by MT2063_Open) | |
2743 | ** Bits - Mask bits to be cleared. | |
2744 | ** | |
2745 | ** See definition of MT2063_Mask_Bits type for description | |
2746 | ** of each of the power bits. | |
2747 | ** | |
2748 | ** Returns: status: | |
2749 | ** MT_OK - No errors | |
2750 | ** MT_INV_HANDLE - Invalid tuner handle | |
2751 | ** MT_COMM_ERR - Serial bus communications error | |
2752 | ** | |
2753 | ** Dependencies: USERS MUST CALL MT2063_Open() FIRST! | |
2754 | ** | |
2755 | ** Revision History: | |
2756 | ** | |
2757 | ** SCR Date Author Description | |
2758 | ** ------------------------------------------------------------------------- | |
2759 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
2760 | ** | |
2761 | ****************************************************************************/ | |
dcd52d20 | 2762 | static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state, enum MT2063_Mask_Bits Bits) |
0e301442 | 2763 | { |
fdf77a4f | 2764 | u32 status = 0; /* Status to be returned */ |
0e301442 | 2765 | |
fdf77a4f MCC |
2766 | Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */ |
2767 | if ((Bits & 0xFF00) != 0) { | |
dcd52d20 | 2768 | state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8); |
fdf77a4f | 2769 | status |= |
e1de3d18 | 2770 | mt2063_write(state, |
fdf77a4f | 2771 | MT2063_REG_PWR_2, |
dcd52d20 | 2772 | &state->reg[MT2063_REG_PWR_2], 1); |
fdf77a4f MCC |
2773 | } |
2774 | if ((Bits & 0xFF) != 0) { | |
dcd52d20 | 2775 | state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF); |
fdf77a4f | 2776 | status |= |
e1de3d18 | 2777 | mt2063_write(state, |
fdf77a4f | 2778 | MT2063_REG_PWR_1, |
dcd52d20 | 2779 | &state->reg[MT2063_REG_PWR_1], 1); |
0e301442 MCC |
2780 | } |
2781 | ||
2782 | return (status); | |
2783 | } | |
2784 | ||
0e301442 MCC |
2785 | /**************************************************************************** |
2786 | ** | |
2787 | ** Name: MT2063_SoftwareShutdown | |
2788 | ** | |
2789 | ** Description: Enables or disables software shutdown function. When | |
2790 | ** Shutdown==1, any section whose power mask is set will be | |
2791 | ** shutdown. | |
2792 | ** | |
2793 | ** Parameters: h - Tuner handle (returned by MT2063_Open) | |
2794 | ** Shutdown - 1 = shutdown the masked sections, otherwise | |
2795 | ** power all sections on | |
2796 | ** | |
2797 | ** Returns: status: | |
2798 | ** MT_OK - No errors | |
2799 | ** MT_INV_HANDLE - Invalid tuner handle | |
2800 | ** MT_COMM_ERR - Serial bus communications error | |
2801 | ** | |
2802 | ** Dependencies: USERS MUST CALL MT2063_Open() FIRST! | |
2803 | ** | |
2804 | ** Revision History: | |
2805 | ** | |
2806 | ** SCR Date Author Description | |
2807 | ** ------------------------------------------------------------------------- | |
2808 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
2809 | ** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for | |
2810 | ** correct wakeup of the LNA | |
2811 | ** | |
2812 | ****************************************************************************/ | |
dcd52d20 | 2813 | static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown) |
0e301442 | 2814 | { |
fdf77a4f | 2815 | u32 status = 0; /* Status to be returned */ |
0e301442 | 2816 | |
fdf77a4f | 2817 | if (Shutdown == 1) |
dcd52d20 | 2818 | state->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */ |
fdf77a4f | 2819 | else |
dcd52d20 | 2820 | state->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */ |
0e301442 | 2821 | |
fdf77a4f | 2822 | status |= |
e1de3d18 | 2823 | mt2063_write(state, |
fdf77a4f | 2824 | MT2063_REG_PWR_1, |
dcd52d20 | 2825 | &state->reg[MT2063_REG_PWR_1], 1); |
fdf77a4f MCC |
2826 | |
2827 | if (Shutdown != 1) { | |
dcd52d20 MCC |
2828 | state->reg[MT2063_REG_BYP_CTRL] = |
2829 | (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40; | |
0e301442 | 2830 | status |= |
e1de3d18 | 2831 | mt2063_write(state, |
fdf77a4f | 2832 | MT2063_REG_BYP_CTRL, |
dcd52d20 | 2833 | &state->reg[MT2063_REG_BYP_CTRL], |
fdf77a4f | 2834 | 1); |
dcd52d20 MCC |
2835 | state->reg[MT2063_REG_BYP_CTRL] = |
2836 | (state->reg[MT2063_REG_BYP_CTRL] & 0x9F); | |
fdf77a4f | 2837 | status |= |
e1de3d18 | 2838 | mt2063_write(state, |
fdf77a4f | 2839 | MT2063_REG_BYP_CTRL, |
dcd52d20 | 2840 | &state->reg[MT2063_REG_BYP_CTRL], |
fdf77a4f | 2841 | 1); |
0e301442 MCC |
2842 | } |
2843 | ||
2844 | return (status); | |
2845 | } | |
2846 | ||
0e301442 MCC |
2847 | /**************************************************************************** |
2848 | ** | |
2849 | ** Name: MT2063_SetReg | |
2850 | ** | |
2851 | ** Description: Sets an MT2063 register. | |
2852 | ** | |
2853 | ** Parameters: h - Tuner handle (returned by MT2063_Open) | |
2854 | ** reg - MT2063 register/subaddress location | |
2855 | ** val - MT2063 register/subaddress value | |
2856 | ** | |
2857 | ** Returns: status: | |
2858 | ** MT_OK - No errors | |
2859 | ** MT_COMM_ERR - Serial bus communications error | |
2860 | ** MT_INV_HANDLE - Invalid tuner handle | |
2861 | ** MT_ARG_RANGE - Argument out of range | |
2862 | ** | |
2863 | ** Dependencies: USERS MUST CALL MT2063_Open() FIRST! | |
2864 | ** | |
2865 | ** Use this function if you need to override a default | |
2866 | ** register value | |
2867 | ** | |
2868 | ** Revision History: | |
2869 | ** | |
2870 | ** SCR Date Author Description | |
2871 | ** ------------------------------------------------------------------------- | |
2872 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
2873 | ** | |
2874 | ****************************************************************************/ | |
dcd52d20 | 2875 | static u32 MT2063_SetReg(struct mt2063_state *state, u8 reg, u8 val) |
0e301442 | 2876 | { |
fdf77a4f | 2877 | u32 status = 0; /* Status to be returned */ |
0e301442 | 2878 | |
0e301442 | 2879 | if (reg >= MT2063_REG_END_REGS) |
fdf77a4f | 2880 | status |= -ERANGE; |
0e301442 | 2881 | |
e1de3d18 | 2882 | status = mt2063_write(state, reg, &val, |
fdf77a4f MCC |
2883 | 1); |
2884 | if (status >= 0) | |
dcd52d20 | 2885 | state->reg[reg] = val; |
0e301442 MCC |
2886 | |
2887 | return (status); | |
2888 | } | |
2889 | ||
cfde8925 | 2890 | static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref) |
0e301442 MCC |
2891 | { |
2892 | return f_ref * (f_LO / f_ref) | |
2893 | + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step); | |
2894 | } | |
2895 | ||
2896 | /**************************************************************************** | |
2897 | ** | |
2898 | ** Name: fLO_FractionalTerm | |
2899 | ** | |
2900 | ** Description: Calculates the portion contributed by FracN / denom. | |
2901 | ** | |
2902 | ** This function preserves maximum precision without | |
2903 | ** risk of overflow. It accurately calculates | |
2904 | ** f_ref * num / denom to within 1 HZ with fixed math. | |
2905 | ** | |
2906 | ** Parameters: num - Fractional portion of the multiplier | |
2907 | ** denom - denominator portion of the ratio | |
2908 | ** This routine successfully handles denom values | |
2909 | ** up to and including 2^18. | |
2910 | ** f_Ref - SRO frequency. This calculation handles | |
2911 | ** f_ref as two separate 14-bit fields. | |
2912 | ** Therefore, a maximum value of 2^28-1 | |
2913 | ** may safely be used for f_ref. This is | |
2914 | ** the genesis of the magic number "14" and the | |
2915 | ** magic mask value of 0x03FFF. | |
2916 | ** | |
2917 | ** Returns: f_ref * num / denom | |
2918 | ** | |
2919 | ** Revision History: | |
2920 | ** | |
2921 | ** SCR Date Author Description | |
2922 | ** ------------------------------------------------------------------------- | |
2923 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
2924 | ** | |
2925 | ****************************************************************************/ | |
cfde8925 MCC |
2926 | static u32 MT2063_fLO_FractionalTerm(u32 f_ref, |
2927 | u32 num, u32 denom) | |
0e301442 | 2928 | { |
cfde8925 MCC |
2929 | u32 t1 = (f_ref >> 14) * num; |
2930 | u32 term1 = t1 / denom; | |
2931 | u32 loss = t1 % denom; | |
2932 | u32 term2 = | |
0e301442 MCC |
2933 | (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom; |
2934 | return ((term1 << 14) + term2); | |
2935 | } | |
2936 | ||
2937 | /**************************************************************************** | |
2938 | ** | |
2939 | ** Name: CalcLO1Mult | |
2940 | ** | |
2941 | ** Description: Calculates Integer divider value and the numerator | |
2942 | ** value for a FracN PLL. | |
2943 | ** | |
2944 | ** This function assumes that the f_LO and f_Ref are | |
2945 | ** evenly divisible by f_LO_Step. | |
2946 | ** | |
2947 | ** Parameters: Div - OUTPUT: Whole number portion of the multiplier | |
2948 | ** FracN - OUTPUT: Fractional portion of the multiplier | |
2949 | ** f_LO - desired LO frequency. | |
2950 | ** f_LO_Step - Minimum step size for the LO (in Hz). | |
2951 | ** f_Ref - SRO frequency. | |
2952 | ** f_Avoid - Range of PLL frequencies to avoid near | |
2953 | ** integer multiples of f_Ref (in Hz). | |
2954 | ** | |
2955 | ** Returns: Recalculated LO frequency. | |
2956 | ** | |
2957 | ** Revision History: | |
2958 | ** | |
2959 | ** SCR Date Author Description | |
2960 | ** ------------------------------------------------------------------------- | |
2961 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
2962 | ** | |
2963 | ****************************************************************************/ | |
cfde8925 MCC |
2964 | static u32 MT2063_CalcLO1Mult(u32 * Div, |
2965 | u32 * FracN, | |
2966 | u32 f_LO, | |
2967 | u32 f_LO_Step, u32 f_Ref) | |
0e301442 MCC |
2968 | { |
2969 | /* Calculate the whole number portion of the divider */ | |
2970 | *Div = f_LO / f_Ref; | |
2971 | ||
2972 | /* Calculate the numerator value (round to nearest f_LO_Step) */ | |
2973 | *FracN = | |
2974 | (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) + | |
2975 | (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step); | |
2976 | ||
2977 | return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64); | |
2978 | } | |
2979 | ||
2980 | /**************************************************************************** | |
2981 | ** | |
2982 | ** Name: CalcLO2Mult | |
2983 | ** | |
2984 | ** Description: Calculates Integer divider value and the numerator | |
2985 | ** value for a FracN PLL. | |
2986 | ** | |
2987 | ** This function assumes that the f_LO and f_Ref are | |
2988 | ** evenly divisible by f_LO_Step. | |
2989 | ** | |
2990 | ** Parameters: Div - OUTPUT: Whole number portion of the multiplier | |
2991 | ** FracN - OUTPUT: Fractional portion of the multiplier | |
2992 | ** f_LO - desired LO frequency. | |
2993 | ** f_LO_Step - Minimum step size for the LO (in Hz). | |
2994 | ** f_Ref - SRO frequency. | |
2995 | ** f_Avoid - Range of PLL frequencies to avoid near | |
2996 | ** integer multiples of f_Ref (in Hz). | |
2997 | ** | |
2998 | ** Returns: Recalculated LO frequency. | |
2999 | ** | |
3000 | ** Revision History: | |
3001 | ** | |
3002 | ** SCR Date Author Description | |
3003 | ** ------------------------------------------------------------------------- | |
3004 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
3005 | ** | |
3006 | ****************************************************************************/ | |
cfde8925 MCC |
3007 | static u32 MT2063_CalcLO2Mult(u32 * Div, |
3008 | u32 * FracN, | |
3009 | u32 f_LO, | |
3010 | u32 f_LO_Step, u32 f_Ref) | |
0e301442 MCC |
3011 | { |
3012 | /* Calculate the whole number portion of the divider */ | |
3013 | *Div = f_LO / f_Ref; | |
3014 | ||
3015 | /* Calculate the numerator value (round to nearest f_LO_Step) */ | |
3016 | *FracN = | |
3017 | (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) + | |
3018 | (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step); | |
3019 | ||
3020 | return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, | |
3021 | 8191); | |
3022 | } | |
3023 | ||
3024 | /**************************************************************************** | |
3025 | ** | |
3026 | ** Name: FindClearTuneFilter | |
3027 | ** | |
3028 | ** Description: Calculate the corrrect ClearTune filter to be used for | |
3029 | ** a given input frequency. | |
3030 | ** | |
dcd52d20 | 3031 | ** Parameters: state - ptr to tuner data structure |
0e301442 MCC |
3032 | ** f_in - RF input center frequency (in Hz). |
3033 | ** | |
3034 | ** Returns: ClearTune filter number (0-31) | |
3035 | ** | |
3036 | ** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter! | |
3037 | ** | |
3038 | ** Revision History: | |
3039 | ** | |
3040 | ** SCR Date Author Description | |
3041 | ** ------------------------------------------------------------------------- | |
3042 | ** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune | |
3043 | ** cross-over frequency values. | |
3044 | ** | |
3045 | ****************************************************************************/ | |
dcd52d20 | 3046 | static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in) |
0e301442 | 3047 | { |
cfde8925 MCC |
3048 | u32 RFBand; |
3049 | u32 idx; /* index loop */ | |
0e301442 MCC |
3050 | |
3051 | /* | |
3052 | ** Find RF Band setting | |
3053 | */ | |
3054 | RFBand = 31; /* def when f_in > all */ | |
3055 | for (idx = 0; idx < 31; ++idx) { | |
dcd52d20 | 3056 | if (state->CTFiltMax[idx] >= f_in) { |
0e301442 MCC |
3057 | RFBand = idx; |
3058 | break; | |
3059 | } | |
3060 | } | |
3061 | return (RFBand); | |
3062 | } | |
3063 | ||
3064 | /**************************************************************************** | |
3065 | ** | |
3066 | ** Name: MT2063_Tune | |
3067 | ** | |
3068 | ** Description: Change the tuner's tuned frequency to RFin. | |
3069 | ** | |
3070 | ** Parameters: h - Open handle to the tuner (from MT2063_Open). | |
3071 | ** f_in - RF input center frequency (in Hz). | |
3072 | ** | |
3073 | ** Returns: status: | |
3074 | ** MT_OK - No errors | |
3075 | ** MT_INV_HANDLE - Invalid tuner handle | |
3076 | ** MT_UPC_UNLOCK - Upconverter PLL unlocked | |
3077 | ** MT_DNC_UNLOCK - Downconverter PLL unlocked | |
3078 | ** MT_COMM_ERR - Serial bus communications error | |
3079 | ** MT_SPUR_CNT_MASK - Count of avoided LO spurs | |
3080 | ** MT_SPUR_PRESENT - LO spur possible in output | |
3081 | ** MT_FIN_RANGE - Input freq out of range | |
3082 | ** MT_FOUT_RANGE - Output freq out of range | |
3083 | ** MT_UPC_RANGE - Upconverter freq out of range | |
3084 | ** MT_DNC_RANGE - Downconverter freq out of range | |
3085 | ** | |
3086 | ** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune! | |
3087 | ** | |
3088 | ** MT_ReadSub - Read data from the two-wire serial bus | |
3089 | ** MT_WriteSub - Write data to the two-wire serial bus | |
3090 | ** MT_Sleep - Delay execution for x milliseconds | |
3091 | ** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked | |
3092 | ** | |
3093 | ** Revision History: | |
3094 | ** | |
3095 | ** SCR Date Author Description | |
3096 | ** ------------------------------------------------------------------------- | |
3097 | ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. | |
3098 | ** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune | |
3099 | ** cross-over frequency values. | |
3100 | ** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs. | |
3101 | ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. | |
3102 | ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW | |
3103 | ** | |
3104 | ****************************************************************************/ | |
dcd52d20 | 3105 | static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in) |
0e301442 | 3106 | { /* RF input center frequency */ |
0e301442 | 3107 | |
fdf77a4f | 3108 | u32 status = 0; /* status of operation */ |
cfde8925 MCC |
3109 | u32 LO1; /* 1st LO register value */ |
3110 | u32 Num1; /* Numerator for LO1 reg. value */ | |
3111 | u32 f_IF1; /* 1st IF requested */ | |
3112 | u32 LO2; /* 2nd LO register value */ | |
3113 | u32 Num2; /* Numerator for LO2 reg. value */ | |
3114 | u32 ofLO1, ofLO2; /* last time's LO frequencies */ | |
3115 | u32 ofin, ofout; /* last time's I/O frequencies */ | |
3116 | u8 fiffc = 0x80; /* FIFF center freq from tuner */ | |
3117 | u32 fiffof; /* Offset from FIFF center freq */ | |
3118 | const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */ | |
3119 | u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */ | |
3120 | u8 val; | |
3121 | u32 RFBand; | |
0e301442 | 3122 | |
0e301442 MCC |
3123 | /* Check the input and output frequency ranges */ |
3124 | if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ)) | |
fdf77a4f | 3125 | return -EINVAL; |
0e301442 | 3126 | |
dcd52d20 MCC |
3127 | if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ) |
3128 | || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ)) | |
fdf77a4f | 3129 | return -EINVAL; |
0e301442 MCC |
3130 | |
3131 | /* | |
3132 | ** Save original LO1 and LO2 register values | |
3133 | */ | |
dcd52d20 MCC |
3134 | ofLO1 = state->AS_Data.f_LO1; |
3135 | ofLO2 = state->AS_Data.f_LO2; | |
3136 | ofin = state->AS_Data.f_in; | |
3137 | ofout = state->AS_Data.f_out; | |
0e301442 MCC |
3138 | |
3139 | /* | |
3140 | ** Find and set RF Band setting | |
3141 | */ | |
dcd52d20 MCC |
3142 | if (state->ctfilt_sw == 1) { |
3143 | val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08); | |
3144 | if (state->reg[MT2063_REG_CTUNE_CTRL] != val) { | |
0e301442 | 3145 | status |= |
dcd52d20 | 3146 | MT2063_SetReg(state, MT2063_REG_CTUNE_CTRL, val); |
0e301442 | 3147 | } |
dcd52d20 MCC |
3148 | val = state->reg[MT2063_REG_CTUNE_OV]; |
3149 | RFBand = FindClearTuneFilter(state, f_in); | |
3150 | state->reg[MT2063_REG_CTUNE_OV] = | |
3151 | (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F) | |
0e301442 | 3152 | | RFBand); |
dcd52d20 | 3153 | if (state->reg[MT2063_REG_CTUNE_OV] != val) { |
0e301442 | 3154 | status |= |
dcd52d20 | 3155 | MT2063_SetReg(state, MT2063_REG_CTUNE_OV, val); |
0e301442 MCC |
3156 | } |
3157 | } | |
3158 | ||
3159 | /* | |
3160 | ** Read the FIFF Center Frequency from the tuner | |
3161 | */ | |
fdf77a4f | 3162 | if (status >= 0) { |
0e301442 | 3163 | status |= |
e1de3d18 | 3164 | mt2063_read(state, |
0e301442 | 3165 | MT2063_REG_FIFFC, |
dcd52d20 MCC |
3166 | &state->reg[MT2063_REG_FIFFC], 1); |
3167 | fiffc = state->reg[MT2063_REG_FIFFC]; | |
0e301442 MCC |
3168 | } |
3169 | /* | |
3170 | ** Assign in the requested values | |
3171 | */ | |
dcd52d20 | 3172 | state->AS_Data.f_in = f_in; |
0e301442 | 3173 | /* Request a 1st IF such that LO1 is on a step size */ |
dcd52d20 MCC |
3174 | state->AS_Data.f_if1_Request = |
3175 | MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in, | |
3176 | state->AS_Data.f_LO1_Step, | |
3177 | state->AS_Data.f_ref) - f_in; | |
0e301442 MCC |
3178 | |
3179 | /* | |
3180 | ** Calculate frequency settings. f_IF1_FREQ + f_in is the | |
3181 | ** desired LO1 frequency | |
3182 | */ | |
dcd52d20 | 3183 | MT2063_ResetExclZones(&state->AS_Data); |
0e301442 | 3184 | |
dcd52d20 | 3185 | f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data); |
0e301442 | 3186 | |
dcd52d20 MCC |
3187 | state->AS_Data.f_LO1 = |
3188 | MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step, | |
3189 | state->AS_Data.f_ref); | |
0e301442 | 3190 | |
dcd52d20 MCC |
3191 | state->AS_Data.f_LO2 = |
3192 | MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in, | |
3193 | state->AS_Data.f_LO2_Step, state->AS_Data.f_ref); | |
0e301442 MCC |
3194 | |
3195 | /* | |
3196 | ** Check for any LO spurs in the output bandwidth and adjust | |
3197 | ** the LO settings to avoid them if needed | |
3198 | */ | |
dcd52d20 | 3199 | status |= MT2063_AvoidSpurs(state, &state->AS_Data); |
0e301442 MCC |
3200 | /* |
3201 | ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values. | |
3202 | ** Recalculate the LO frequencies and the values to be placed | |
3203 | ** in the tuning registers. | |
3204 | */ | |
dcd52d20 MCC |
3205 | state->AS_Data.f_LO1 = |
3206 | MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1, | |
3207 | state->AS_Data.f_LO1_Step, state->AS_Data.f_ref); | |
3208 | state->AS_Data.f_LO2 = | |
3209 | MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in, | |
3210 | state->AS_Data.f_LO2_Step, state->AS_Data.f_ref); | |
3211 | state->AS_Data.f_LO2 = | |
3212 | MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2, | |
3213 | state->AS_Data.f_LO2_Step, state->AS_Data.f_ref); | |
0e301442 MCC |
3214 | |
3215 | /* | |
3216 | ** Check the upconverter and downconverter frequency ranges | |
3217 | */ | |
dcd52d20 MCC |
3218 | if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ) |
3219 | || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ)) | |
0e301442 | 3220 | status |= MT2063_UPC_RANGE; |
dcd52d20 MCC |
3221 | if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ) |
3222 | || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ)) | |
0e301442 MCC |
3223 | status |= MT2063_DNC_RANGE; |
3224 | /* LO2 Lock bit was in a different place for B0 version */ | |
dcd52d20 | 3225 | if (state->tuner_id == MT2063_B0) |
0e301442 MCC |
3226 | LO2LK = 0x40; |
3227 | ||
3228 | /* | |
3229 | ** If we have the same LO frequencies and we're already locked, | |
3230 | ** then skip re-programming the LO registers. | |
3231 | */ | |
dcd52d20 MCC |
3232 | if ((ofLO1 != state->AS_Data.f_LO1) |
3233 | || (ofLO2 != state->AS_Data.f_LO2) | |
3234 | || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) != | |
0e301442 MCC |
3235 | (LO1LK | LO2LK))) { |
3236 | /* | |
3237 | ** Calculate the FIFFOF register value | |
3238 | ** | |
3239 | ** IF1_Actual | |
3240 | ** FIFFOF = ------------ - 8 * FIFFC - 4992 | |
3241 | ** f_ref/64 | |
3242 | */ | |
3243 | fiffof = | |
dcd52d20 MCC |
3244 | (state->AS_Data.f_LO1 - |
3245 | f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc - | |
0e301442 MCC |
3246 | 4992; |
3247 | if (fiffof > 0xFF) | |
3248 | fiffof = 0xFF; | |
3249 | ||
3250 | /* | |
3251 | ** Place all of the calculated values into the local tuner | |
3252 | ** register fields. | |
3253 | */ | |
fdf77a4f | 3254 | if (status >= 0) { |
dcd52d20 MCC |
3255 | state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */ |
3256 | state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */ | |
3257 | state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */ | |
0e301442 | 3258 | |(Num2 >> 12)); /* NUM2q (hi) */ |
dcd52d20 MCC |
3259 | state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */ |
3260 | state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */ | |
0e301442 MCC |
3261 | |
3262 | /* | |
3263 | ** Now write out the computed register values | |
3264 | ** IMPORTANT: There is a required order for writing | |
3265 | ** (0x05 must follow all the others). | |
3266 | */ | |
e1de3d18 | 3267 | status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */ |
dcd52d20 | 3268 | if (state->tuner_id == MT2063_B0) { |
0e301442 | 3269 | /* Re-write the one-shot bits to trigger the tune operation */ |
e1de3d18 | 3270 | status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */ |
0e301442 MCC |
3271 | } |
3272 | /* Write out the FIFF offset only if it's changing */ | |
dcd52d20 | 3273 | if (state->reg[MT2063_REG_FIFF_OFFSET] != |
cfde8925 | 3274 | (u8) fiffof) { |
dcd52d20 | 3275 | state->reg[MT2063_REG_FIFF_OFFSET] = |
cfde8925 | 3276 | (u8) fiffof; |
0e301442 | 3277 | status |= |
e1de3d18 | 3278 | mt2063_write(state, |
0e301442 | 3279 | MT2063_REG_FIFF_OFFSET, |
dcd52d20 | 3280 | &state-> |
0e301442 MCC |
3281 | reg[MT2063_REG_FIFF_OFFSET], |
3282 | 1); | |
3283 | } | |
3284 | } | |
3285 | ||
3286 | /* | |
3287 | ** Check for LO's locking | |
3288 | */ | |
3289 | ||
fdf77a4f | 3290 | if (status >= 0) { |
dcd52d20 | 3291 | status |= MT2063_GetLocked(state); |
0e301442 MCC |
3292 | } |
3293 | /* | |
51f0f7b3 | 3294 | ** If we locked OK, assign calculated data to mt2063_state structure |
0e301442 | 3295 | */ |
fdf77a4f | 3296 | if (status >= 0) { |
dcd52d20 | 3297 | state->f_IF1_actual = state->AS_Data.f_LO1 - f_in; |
0e301442 MCC |
3298 | } |
3299 | } | |
3300 | ||
3301 | return (status); | |
3302 | } | |
3303 | ||
bf97555e | 3304 | static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in, |
0e301442 MCC |
3305 | enum MTTune_atv_standard tv_type) |
3306 | { | |
3307 | ||
fdf77a4f | 3308 | u32 status = 0; |
0e301442 | 3309 | |
cfde8925 MCC |
3310 | s32 pict_car = 0; |
3311 | s32 pict2chanb_vsb = 0; | |
3312 | s32 pict2chanb_snd = 0; | |
3313 | s32 pict2snd1 = 0; | |
3314 | s32 pict2snd2 = 0; | |
3315 | s32 ch_bw = 0; | |
0e301442 | 3316 | |
cfde8925 MCC |
3317 | s32 if_mid = 0; |
3318 | s32 rcvr_mode = 0; | |
3319 | u32 mode_get = 0; | |
0e301442 MCC |
3320 | |
3321 | switch (tv_type) { | |
3322 | case MTTUNEA_PAL_B:{ | |
3323 | pict_car = 38900000; | |
3324 | ch_bw = 8000000; | |
3325 | pict2chanb_vsb = -1250000; | |
3326 | pict2snd1 = 5500000; | |
3327 | pict2snd2 = 5742000; | |
3328 | rcvr_mode = 1; | |
3329 | break; | |
3330 | } | |
3331 | case MTTUNEA_PAL_G:{ | |
3332 | pict_car = 38900000; | |
3333 | ch_bw = 7000000; | |
3334 | pict2chanb_vsb = -1250000; | |
3335 | pict2snd1 = 5500000; | |
3336 | pict2snd2 = 0; | |
3337 | rcvr_mode = 1; | |
3338 | break; | |
3339 | } | |
3340 | case MTTUNEA_PAL_I:{ | |
3341 | pict_car = 38900000; | |
3342 | ch_bw = 8000000; | |
3343 | pict2chanb_vsb = -1250000; | |
3344 | pict2snd1 = 6000000; | |
3345 | pict2snd2 = 0; | |
3346 | rcvr_mode = 1; | |
3347 | break; | |
3348 | } | |
3349 | case MTTUNEA_PAL_L:{ | |
3350 | pict_car = 38900000; | |
3351 | ch_bw = 8000000; | |
3352 | pict2chanb_vsb = -1250000; | |
3353 | pict2snd1 = 6500000; | |
3354 | pict2snd2 = 0; | |
3355 | rcvr_mode = 1; | |
3356 | break; | |
3357 | } | |
3358 | case MTTUNEA_PAL_MN:{ | |
3359 | pict_car = 38900000; | |
3360 | ch_bw = 6000000; | |
3361 | pict2chanb_vsb = -1250000; | |
3362 | pict2snd1 = 4500000; | |
3363 | pict2snd2 = 0; | |
3364 | rcvr_mode = 1; | |
3365 | break; | |
3366 | } | |
3367 | case MTTUNEA_PAL_DK:{ | |
3368 | pict_car = 38900000; | |
3369 | ch_bw = 8000000; | |
3370 | pict2chanb_vsb = -1250000; | |
3371 | pict2snd1 = 6500000; | |
3372 | pict2snd2 = 0; | |
3373 | rcvr_mode = 1; | |
3374 | break; | |
3375 | } | |
3376 | case MTTUNEA_DIGITAL:{ | |
3377 | pict_car = 36125000; | |
3378 | ch_bw = 8000000; | |
3379 | pict2chanb_vsb = -(ch_bw / 2); | |
3380 | pict2snd1 = 0; | |
3381 | pict2snd2 = 0; | |
3382 | rcvr_mode = 2; | |
3383 | break; | |
3384 | } | |
3385 | case MTTUNEA_FMRADIO:{ | |
3386 | pict_car = 38900000; | |
3387 | ch_bw = 8000000; | |
3388 | pict2chanb_vsb = -(ch_bw / 2); | |
3389 | pict2snd1 = 0; | |
3390 | pict2snd2 = 0; | |
3391 | rcvr_mode = 4; | |
3392 | //f_in -= 2900000; | |
3393 | break; | |
3394 | } | |
3395 | case MTTUNEA_DVBC:{ | |
3396 | pict_car = 36125000; | |
3397 | ch_bw = 8000000; | |
3398 | pict2chanb_vsb = -(ch_bw / 2); | |
3399 | pict2snd1 = 0; | |
3400 | pict2snd2 = 0; | |
3401 | rcvr_mode = MT2063_CABLE_QAM; | |
3402 | break; | |
3403 | } | |
3404 | case MTTUNEA_DVBT:{ | |
3405 | pict_car = 36125000; | |
3406 | ch_bw = bw_in; //8000000 | |
3407 | pict2chanb_vsb = -(ch_bw / 2); | |
3408 | pict2snd1 = 0; | |
3409 | pict2snd2 = 0; | |
3410 | rcvr_mode = MT2063_OFFAIR_COFDM; | |
3411 | break; | |
3412 | } | |
3413 | case MTTUNEA_UNKNOWN: | |
3414 | break; | |
3415 | default: | |
3416 | break; | |
3417 | } | |
3418 | ||
3419 | pict2chanb_snd = pict2chanb_vsb - ch_bw; | |
3420 | if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2)); | |
3421 | ||
3422 | status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000); | |
3423 | status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid); | |
3424 | status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw); | |
3425 | status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get); | |
3426 | ||
3427 | status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode); | |
3428 | status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2)))); | |
3429 | status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get); | |
3430 | ||
cfde8925 | 3431 | return (u32) status; |
0e301442 MCC |
3432 | } |
3433 | ||
01e0dafc MCC |
3434 | static const u8 MT2063B0_defaults[] = { |
3435 | /* Reg, Value */ | |
3436 | 0x19, 0x05, | |
3437 | 0x1B, 0x1D, | |
3438 | 0x1C, 0x1F, | |
3439 | 0x1D, 0x0F, | |
3440 | 0x1E, 0x3F, | |
3441 | 0x1F, 0x0F, | |
3442 | 0x20, 0x3F, | |
3443 | 0x22, 0x21, | |
3444 | 0x23, 0x3F, | |
3445 | 0x24, 0x20, | |
3446 | 0x25, 0x3F, | |
3447 | 0x27, 0xEE, | |
3448 | 0x2C, 0x27, /* bit at 0x20 is cleared below */ | |
3449 | 0x30, 0x03, | |
3450 | 0x2C, 0x07, /* bit at 0x20 is cleared here */ | |
3451 | 0x2D, 0x87, | |
3452 | 0x2E, 0xAA, | |
3453 | 0x28, 0xE1, /* Set the FIFCrst bit here */ | |
3454 | 0x28, 0xE0, /* Clear the FIFCrst bit here */ | |
3455 | 0x00 | |
3456 | }; | |
3457 | ||
3458 | /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */ | |
3459 | static const u8 MT2063B1_defaults[] = { | |
3460 | /* Reg, Value */ | |
3461 | 0x05, 0xF0, | |
3462 | 0x11, 0x10, /* New Enable AFCsd */ | |
3463 | 0x19, 0x05, | |
3464 | 0x1A, 0x6C, | |
3465 | 0x1B, 0x24, | |
3466 | 0x1C, 0x28, | |
3467 | 0x1D, 0x8F, | |
3468 | 0x1E, 0x14, | |
3469 | 0x1F, 0x8F, | |
3470 | 0x20, 0x57, | |
3471 | 0x22, 0x21, /* New - ver 1.03 */ | |
3472 | 0x23, 0x3C, /* New - ver 1.10 */ | |
3473 | 0x24, 0x20, /* New - ver 1.03 */ | |
3474 | 0x2C, 0x24, /* bit at 0x20 is cleared below */ | |
3475 | 0x2D, 0x87, /* FIFFQ=0 */ | |
3476 | 0x2F, 0xF3, | |
3477 | 0x30, 0x0C, /* New - ver 1.11 */ | |
3478 | 0x31, 0x1B, /* New - ver 1.11 */ | |
3479 | 0x2C, 0x04, /* bit at 0x20 is cleared here */ | |
3480 | 0x28, 0xE1, /* Set the FIFCrst bit here */ | |
3481 | 0x28, 0xE0, /* Clear the FIFCrst bit here */ | |
3482 | 0x00 | |
3483 | }; | |
3484 | ||
3485 | /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */ | |
3486 | static const u8 MT2063B3_defaults[] = { | |
3487 | /* Reg, Value */ | |
3488 | 0x05, 0xF0, | |
3489 | 0x19, 0x3D, | |
3490 | 0x2C, 0x24, /* bit at 0x20 is cleared below */ | |
3491 | 0x2C, 0x04, /* bit at 0x20 is cleared here */ | |
3492 | 0x28, 0xE1, /* Set the FIFCrst bit here */ | |
3493 | 0x28, 0xE0, /* Clear the FIFCrst bit here */ | |
3494 | 0x00 | |
3495 | }; | |
3496 | ||
0e301442 MCC |
3497 | static int mt2063_init(struct dvb_frontend *fe) |
3498 | { | |
01e0dafc | 3499 | u32 status; |
0e301442 | 3500 | struct mt2063_state *state = fe->tuner_priv; |
01e0dafc MCC |
3501 | u8 all_resets = 0xF0; /* reset/load bits */ |
3502 | const u8 *def = NULL; | |
3503 | u32 FCRUN; | |
3504 | s32 maxReads; | |
3505 | u32 fcu_osc; | |
3506 | u32 i; | |
3507 | ||
3508 | state->rcvr_mode = MT2063_CABLE_QAM; | |
3509 | ||
3510 | /* Read the Part/Rev code from the tuner */ | |
3511 | status = mt2063_read(state, MT2063_REG_PART_REV, state->reg, 1); | |
3512 | if (status < 0) | |
3513 | return status; | |
3514 | ||
3515 | /* Check the part/rev code */ | |
3516 | if (((state->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */ | |
3517 | &&(state->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */ | |
3518 | &&(state->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */ | |
3519 | return -ENODEV; /* Wrong tuner Part/Rev code */ | |
0e301442 | 3520 | |
01e0dafc MCC |
3521 | /* Check the 2nd byte of the Part/Rev code from the tuner */ |
3522 | status = mt2063_read(state, MT2063_REG_RSVD_3B, | |
3523 | &state->reg[MT2063_REG_RSVD_3B], 1); | |
0e301442 | 3524 | |
01e0dafc MCC |
3525 | /* b7 != 0 ==> NOT MT2063 */ |
3526 | if (status < 0 ||((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) | |
3527 | return -ENODEV; /* Wrong tuner Part/Rev code */ | |
3528 | ||
3529 | /* Reset the tuner */ | |
3530 | status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1); | |
3531 | if (status < 0) | |
3532 | return status; | |
3533 | ||
3534 | /* change all of the default values that vary from the HW reset values */ | |
3535 | /* def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */ | |
3536 | switch (state->reg[MT2063_REG_PART_REV]) { | |
3537 | case MT2063_B3: | |
3538 | def = MT2063B3_defaults; | |
3539 | break; | |
3540 | ||
3541 | case MT2063_B1: | |
3542 | def = MT2063B1_defaults; | |
3543 | break; | |
3544 | ||
3545 | case MT2063_B0: | |
3546 | def = MT2063B0_defaults; | |
3547 | break; | |
3548 | ||
3549 | default: | |
3550 | return -ENODEV; | |
3551 | break; | |
0e301442 MCC |
3552 | } |
3553 | ||
01e0dafc MCC |
3554 | while (status >= 0 && *def) { |
3555 | u8 reg = *def++; | |
3556 | u8 val = *def++; | |
3557 | status = mt2063_write(state, reg, &val, 1); | |
3558 | } | |
3559 | if (status < 0) | |
3560 | return status; | |
3561 | ||
3562 | /* Wait for FIFF location to complete. */ | |
3563 | FCRUN = 1; | |
3564 | maxReads = 10; | |
3565 | while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) { | |
3566 | msleep(2); | |
3567 | status = mt2063_read(state, | |
3568 | MT2063_REG_XO_STATUS, | |
3569 | &state-> | |
3570 | reg[MT2063_REG_XO_STATUS], 1); | |
3571 | FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6; | |
3572 | } | |
3573 | ||
3574 | if (FCRUN != 0 || status < 0) | |
3575 | return -ENODEV; | |
3576 | ||
3577 | status = mt2063_read(state, | |
3578 | MT2063_REG_FIFFC, | |
3579 | &state->reg[MT2063_REG_FIFFC], 1); | |
3580 | if (status < 0) | |
3581 | return status; | |
3582 | ||
3583 | /* Read back all the registers from the tuner */ | |
3584 | status = mt2063_read(state, | |
3585 | MT2063_REG_PART_REV, | |
3586 | state->reg, MT2063_REG_END_REGS); | |
3587 | if (status < 0) | |
3588 | return status; | |
3589 | ||
3590 | /* Initialize the tuner state. */ | |
3591 | state->tuner_id = state->reg[MT2063_REG_PART_REV]; | |
3592 | state->AS_Data.f_ref = MT2063_REF_FREQ; | |
3593 | state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) * | |
3594 | ((u32) state->reg[MT2063_REG_FIFFC] + 640); | |
3595 | state->AS_Data.f_if1_bw = MT2063_IF1_BW; | |
3596 | state->AS_Data.f_out = 43750000UL; | |
3597 | state->AS_Data.f_out_bw = 6750000UL; | |
3598 | state->AS_Data.f_zif_bw = MT2063_ZIF_BW; | |
3599 | state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64; | |
3600 | state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE; | |
3601 | state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1; | |
3602 | state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2; | |
3603 | state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP; | |
3604 | state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center; | |
3605 | state->AS_Data.f_LO1 = 2181000000UL; | |
3606 | state->AS_Data.f_LO2 = 1486249786UL; | |
3607 | state->f_IF1_actual = state->AS_Data.f_if1_Center; | |
3608 | state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual; | |
3609 | state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID; | |
3610 | state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID; | |
3611 | state->num_regs = MT2063_REG_END_REGS; | |
3612 | state->AS_Data.avoidDECT = MT2063_AVOID_BOTH; | |
3613 | state->ctfilt_sw = 0; | |
3614 | ||
3615 | state->CTFiltMax[0] = 69230000; | |
3616 | state->CTFiltMax[1] = 105770000; | |
3617 | state->CTFiltMax[2] = 140350000; | |
3618 | state->CTFiltMax[3] = 177110000; | |
3619 | state->CTFiltMax[4] = 212860000; | |
3620 | state->CTFiltMax[5] = 241130000; | |
3621 | state->CTFiltMax[6] = 274370000; | |
3622 | state->CTFiltMax[7] = 309820000; | |
3623 | state->CTFiltMax[8] = 342450000; | |
3624 | state->CTFiltMax[9] = 378870000; | |
3625 | state->CTFiltMax[10] = 416210000; | |
3626 | state->CTFiltMax[11] = 456500000; | |
3627 | state->CTFiltMax[12] = 495790000; | |
3628 | state->CTFiltMax[13] = 534530000; | |
3629 | state->CTFiltMax[14] = 572610000; | |
3630 | state->CTFiltMax[15] = 598970000; | |
3631 | state->CTFiltMax[16] = 635910000; | |
3632 | state->CTFiltMax[17] = 672130000; | |
3633 | state->CTFiltMax[18] = 714840000; | |
3634 | state->CTFiltMax[19] = 739660000; | |
3635 | state->CTFiltMax[20] = 770410000; | |
3636 | state->CTFiltMax[21] = 814660000; | |
3637 | state->CTFiltMax[22] = 846950000; | |
3638 | state->CTFiltMax[23] = 867820000; | |
3639 | state->CTFiltMax[24] = 915980000; | |
3640 | state->CTFiltMax[25] = 947450000; | |
3641 | state->CTFiltMax[26] = 983110000; | |
3642 | state->CTFiltMax[27] = 1021630000; | |
3643 | state->CTFiltMax[28] = 1061870000; | |
3644 | state->CTFiltMax[29] = 1098330000; | |
3645 | state->CTFiltMax[30] = 1138990000; | |
3646 | ||
3647 | /* | |
3648 | ** Fetch the FCU osc value and use it and the fRef value to | |
3649 | ** scale all of the Band Max values | |
3650 | */ | |
3651 | ||
3652 | state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A; | |
3653 | status = mt2063_write(state, MT2063_REG_CTUNE_CTRL, | |
3654 | &state->reg[MT2063_REG_CTUNE_CTRL], 1); | |
3655 | if (status < 0) | |
3656 | return status; | |
3657 | ||
3658 | /* Read the ClearTune filter calibration value */ | |
3659 | status = mt2063_read(state, MT2063_REG_FIFFC, | |
3660 | &state->reg[MT2063_REG_FIFFC], 1); | |
3661 | if (status < 0) | |
3662 | return status; | |
3663 | ||
3664 | fcu_osc = state->reg[MT2063_REG_FIFFC]; | |
3665 | ||
3666 | state->reg[MT2063_REG_CTUNE_CTRL] = 0x00; | |
3667 | status = mt2063_write(state, MT2063_REG_CTUNE_CTRL, | |
3668 | &state->reg[MT2063_REG_CTUNE_CTRL], 1); | |
3669 | if (status < 0) | |
3670 | return status; | |
3671 | ||
3672 | /* Adjust each of the values in the ClearTune filter cross-over table */ | |
3673 | for (i = 0; i < 31; i++) | |
3674 | state->CTFiltMax[i] =(state->CTFiltMax[i] / 768) * (fcu_osc + 640); | |
3675 | ||
3676 | status = MT2063_SoftwareShutdown(state, 1); | |
3677 | if (status < 0) | |
3678 | return status; | |
3679 | status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD); | |
3680 | if (status < 0) | |
3681 | return status; | |
3682 | ||
0e301442 MCC |
3683 | return 0; |
3684 | } | |
3685 | ||
0e301442 | 3686 | static int mt2063_get_status(struct dvb_frontend *fe, u32 * status) |
223c7b05 | 3687 | { |
0e301442 MCC |
3688 | int rc = 0; |
3689 | ||
3690 | //get tuner lock status | |
3691 | ||
3692 | return rc; | |
223c7b05 | 3693 | } |
0e301442 MCC |
3694 | |
3695 | static int mt2063_get_state(struct dvb_frontend *fe, | |
51f0f7b3 | 3696 | enum tuner_param param, struct tuner_state *tunstate) |
0e301442 | 3697 | { |
51f0f7b3 | 3698 | struct mt2063_state *state = fe->tuner_priv; |
0e301442 | 3699 | |
223c7b05 MCC |
3700 | switch (param) { |
3701 | case DVBFE_TUNER_FREQUENCY: | |
0e301442 | 3702 | //get frequency |
223c7b05 MCC |
3703 | break; |
3704 | case DVBFE_TUNER_TUNERSTEP: | |
3705 | break; | |
3706 | case DVBFE_TUNER_IFFREQ: | |
3707 | break; | |
3708 | case DVBFE_TUNER_BANDWIDTH: | |
0e301442 | 3709 | //get bandwidth |
223c7b05 | 3710 | break; |
0e301442 | 3711 | case DVBFE_TUNER_REFCLOCK: |
51f0f7b3 | 3712 | tunstate->refclock = (u32) MT2063_GetLocked(state); |
223c7b05 MCC |
3713 | break; |
3714 | default: | |
3715 | break; | |
3716 | } | |
3717 | ||
51f0f7b3 | 3718 | return (int)tunstate->refclock; |
0e301442 MCC |
3719 | } |
3720 | ||
3721 | static int mt2063_set_state(struct dvb_frontend *fe, | |
51f0f7b3 | 3722 | enum tuner_param param, struct tuner_state *tunstate) |
223c7b05 | 3723 | { |
51f0f7b3 | 3724 | struct mt2063_state *state = fe->tuner_priv; |
fdf77a4f | 3725 | u32 status = 0; |
0e301442 | 3726 | |
223c7b05 MCC |
3727 | switch (param) { |
3728 | case DVBFE_TUNER_FREQUENCY: | |
0e301442 MCC |
3729 | //set frequency |
3730 | ||
3731 | status = | |
51f0f7b3 MCC |
3732 | MT_Tune_atv(state, |
3733 | tunstate->frequency, tunstate->bandwidth, | |
3734 | state->tv_type); | |
0e301442 | 3735 | |
51f0f7b3 | 3736 | state->frequency = tunstate->frequency; |
223c7b05 MCC |
3737 | break; |
3738 | case DVBFE_TUNER_TUNERSTEP: | |
3739 | break; | |
3740 | case DVBFE_TUNER_IFFREQ: | |
3741 | break; | |
3742 | case DVBFE_TUNER_BANDWIDTH: | |
0e301442 | 3743 | //set bandwidth |
51f0f7b3 | 3744 | state->bandwidth = tunstate->bandwidth; |
0e301442 MCC |
3745 | break; |
3746 | case DVBFE_TUNER_REFCLOCK: | |
3747 | ||
0e301442 | 3748 | break; |
223c7b05 MCC |
3749 | default: |
3750 | break; | |
3751 | } | |
3752 | ||
0e301442 MCC |
3753 | return (int)status; |
3754 | } | |
3755 | ||
3756 | static int mt2063_release(struct dvb_frontend *fe) | |
223c7b05 | 3757 | { |
0e301442 | 3758 | struct mt2063_state *state = fe->tuner_priv; |
223c7b05 MCC |
3759 | |
3760 | fe->tuner_priv = NULL; | |
3761 | kfree(state); | |
3762 | ||
3763 | return 0; | |
0e301442 MCC |
3764 | } |
3765 | ||
3766 | static struct dvb_tuner_ops mt2063_ops = { | |
223c7b05 | 3767 | .info = { |
0e301442 MCC |
3768 | .name = "MT2063 Silicon Tuner", |
3769 | .frequency_min = 45000000, | |
3770 | .frequency_max = 850000000, | |
3771 | .frequency_step = 0, | |
3772 | }, | |
3773 | ||
3774 | .init = mt2063_init, | |
bf97555e | 3775 | .sleep = MT2063_Sleep, |
0e301442 MCC |
3776 | .get_status = mt2063_get_status, |
3777 | .get_state = mt2063_get_state, | |
3778 | .set_state = mt2063_set_state, | |
3779 | .release = mt2063_release | |
223c7b05 MCC |
3780 | }; |
3781 | ||
0e301442 MCC |
3782 | struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, |
3783 | struct mt2063_config *config, | |
3784 | struct i2c_adapter *i2c) | |
223c7b05 | 3785 | { |
0e301442 | 3786 | struct mt2063_state *state = NULL; |
223c7b05 | 3787 | |
0e301442 | 3788 | state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL); |
223c7b05 MCC |
3789 | if (state == NULL) |
3790 | goto error; | |
3791 | ||
0e301442 MCC |
3792 | state->config = config; |
3793 | state->i2c = i2c; | |
3794 | state->frontend = fe; | |
3795 | state->reference = config->refclock / 1000; /* kHz */ | |
0e301442 MCC |
3796 | fe->tuner_priv = state; |
3797 | fe->ops.tuner_ops = mt2063_ops; | |
223c7b05 | 3798 | |
0e301442 | 3799 | printk("%s: Attaching MT2063 \n", __func__); |
223c7b05 MCC |
3800 | return fe; |
3801 | ||
3802 | error: | |
3803 | kfree(state); | |
3804 | return NULL; | |
3805 | } | |
3806 | ||
0e301442 | 3807 | EXPORT_SYMBOL(mt2063_attach); |
223c7b05 MCC |
3808 | MODULE_PARM_DESC(verbose, "Set Verbosity level"); |
3809 | ||
0e301442 MCC |
3810 | MODULE_AUTHOR("Henry"); |
3811 | MODULE_DESCRIPTION("MT2063 Silicon tuner"); | |
3812 | MODULE_LICENSE("GPL"); |