blob: 66633fa99e82bab9754b9f0248855b77c6d294f1 [file] [log] [blame]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03002#include <linux/init.h>
3#include <linux/kernel.h>
4#include <linux/module.h>
5#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03007#include "mt2063.h"
8
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03009static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -030010module_param(verbose, int, 0644);
11
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030012/* Internal structures and types */
13
Mauro Carvalho Chehab065719a2011-07-20 22:45:06 -030014/* FIXME: we probably don't need these new FE get/set property types for tuner */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030015#define DVBFE_TUNER_OPEN 99
16#define DVBFE_TUNER_SOFTWARE_SHUTDOWN 100
17#define DVBFE_TUNER_CLEAR_POWER_MASKBITS 101
18
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030019/* FIXME: Those two error codes need conversion*/
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030020/* Error: Upconverter PLL is not locked */
21#define MT2063_UPC_UNLOCK (0x80000002)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030022/* Error: Downconverter PLL is not locked */
23#define MT2063_DNC_UNLOCK (0x80000004)
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030024
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -030025/* Info: Unavoidable LO-related spur may be present in the output */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030026#define MT2063_SPUR_PRESENT_ERR (0x00800000)
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030027
28/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */
29#define MT2063_SPUR_CNT_MASK (0x001f0000)
30#define MT2063_SPUR_SHIFT (16)
31
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030032/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
33#define MT2063_UPC_RANGE (0x04000000)
34
35/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
36#define MT2063_DNC_RANGE (0x08000000)
37
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030038#define MAX_UDATA (4294967295) /* max value storable in u32 */
39
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030040#define MT2063_TUNER_CNT (1) /* total num of MicroTuner tuners */
41#define MT2063_I2C (0xC0)
42
43/*
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -030044 * Data Types
45 */
46
47/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030048 * Constant defining the version of the following structure
49 * and therefore the API for this code.
50 *
51 * When compiling the tuner driver, the preprocessor will
52 * check against this version number to make sure that
53 * it matches the version that the tuner driver knows about.
54 */
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030055
56/* DECT Frequency Avoidance */
57#define MT2063_DECT_AVOID_US_FREQS 0x00000001
58
59#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002
60
61#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
62
63#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
64
65enum MT2063_DECT_Avoid_Type {
66 MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */
67 MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */
68 MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */
69 MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */
70};
71
72#define MT2063_MAX_ZONES 48
73
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -030074struct MT2063_ExclZone_t {
75 u32 min_;
76 u32 max_;
77 struct MT2063_ExclZone_t *next_;
78};
79
80/*
81 * Structure of data needed for Spur Avoidance
82 */
83struct MT2063_AvoidSpursData_t {
84 u32 nAS_Algorithm;
85 u32 f_ref;
86 u32 f_in;
87 u32 f_LO1;
88 u32 f_if1_Center;
89 u32 f_if1_Request;
90 u32 f_if1_bw;
91 u32 f_LO2;
92 u32 f_out;
93 u32 f_out_bw;
94 u32 f_LO1_Step;
95 u32 f_LO2_Step;
96 u32 f_LO1_FracN_Avoid;
97 u32 f_LO2_FracN_Avoid;
98 u32 f_zif_bw;
99 u32 f_min_LO_Separation;
100 u32 maxH1;
101 u32 maxH2;
102 enum MT2063_DECT_Avoid_Type avoidDECT;
103 u32 bSpurPresent;
104 u32 bSpurAvoided;
105 u32 nSpursFound;
106 u32 nZones;
107 struct MT2063_ExclZone_t *freeZones;
108 struct MT2063_ExclZone_t *usedZones;
109 struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
110};
111
112/*
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300113 * Parameter for function MT2063_SetPowerMask that specifies the power down
114 * of various sections of the MT2063.
115 */
116enum MT2063_Mask_Bits {
117 MT2063_REG_SD = 0x0040, /* Shutdown regulator */
118 MT2063_SRO_SD = 0x0020, /* Shutdown SRO */
119 MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */
120 MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */
121 MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */
122 MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */
123 MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */
124 MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */
125 MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */
126 MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */
127 MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */
128 MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */
129 MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */
130 MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */
131 MT2063_NONE_SD = 0x0000 /* No shutdown bits */
132};
133
134/*
135 * Parameter for function MT2063_GetParam & MT2063_SetParam that
136 * specifies the tuning algorithm parameter to be read/written.
137 */
138enum MT2063_Param {
139 /* tuner address set by MT2063_Open() */
140 MT2063_IC_ADDR,
141
142 /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */
143 MT2063_MAX_OPEN,
144
145 /* current number of open MT2063 tuners set by MT2063_Open() */
146 MT2063_NUM_OPEN,
147
148 /* crystal frequency (default: 16000000 Hz) */
149 MT2063_SRO_FREQ,
150
151 /* min tuning step size (default: 50000 Hz) */
152 MT2063_STEPSIZE,
153
154 /* input center frequency set by MT2063_Tune() */
155 MT2063_INPUT_FREQ,
156
157 /* LO1 Frequency set by MT2063_Tune() */
158 MT2063_LO1_FREQ,
159
160 /* LO1 minimum step size (default: 250000 Hz) */
161 MT2063_LO1_STEPSIZE,
162
163 /* LO1 FracN keep-out region (default: 999999 Hz) */
164 MT2063_LO1_FRACN_AVOID_PARAM,
165
166 /* Current 1st IF in use set by MT2063_Tune() */
167 MT2063_IF1_ACTUAL,
168
169 /* Requested 1st IF set by MT2063_Tune() */
170 MT2063_IF1_REQUEST,
171
172 /* Center of 1st IF SAW filter (default: 1218000000 Hz) */
173 MT2063_IF1_CENTER,
174
175 /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */
176 MT2063_IF1_BW,
177
178 /* zero-IF bandwidth (default: 2000000 Hz) */
179 MT2063_ZIF_BW,
180
181 /* LO2 Frequency set by MT2063_Tune() */
182 MT2063_LO2_FREQ,
183
184 /* LO2 minimum step size (default: 50000 Hz) */
185 MT2063_LO2_STEPSIZE,
186
187 /* LO2 FracN keep-out region (default: 374999 Hz) */
188 MT2063_LO2_FRACN_AVOID,
189
190 /* output center frequency set by MT2063_Tune() */
191 MT2063_OUTPUT_FREQ,
192
193 /* output bandwidth set by MT2063_Tune() */
194 MT2063_OUTPUT_BW,
195
196 /* min inter-tuner LO separation (default: 1000000 Hz) */
197 MT2063_LO_SEPARATION,
198
199 /* ID of avoid-spurs algorithm in use compile-time constant */
200 MT2063_AS_ALG,
201
202 /* max # of intra-tuner harmonics (default: 15) */
203 MT2063_MAX_HARM1,
204
205 /* max # of inter-tuner harmonics (default: 7) */
206 MT2063_MAX_HARM2,
207
208 /* # of 1st IF exclusion zones used set by MT2063_Tune() */
209 MT2063_EXCL_ZONES,
210
211 /* # of spurs found/avoided set by MT2063_Tune() */
212 MT2063_NUM_SPURS,
213
214 /* >0 spurs avoided set by MT2063_Tune() */
215 MT2063_SPUR_AVOIDED,
216
217 /* >0 spurs in output (mathematically) set by MT2063_Tune() */
218 MT2063_SPUR_PRESENT,
219
220 /* Receiver Mode for some parameters. 1 is DVB-T */
221 MT2063_RCVR_MODE,
222
223 /* directly set LNA attenuation, parameter is value to set */
224 MT2063_ACLNA,
225
226 /* maximum LNA attenuation, parameter is value to set */
227 MT2063_ACLNA_MAX,
228
229 /* directly set ATN attenuation. Paremeter is value to set. */
230 MT2063_ACRF,
231
232 /* maxium ATN attenuation. Paremeter is value to set. */
233 MT2063_ACRF_MAX,
234
235 /* directly set FIF attenuation. Paremeter is value to set. */
236 MT2063_ACFIF,
237
238 /* maxium FIF attenuation. Paremeter is value to set. */
239 MT2063_ACFIF_MAX,
240
241 /* LNA Rin */
242 MT2063_LNA_RIN,
243
244 /* Power Detector LNA level target */
245 MT2063_LNA_TGT,
246
247 /* Power Detector 1 level */
248 MT2063_PD1,
249
250 /* Power Detector 1 level target */
251 MT2063_PD1_TGT,
252
253 /* Power Detector 2 level */
254 MT2063_PD2,
255
256 /* Power Detector 2 level target */
257 MT2063_PD2_TGT,
258
259 /* Selects, which DNC is activ */
260 MT2063_DNC_OUTPUT_ENABLE,
261
262 /* VGA gain code */
263 MT2063_VGAGC,
264
265 /* VGA bias current */
266 MT2063_VGAOI,
267
268 /* TAGC, determins the speed of the AGC */
269 MT2063_TAGC,
270
271 /* AMP gain code */
272 MT2063_AMPGC,
273
274 /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */
275 MT2063_AVOID_DECT,
276
277 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
278 MT2063_CTFILT_SW,
279
280 MT2063_EOP /* last entry in enumerated list */
281};
282
283/*
284 * Parameter for selecting tuner mode
285 */
286enum MT2063_RCVR_MODES {
287 MT2063_CABLE_QAM = 0, /* Digital cable */
288 MT2063_CABLE_ANALOG, /* Analog cable */
289 MT2063_OFFAIR_COFDM, /* Digital offair */
290 MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */
291 MT2063_OFFAIR_ANALOG, /* Analog offair */
292 MT2063_OFFAIR_8VSB, /* Analog offair */
293 MT2063_NUM_RCVR_MODES
294};
295
296/*
297 * Possible values for MT2063_DNC_OUTPUT
298 */
299enum MT2063_DNC_Output_Enable {
300 MT2063_DNC_NONE = 0,
301 MT2063_DNC_1,
302 MT2063_DNC_2,
303 MT2063_DNC_BOTH
304};
305
306/*
307** Two-wire serial bus subaddresses of the tuner registers.
308** Also known as the tuner's register addresses.
309*/
310enum MT2063_Register_Offsets {
311 MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */
312 MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */
313 MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */
314 MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */
315 MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */
316 MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */
317 MT2063_REG_RSVD_06, /* 0x06: Reserved */
318 MT2063_REG_LO_STATUS, /* 0x07: LO Status */
319 MT2063_REG_FIFFC, /* 0x08: FIFF Center */
320 MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */
321 MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */
322 MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */
323 MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */
324 MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */
325 MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */
326 MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */
327 MT2063_REG_RSVD_10, /* 0x10: Reserved */
328 MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */
329 MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */
330 MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */
331 MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */
332 MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */
333 MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */
334 MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */
335 MT2063_REG_RF_OV, /* 0x18: RF Attn Override */
336 MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */
337 MT2063_REG_LNA_TGT, /* 0x1A: Reserved */
338 MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */
339 MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */
340 MT2063_REG_RSVD_1D, /* 0x1D: Reserved */
341 MT2063_REG_RSVD_1E, /* 0x1E: Reserved */
342 MT2063_REG_RSVD_1F, /* 0x1F: Reserved */
343 MT2063_REG_RSVD_20, /* 0x20: Reserved */
344 MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */
345 MT2063_REG_RSVD_22, /* 0x22: Reserved */
346 MT2063_REG_RSVD_23, /* 0x23: Reserved */
347 MT2063_REG_RSVD_24, /* 0x24: Reserved */
348 MT2063_REG_RSVD_25, /* 0x25: Reserved */
349 MT2063_REG_RSVD_26, /* 0x26: Reserved */
350 MT2063_REG_RSVD_27, /* 0x27: Reserved */
351 MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */
352 MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */
353 MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */
354 MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */
355 MT2063_REG_CTRL_2C, /* 0x2C: Reserved */
356 MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */
357 MT2063_REG_RSVD_2E, /* 0x2E: Reserved */
358 MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */
359 MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */
360 MT2063_REG_RSVD_31, /* 0x31: Reserved */
361 MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */
362 MT2063_REG_RSVD_33, /* 0x33: Reserved */
363 MT2063_REG_RSVD_34, /* 0x34: Reserved */
364 MT2063_REG_RSVD_35, /* 0x35: Reserved */
365 MT2063_REG_RSVD_36, /* 0x36: Reserved */
366 MT2063_REG_RSVD_37, /* 0x37: Reserved */
367 MT2063_REG_RSVD_38, /* 0x38: Reserved */
368 MT2063_REG_RSVD_39, /* 0x39: Reserved */
369 MT2063_REG_RSVD_3A, /* 0x3A: Reserved */
370 MT2063_REG_RSVD_3B, /* 0x3B: Reserved */
371 MT2063_REG_RSVD_3C, /* 0x3C: Reserved */
372 MT2063_REG_END_REGS
373};
374
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300375enum MTTune_atv_standard {
376 MTTUNEA_UNKNOWN = 0,
377 MTTUNEA_PAL_B,
378 MTTUNEA_PAL_G,
379 MTTUNEA_PAL_I,
380 MTTUNEA_PAL_L,
381 MTTUNEA_PAL_MN,
382 MTTUNEA_PAL_DK,
383 MTTUNEA_DIGITAL,
384 MTTUNEA_FMRADIO,
385 MTTUNEA_DVBC,
386 MTTUNEA_DVBT
387};
388
389
390struct mt2063_state {
391 struct i2c_adapter *i2c;
392
393 const struct mt2063_config *config;
394 struct dvb_tuner_ops ops;
395 struct dvb_frontend *frontend;
396 struct tuner_state status;
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300397 bool MT2063_init;
398
399 enum MTTune_atv_standard tv_type;
400 u32 frequency;
401 u32 srate;
402 u32 bandwidth;
403 u32 reference;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300404
405 u32 tuner_id;
406 struct MT2063_AvoidSpursData_t AS_Data;
407 u32 f_IF1_actual;
408 u32 rcvr_mode;
409 u32 ctfilt_sw;
410 u32 CTFiltMax[31];
411 u32 num_regs;
412 u8 reg[MT2063_REG_END_REGS];
Mauro Carvalho Chehab6d3d7482011-07-20 22:21:26 -0300413};
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300414
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300415/* Prototypes */
416static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
417 u32 f_min, u32 f_max);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300418static u32 MT2063_ReInit(struct mt2063_state *pInfo);
419static u32 MT2063_Close(struct mt2063_state *pInfo);
420static u32 MT2063_GetReg(struct mt2063_state *pInfo, u8 reg, u8 * val);
421static u32 MT2063_GetParam(struct mt2063_state *pInfo, enum MT2063_Param param, u32 * pValue);
422static u32 MT2063_SetReg(struct mt2063_state *pInfo, u8 reg, u8 val);
423static u32 MT2063_SetParam(struct mt2063_state *pInfo, enum MT2063_Param param,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -0300424 enum MT2063_DNC_Output_Enable nValue);
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300425
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300426/*****************/
427/* From drivers/media/common/tuners/mt2063_cfg.h */
428
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300429unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300430 u32 bw_in,
431 enum MTTune_atv_standard tv_type)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300432{
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300433 struct dvb_frontend_ops *frontend_ops = NULL;
434 struct dvb_tuner_ops *tuner_ops = NULL;
435 struct tuner_state t_state;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300436 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300437 int err = 0;
438
439 t_state.frequency = f_in;
440 t_state.bandwidth = bw_in;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300441 state->tv_type = tv_type;
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300442 if (&fe->ops)
443 frontend_ops = &fe->ops;
444 if (&frontend_ops->tuner_ops)
445 tuner_ops = &frontend_ops->tuner_ops;
446 if (tuner_ops->set_state) {
447 if ((err =
448 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
449 &t_state)) < 0) {
450 printk("%s: Invalid parameter\n", __func__);
451 return err;
452 }
453 }
454
455 return err;
456}
457
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300458unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300459{
460 struct dvb_frontend_ops *frontend_ops = &fe->ops;
461 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
462 struct tuner_state t_state;
463 int err = 0;
464
465 if (&fe->ops)
466 frontend_ops = &fe->ops;
467 if (&frontend_ops->tuner_ops)
468 tuner_ops = &frontend_ops->tuner_ops;
469 if (tuner_ops->get_state) {
470 if ((err =
471 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
472 &t_state)) < 0) {
473 printk("%s: Invalid parameter\n", __func__);
474 return err;
475 }
476 }
477 return err;
478}
479
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300480unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300481{
482 struct dvb_frontend_ops *frontend_ops = &fe->ops;
483 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
484 struct tuner_state t_state;
485 int err = 0;
486
487 if (&fe->ops)
488 frontend_ops = &fe->ops;
489 if (&frontend_ops->tuner_ops)
490 tuner_ops = &frontend_ops->tuner_ops;
491 if (tuner_ops->set_state) {
492 if ((err =
493 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
494 &t_state)) < 0) {
495 printk("%s: Invalid parameter\n", __func__);
496 return err;
497 }
498 }
499
500 return err;
501}
502
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300503unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300504{
505 struct dvb_frontend_ops *frontend_ops = &fe->ops;
506 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
507 struct tuner_state t_state;
508 int err = 0;
509
510 if (&fe->ops)
511 frontend_ops = &fe->ops;
512 if (&frontend_ops->tuner_ops)
513 tuner_ops = &frontend_ops->tuner_ops;
514 if (tuner_ops->set_state) {
515 if ((err =
516 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
517 &t_state)) < 0) {
518 printk("%s: Invalid parameter\n", __func__);
519 return err;
520 }
521 }
522
523 return err;
524}
525
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300526unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -0300527{
528 struct dvb_frontend_ops *frontend_ops = &fe->ops;
529 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
530 struct tuner_state t_state;
531 int err = 0;
532
533 if (&fe->ops)
534 frontend_ops = &fe->ops;
535 if (&frontend_ops->tuner_ops)
536 tuner_ops = &frontend_ops->tuner_ops;
537 if (tuner_ops->set_state) {
538 if ((err =
539 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
540 &t_state)) < 0) {
541 printk("%s: Invalid parameter\n", __func__);
542 return err;
543 }
544 }
545
546 return err;
547}
548
549/*****************/
550
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300551//i2c operation
552static int mt2063_writeregs(struct mt2063_state *state, u8 reg1,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300553 u8 *data, int len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300554{
555 int ret;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300556 u8 buf[60]; /* = { reg1, data }; */
557
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300558 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300559 .addr = state->config->tuner_address,
560 .flags = 0,
561 .buf = buf,
562 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300563 };
564
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300565 msg.buf[0] = reg1;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300566 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300567
568 //printk("mt2063_writeregs state->i2c=%p\n", state->i2c);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300569 ret = i2c_transfer(state->i2c, &msg, 1);
570
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300571 if (ret < 0)
572 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300573
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300574 return ret;
575}
576
577static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 * b, u8 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300578{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300579 int ret;
580 u8 b0[] = { reg1 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300581 struct i2c_msg msg[] = {
582 {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300583 .addr = state->config->tuner_address,
584 .flags = I2C_M_RD,
585 .buf = b0,
586 .len = 1}, {
587 .addr = state->config->tuner_address,
588 .flags = I2C_M_RD,
589 .buf = b,
590 .len = len}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300591 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300592
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300593 //printk("mt2063_read_regs state->i2c=%p\n", state->i2c);
594 ret = i2c_transfer(state->i2c, msg, 2);
595 if (ret < 0)
596 printk("mt2063_readregs error ret=%d\n", ret);
597
598 return ret;
599}
600
601//context of mt2063_userdef.c <Henry> ======================================
602//#################################################################
603//=================================================================
604/*****************************************************************************
605**
606** Name: MT_WriteSub
607**
608** Description: Write values to device using a two-wire serial bus.
609**
610** Parameters: hUserData - User-specific I/O parameter that was
611** passed to tuner's Open function.
612** addr - device serial bus address (value passed
613** as parameter to MTxxxx_Open)
614** subAddress - serial bus sub-address (Register Address)
615** pData - pointer to the Data to be written to the
616** device
617** cnt - number of bytes/registers to be written
618**
619** Returns: status:
620** MT_OK - No errors
621** MT_COMM_ERR - Serial bus communications error
622** user-defined
623**
624** Notes: This is a callback function that is called from the
625** the tuning algorithm. You MUST provide code for this
626** function to write data using the tuner's 2-wire serial
627** bus.
628**
629** The hUserData parameter is a user-specific argument.
630** If additional arguments are needed for the user's
631** serial bus read/write functions, this argument can be
632** used to supply the necessary information.
633** The hUserData parameter is initialized in the tuner's Open
634** function.
635**
636** Revision History:
637**
638** SCR Date Author Description
639** -------------------------------------------------------------------------
640** N/A 03-25-2004 DAD Original
641**
642*****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300643static u32 MT2063_WriteSub(struct mt2063_state *state,
644 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300645{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300646 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300647 struct dvb_frontend *fe = state->frontend;
648
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300649 /*
650 ** ToDo: Add code here to implement a serial-bus write
651 ** operation to the MTxxxx tuner. If successful,
652 ** return MT_OK.
653 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300654
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300655 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300656
657 if (mt2063_writeregs(state, subAddress, pData, cnt) < 0) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300658 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300659 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300660 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300661
662 return (status);
663}
664
665/*****************************************************************************
666**
667** Name: MT_ReadSub
668**
669** Description: Read values from device using a two-wire serial bus.
670**
671** Parameters: hUserData - User-specific I/O parameter that was
672** passed to tuner's Open function.
673** addr - device serial bus address (value passed
674** as parameter to MTxxxx_Open)
675** subAddress - serial bus sub-address (Register Address)
676** pData - pointer to the Data to be written to the
677** device
678** cnt - number of bytes/registers to be written
679**
680** Returns: status:
681** MT_OK - No errors
682** MT_COMM_ERR - Serial bus communications error
683** user-defined
684**
685** Notes: This is a callback function that is called from the
686** the tuning algorithm. You MUST provide code for this
687** function to read data using the tuner's 2-wire serial
688** bus.
689**
690** The hUserData parameter is a user-specific argument.
691** If additional arguments are needed for the user's
692** serial bus read/write functions, this argument can be
693** used to supply the necessary information.
694** The hUserData parameter is initialized in the tuner's Open
695** function.
696**
697** Revision History:
698**
699** SCR Date Author Description
700** -------------------------------------------------------------------------
701** N/A 03-25-2004 DAD Original
702**
703*****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300704static u32 MT2063_ReadSub(struct mt2063_state *state,
705 u8 subAddress, u8 *pData, u32 cnt)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300706{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -0300707 u32 status = 0; /* Status to be returned */
708 struct dvb_frontend *fe = state->frontend;
709 u32 i = 0;
710
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300711 /*
712 ** ToDo: Add code here to implement a serial-bus read
713 ** operation to the MTxxxx tuner. If successful,
714 ** return MT_OK.
715 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300716 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300717
718 for (i = 0; i < cnt; i++) {
719 if (mt2063_read_regs(state, subAddress + i, pData + i, 1) < 0) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300720 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300721 break;
722 }
723 }
724
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300725 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300726
727 return (status);
728}
729
730/*****************************************************************************
731**
732** Name: MT_Sleep
733**
734** Description: Delay execution for "nMinDelayTime" milliseconds
735**
736** Parameters: hUserData - User-specific I/O parameter that was
737** passed to tuner's Open function.
738** nMinDelayTime - Delay time in milliseconds
739**
740** Returns: None.
741**
742** Notes: This is a callback function that is called from the
743** the tuning algorithm. You MUST provide code that
744** blocks execution for the specified period of time.
745**
746** Revision History:
747**
748** SCR Date Author Description
749** -------------------------------------------------------------------------
750** N/A 03-25-2004 DAD Original
751**
752*****************************************************************************/
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300753static int MT2063_Sleep(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300754{
755 /*
756 ** ToDo: Add code here to implement a OS blocking
757 ** for a period of "nMinDelayTime" milliseconds.
758 */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300759 msleep(10);
760
761 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300762}
763
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300764//end of mt2063_userdef.c
765//=================================================================
766//#################################################################
767//=================================================================
768
769//context of mt2063_spuravoid.c <Henry> ======================================
770//#################################################################
771//=================================================================
772
773/*****************************************************************************
774**
775** Name: mt_spuravoid.c
776**
777** Description: Microtune spur avoidance software module.
778** Supports Microtune tuner drivers.
779**
780** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
781** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
782**
783** Revision History:
784**
785** SCR Date Author Description
786** -------------------------------------------------------------------------
787** 082 03-25-2005 JWS Original multi-tuner support - requires
788** MTxxxx_CNT declarations
789** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
790** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
791** of compiler warnings
792** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
793** avoidance into a single module.
794** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
795** (f_min, f_max) < 0, ignore the entry.
796** 115 03-23-2007 DAD Fix declaration of spur due to truncation
797** errors.
798** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
799** tuner DLL.
800** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
801** multi-tuners that have
802** (delta IF1) > (f_out-f_outbw/2).
803** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
804** Added logic to force f_Center within 1/2 f_Step.
805** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
806** Type casts added to preserve correct sign.
807** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
808** frequencies into MT_ResetExclZones().
809** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
810**
811*****************************************************************************/
812
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300813/* Version of this module */
814#define MT2063_SPUR_VERSION 10201 /* Version 01.21 */
815
816/* Implement ceiling, floor functions. */
817#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
818#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
819#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
820#define ufloor(n, d) ((n)/(d))
821
822struct MT2063_FIFZone_t {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300823 s32 min_;
824 s32 max_;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300825};
826
827#if MT2063_TUNER_CNT > 1
828static struct MT2063_AvoidSpursData_t *TunerList[MT2063_TUNER_CNT];
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300829static u32 TunerCount = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300830#endif
831
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300832static u32 MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300833{
834#if MT2063_TUNER_CNT == 1
835 pAS_Info->nAS_Algorithm = 1;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300836 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300837#else
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300838 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300839
840 pAS_Info->nAS_Algorithm = 2;
841
842 /*
843 ** Check to see if tuner is already registered
844 */
845 for (index = 0; index < TunerCount; index++) {
846 if (TunerList[index] == pAS_Info) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300847 return 0; /* Already here - no problem */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300848 }
849 }
850
851 /*
852 ** Add tuner to list - if there is room.
853 */
854 if (TunerCount < MT2063_TUNER_CNT) {
855 TunerList[TunerCount] = pAS_Info;
856 TunerCount++;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300857 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300858 } else
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -0300859 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300860#endif
861}
862
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300863static void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300864{
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -0300865#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300866 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300867
868 for (index = 0; index < TunerCount; index++) {
869 if (TunerList[index] == pAS_Info) {
870 TunerList[index] = TunerList[--TunerCount];
871 }
872 }
873#endif
874}
875
876/*
877** Reset all exclusion zones.
878** Add zones to protect the PLL FracN regions near zero
879**
880** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
881** frequencies into MT_ResetExclZones().
882*/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -0300883static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300884{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300885 u32 center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300886#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -0300887 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300888 struct MT2063_AvoidSpursData_t *adj;
889#endif
890
891 pAS_Info->nZones = 0; /* this clears the used list */
892 pAS_Info->usedZones = NULL; /* reset ptr */
893 pAS_Info->freeZones = NULL; /* reset ptr */
894
895 center =
896 pAS_Info->f_ref *
897 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
898 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
899 while (center <
900 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
901 pAS_Info->f_LO1_FracN_Avoid) {
902 /* Exclude LO1 FracN */
903 MT2063_AddExclZone(pAS_Info,
904 center - pAS_Info->f_LO1_FracN_Avoid,
905 center - 1);
906 MT2063_AddExclZone(pAS_Info, center + 1,
907 center + pAS_Info->f_LO1_FracN_Avoid);
908 center += pAS_Info->f_ref;
909 }
910
911 center =
912 pAS_Info->f_ref *
913 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
914 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
915 while (center <
916 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
917 pAS_Info->f_LO2_FracN_Avoid) {
918 /* Exclude LO2 FracN */
919 MT2063_AddExclZone(pAS_Info,
920 center - pAS_Info->f_LO2_FracN_Avoid,
921 center - 1);
922 MT2063_AddExclZone(pAS_Info, center + 1,
923 center + pAS_Info->f_LO2_FracN_Avoid);
924 center += pAS_Info->f_ref;
925 }
926
927 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
928 /* Exclude LO1 values that conflict with DECT channels */
929 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
930 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
931 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
932 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
933 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
934 }
935
936 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
937 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
938 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
939 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
940 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
941 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
942 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
943 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
944 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
945 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
946 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
947 }
948#if MT2063_TUNER_CNT > 1
949 /*
950 ** Iterate through all adjacent tuners and exclude frequencies related to them
951 */
952 for (index = 0; index < TunerCount; ++index) {
953 adj = TunerList[index];
954 if (pAS_Info == adj) /* skip over our own data, don't process it */
955 continue;
956
957 /*
958 ** Add 1st IF exclusion zone covering adjacent tuner's LO2
959 ** at "adjfLO2 + f_out" +/- m_MinLOSpacing
960 */
961 if (adj->f_LO2 != 0)
962 MT2063_AddExclZone(pAS_Info,
963 (adj->f_LO2 + pAS_Info->f_out) -
964 pAS_Info->f_min_LO_Separation,
965 (adj->f_LO2 + pAS_Info->f_out) +
966 pAS_Info->f_min_LO_Separation);
967
968 /*
969 ** Add 1st IF exclusion zone covering adjacent tuner's LO1
970 ** at "adjfLO1 - f_in" +/- m_MinLOSpacing
971 */
972 if (adj->f_LO1 != 0)
973 MT2063_AddExclZone(pAS_Info,
974 (adj->f_LO1 - pAS_Info->f_in) -
975 pAS_Info->f_min_LO_Separation,
976 (adj->f_LO1 - pAS_Info->f_in) +
977 pAS_Info->f_min_LO_Separation);
978 }
979#endif
980}
981
982static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
983 *pAS_Info,
984 struct MT2063_ExclZone_t *pPrevNode)
985{
986 struct MT2063_ExclZone_t *pNode;
987 /* Check for a node in the free list */
988 if (pAS_Info->freeZones != NULL) {
989 /* Use one from the free list */
990 pNode = pAS_Info->freeZones;
991 pAS_Info->freeZones = pNode->next_;
992 } else {
993 /* Grab a node from the array */
994 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
995 }
996
997 if (pPrevNode != NULL) {
998 pNode->next_ = pPrevNode->next_;
999 pPrevNode->next_ = pNode;
1000 } else { /* insert at the beginning of the list */
1001
1002 pNode->next_ = pAS_Info->usedZones;
1003 pAS_Info->usedZones = pNode;
1004 }
1005
1006 pAS_Info->nZones++;
1007 return pNode;
1008}
1009
1010static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
1011 *pAS_Info,
1012 struct MT2063_ExclZone_t *pPrevNode,
1013 struct MT2063_ExclZone_t
1014 *pNodeToRemove)
1015{
1016 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
1017
1018 /* Make previous node point to the subsequent node */
1019 if (pPrevNode != NULL)
1020 pPrevNode->next_ = pNext;
1021
1022 /* Add pNodeToRemove to the beginning of the freeZones */
1023 pNodeToRemove->next_ = pAS_Info->freeZones;
1024 pAS_Info->freeZones = pNodeToRemove;
1025
1026 /* Decrement node count */
1027 pAS_Info->nZones--;
1028
1029 return pNext;
1030}
1031
1032/*****************************************************************************
1033**
1034** Name: MT_AddExclZone
1035**
1036** Description: Add (and merge) an exclusion zone into the list.
1037** If the range (f_min, f_max) is totally outside the
1038** 1st IF BW, ignore the entry.
1039** If the range (f_min, f_max) is negative, ignore the entry.
1040**
1041** Revision History:
1042**
1043** SCR Date Author Description
1044** -------------------------------------------------------------------------
1045** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
1046** (f_min, f_max) < 0, ignore the entry.
1047**
1048*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001049static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001050 u32 f_min, u32 f_max)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001051{
1052 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
1053 struct MT2063_ExclZone_t *pPrev = NULL;
1054 struct MT2063_ExclZone_t *pNext = NULL;
1055
1056 /* Check to see if this overlaps the 1st IF filter */
1057 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
1058 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
1059 && (f_min < f_max)) {
1060 /*
1061 ** 1 2 3 4 5 6
1062 **
1063 ** New entry: |---| |--| |--| |-| |---| |--|
1064 ** or or or or or
1065 ** Existing: |--| |--| |--| |---| |-| |--|
1066 */
1067
1068 /* Check for our place in the list */
1069 while ((pNode != NULL) && (pNode->max_ < f_min)) {
1070 pPrev = pNode;
1071 pNode = pNode->next_;
1072 }
1073
1074 if ((pNode != NULL) && (pNode->min_ < f_max)) {
1075 /* Combine me with pNode */
1076 if (f_min < pNode->min_)
1077 pNode->min_ = f_min;
1078 if (f_max > pNode->max_)
1079 pNode->max_ = f_max;
1080 } else {
1081 pNode = InsertNode(pAS_Info, pPrev);
1082 pNode->min_ = f_min;
1083 pNode->max_ = f_max;
1084 }
1085
1086 /* Look for merging possibilities */
1087 pNext = pNode->next_;
1088 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
1089 if (pNext->max_ > pNode->max_)
1090 pNode->max_ = pNext->max_;
1091 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
1092 }
1093 }
1094}
1095
1096/*****************************************************************************
1097**
1098** Name: MT_ChooseFirstIF
1099**
1100** Description: Choose the best available 1st IF
1101** If f_Desired is not excluded, choose that first.
1102** Otherwise, return the value closest to f_Center that is
1103** not excluded
1104**
1105** Revision History:
1106**
1107** SCR Date Author Description
1108** -------------------------------------------------------------------------
1109** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
1110** tuner DLL.
1111** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
1112** Added logic to force f_Center within 1/2 f_Step.
1113**
1114*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001115static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001116{
1117 /*
1118 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
1119 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
1120 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
1121 ** However, the sum must be.
1122 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001123 const u32 f_Desired =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001124 pAS_Info->f_LO1_Step *
1125 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
1126 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
1127 pAS_Info->f_in;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001128 const u32 f_Step =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001129 (pAS_Info->f_LO1_Step >
1130 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
1131 f_LO2_Step;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001132 u32 f_Center;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001133
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001134 s32 i;
1135 s32 j = 0;
1136 u32 bDesiredExcluded = 0;
1137 u32 bZeroExcluded = 0;
1138 s32 tmpMin, tmpMax;
1139 s32 bestDiff;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001140 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
1141 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
1142
1143 if (pAS_Info->nZones == 0)
1144 return f_Desired;
1145
1146 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
1147 if (pAS_Info->f_if1_Center > f_Desired)
1148 f_Center =
1149 f_Desired +
1150 f_Step *
1151 ((pAS_Info->f_if1_Center - f_Desired +
1152 f_Step / 2) / f_Step);
1153 else
1154 f_Center =
1155 f_Desired -
1156 f_Step *
1157 ((f_Desired - pAS_Info->f_if1_Center +
1158 f_Step / 2) / f_Step);
1159
1160 //assert;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001161 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001162 // return 0;
1163
1164 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
1165 while (pNode != NULL) {
1166 /* floor function */
1167 tmpMin =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001168 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001169
1170 /* ceil function */
1171 tmpMax =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001172 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001173
1174 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
1175 bDesiredExcluded = 1;
1176
1177 if ((tmpMin < 0) && (tmpMax > 0))
1178 bZeroExcluded = 1;
1179
1180 /* See if this zone overlaps the previous */
1181 if ((j > 0) && (tmpMin < zones[j - 1].max_))
1182 zones[j - 1].max_ = tmpMax;
1183 else {
1184 /* Add new zone */
1185 //assert(j<MT2063_MAX_ZONES);
1186 //if (j>=MT2063_MAX_ZONES)
1187 //break;
1188
1189 zones[j].min_ = tmpMin;
1190 zones[j].max_ = tmpMax;
1191 j++;
1192 }
1193 pNode = pNode->next_;
1194 }
1195
1196 /*
1197 ** If the desired is okay, return with it
1198 */
1199 if (bDesiredExcluded == 0)
1200 return f_Desired;
1201
1202 /*
1203 ** If the desired is excluded and the center is okay, return with it
1204 */
1205 if (bZeroExcluded == 0)
1206 return f_Center;
1207
1208 /* Find the value closest to 0 (f_Center) */
1209 bestDiff = zones[0].min_;
1210 for (i = 0; i < j; i++) {
1211 if (abs(zones[i].min_) < abs(bestDiff))
1212 bestDiff = zones[i].min_;
1213 if (abs(zones[i].max_) < abs(bestDiff))
1214 bestDiff = zones[i].max_;
1215 }
1216
1217 if (bestDiff < 0)
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001218 return f_Center - ((u32) (-bestDiff) * f_Step);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001219
1220 return f_Center + (bestDiff * f_Step);
1221}
1222
1223/****************************************************************************
1224**
1225** Name: gcd
1226**
1227** Description: Uses Euclid's algorithm
1228**
1229** Parameters: u, v - unsigned values whose GCD is desired.
1230**
1231** Global: None
1232**
1233** Returns: greatest common divisor of u and v, if either value
1234** is 0, the other value is returned as the result.
1235**
1236** Dependencies: None.
1237**
1238** Revision History:
1239**
1240** SCR Date Author Description
1241** -------------------------------------------------------------------------
1242** N/A 06-01-2004 JWS Original
1243** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
1244** unsigned numbers.
1245**
1246****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001247static u32 MT2063_gcd(u32 u, u32 v)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001248{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001249 u32 r;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001250
1251 while (v != 0) {
1252 r = u % v;
1253 u = v;
1254 v = r;
1255 }
1256
1257 return u;
1258}
1259
1260/****************************************************************************
1261**
1262** Name: umax
1263**
1264** Description: Implements a simple maximum function for unsigned numbers.
1265** Implemented as a function rather than a macro to avoid
1266** multiple evaluation of the calling parameters.
1267**
1268** Parameters: a, b - Values to be compared
1269**
1270** Global: None
1271**
1272** Returns: larger of the input values.
1273**
1274** Dependencies: None.
1275**
1276** Revision History:
1277**
1278** SCR Date Author Description
1279** -------------------------------------------------------------------------
1280** N/A 06-02-2004 JWS Original
1281**
1282****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001283static u32 MT2063_umax(u32 a, u32 b)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001284{
1285 return (a >= b) ? a : b;
1286}
1287
1288#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001289static s32 RoundAwayFromZero(s32 n, s32 d)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001290{
1291 return (n < 0) ? floor(n, d) : ceil(n, d);
1292}
1293
1294/****************************************************************************
1295**
1296** Name: IsSpurInAdjTunerBand
1297**
1298** Description: Checks to see if a spur will be present within the IF's
1299** bandwidth or near the zero IF.
1300** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2)
1301** and
1302** (0 +/- fZIFBW/2)
1303**
1304** ma mb me mf mc md
1305** <--+-+-+-----------------+-+-+-----------------+-+-+-->
1306** | ^ 0 ^ |
1307** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1308** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1309**
1310** Note that some equations are doubled to prevent round-off
1311** problems when calculating fIFBW/2
1312**
1313** The spur frequencies are computed as:
1314**
1315** fSpur = n * f1 - m * f2 - fOffset
1316**
1317** Parameters: f1 - The 1st local oscillator (LO) frequency
1318** of the tuner whose output we are examining
1319** f2 - The 1st local oscillator (LO) frequency
1320** of the adjacent tuner
1321** fOffset - The 2nd local oscillator of the tuner whose
1322** output we are examining
1323** fIFOut - Output IF center frequency
1324** fIFBW - Output IF Bandwidth
1325** nMaxH - max # of LO harmonics to search
1326** fp - If spur, positive distance to spur-free band edge (returned)
1327** fm - If spur, negative distance to spur-free band edge (returned)
1328**
1329** Returns: 1 if an LO spur would be present, otherwise 0.
1330**
1331** Dependencies: None.
1332**
1333** Revision History:
1334**
1335** SCR Date Author Description
1336** -------------------------------------------------------------------------
1337** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion.
1338** 115 03-23-2007 DAD Fix declaration of spur due to truncation
1339** errors.
1340** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
1341** multi-tuners that have
1342** (delta IF1) > (f_out-f_outbw/2).
1343** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
1344** Type casts added to preserve correct sign.
1345**
1346****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001347static u32 IsSpurInAdjTunerBand(u32 bIsMyOutput,
1348 u32 f1,
1349 u32 f2,
1350 u32 fOffset,
1351 u32 fIFOut,
1352 u32 fIFBW,
1353 u32 fZIFBW,
1354 u32 nMaxH, u32 * fp, u32 * fm)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001355{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001356 u32 bSpurFound = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001357
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001358 const u32 fHalf_IFBW = fIFBW / 2;
1359 const u32 fHalf_ZIFBW = fZIFBW / 2;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001360
1361 /* Calculate a scale factor for all frequencies, so that our
1362 calculations all stay within 31 bits */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001363 const u32 f_Scale =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001364 ((f1 +
1365 (fOffset + fIFOut +
1366 fHalf_IFBW) / nMaxH) / (MAX_UDATA / 2 / nMaxH)) + 1;
1367
1368 /*
1369 ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into
1370 ** signed data types (smaller than MAX_UDATA/2)
1371 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001372 const s32 _f1 = (s32) (f1 / f_Scale);
1373 const s32 _f2 = (s32) (f2 / f_Scale);
1374 const s32 _f3 = (s32) (fOffset / f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001375
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001376 const s32 c = (s32) (fIFOut - fHalf_IFBW) / (s32) f_Scale;
1377 const s32 d = (s32) ((fIFOut + fHalf_IFBW) / f_Scale);
1378 const s32 f = (s32) (fHalf_ZIFBW / f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001379
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001380 s32 ma, mb, mc, md, me, mf;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001381
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001382 s32 fp_ = 0;
1383 s32 fm_ = 0;
1384 s32 n;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001385
1386 /*
1387 ** If the other tuner does not have an LO frequency defined,
1388 ** assume that we cannot interfere with it
1389 */
1390 if (f2 == 0)
1391 return 0;
1392
1393 /* Check out all multiples of f1 from -nMaxH to +nMaxH */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001394 for (n = -(s32) nMaxH; n <= (s32) nMaxH; ++n) {
1395 const s32 nf1 = n * _f1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001396 md = (_f3 + d - nf1) / _f2;
1397
1398 /* If # f2 harmonics > nMaxH, then no spurs present */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001399 if (md <= -(s32) nMaxH)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001400 break;
1401
1402 ma = (_f3 - d - nf1) / _f2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001403 if ((ma == md) || (ma >= (s32) (nMaxH)))
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001404 continue;
1405
1406 mc = (_f3 + c - nf1) / _f2;
1407 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001408 const s32 m = (n < 0) ? md : mc;
1409 const s32 fspur = (nf1 + m * _f2 - _f3);
1410 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001411 if (den == 0) {
1412 fp_ = (d - fspur) * f_Scale;
1413 fm_ = (fspur - c) * f_Scale;
1414 } else {
1415 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001416 (s32) RoundAwayFromZero((d - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001417 f_Scale, den);
1418 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001419 (s32) RoundAwayFromZero((fspur - c) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001420 f_Scale, den);
1421 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001422 if (((u32) abs(fm_) >= f_Scale)
1423 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001424 bSpurFound = 1;
1425 break;
1426 }
1427 }
1428
1429 /* Location of Zero-IF-spur to be checked */
1430 mf = (_f3 + f - nf1) / _f2;
1431 me = (_f3 - f - nf1) / _f2;
1432 if (me != mf) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001433 const s32 m = (n < 0) ? mf : me;
1434 const s32 fspur = (nf1 + m * _f2 - _f3);
1435 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001436 if (den == 0) {
1437 fp_ = (d - fspur) * f_Scale;
1438 fm_ = (fspur - c) * f_Scale;
1439 } else {
1440 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001441 (s32) RoundAwayFromZero((f - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001442 f_Scale, den);
1443 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001444 (s32) RoundAwayFromZero((fspur + f) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001445 f_Scale, den);
1446 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001447 if (((u32) abs(fm_) >= f_Scale)
1448 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001449 bSpurFound = 1;
1450 break;
1451 }
1452 }
1453
1454 mb = (_f3 - c - nf1) / _f2;
1455 if (ma != mb) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001456 const s32 m = (n < 0) ? mb : ma;
1457 const s32 fspur = (nf1 + m * _f2 - _f3);
1458 const s32 den = (bIsMyOutput ? n - 1 : n);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001459 if (den == 0) {
1460 fp_ = (d - fspur) * f_Scale;
1461 fm_ = (fspur - c) * f_Scale;
1462 } else {
1463 fp_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001464 (s32) RoundAwayFromZero((-c - fspur) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001465 f_Scale, den);
1466 fm_ =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001467 (s32) RoundAwayFromZero((fspur + d) *
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001468 f_Scale, den);
1469 }
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001470 if (((u32) abs(fm_) >= f_Scale)
1471 && ((u32) abs(fp_) >= f_Scale)) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001472 bSpurFound = 1;
1473 break;
1474 }
1475 }
1476 }
1477
1478 /*
1479 ** Verify that fm & fp are both positive
1480 ** Add one to ensure next 1st IF choice is not right on the edge
1481 */
1482 if (fp_ < 0) {
1483 *fp = -fm_ + 1;
1484 *fm = -fp_ + 1;
1485 } else if (fp_ > 0) {
1486 *fp = fp_ + 1;
1487 *fm = fm_ + 1;
1488 } else {
1489 *fp = 1;
1490 *fm = abs(fm_) + 1;
1491 }
1492
1493 return bSpurFound;
1494}
1495#endif
1496
1497/****************************************************************************
1498**
1499** Name: IsSpurInBand
1500**
1501** Description: Checks to see if a spur will be present within the IF's
1502** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1503**
1504** ma mb mc md
1505** <--+-+-+-------------------+-------------------+-+-+-->
1506** | ^ 0 ^ |
1507** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1508** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1509**
1510** Note that some equations are doubled to prevent round-off
1511** problems when calculating fIFBW/2
1512**
1513** Parameters: pAS_Info - Avoid Spurs information block
1514** fm - If spur, amount f_IF1 has to move negative
1515** fp - If spur, amount f_IF1 has to move positive
1516**
1517** Global: None
1518**
1519** Returns: 1 if an LO spur would be present, otherwise 0.
1520**
1521** Dependencies: None.
1522**
1523** Revision History:
1524**
1525** SCR Date Author Description
1526** -------------------------------------------------------------------------
1527** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1528**
1529****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001530static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1531 u32 * fm, u32 * fp)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001532{
1533 /*
1534 ** Calculate LO frequency settings.
1535 */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001536 u32 n, n0;
1537 const u32 f_LO1 = pAS_Info->f_LO1;
1538 const u32 f_LO2 = pAS_Info->f_LO2;
1539 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1540 const u32 c = d - pAS_Info->f_out_bw;
1541 const u32 f = pAS_Info->f_zif_bw / 2;
1542 const u32 f_Scale = (f_LO1 / (MAX_UDATA / 2 / pAS_Info->maxH1)) + 1;
1543 s32 f_nsLO1, f_nsLO2;
1544 s32 f_Spur;
1545 u32 ma, mb, mc, md, me, mf;
1546 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001547#if MT2063_TUNER_CNT > 1
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001548 u32 index;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001549
1550 struct MT2063_AvoidSpursData_t *adj;
1551#endif
1552 *fm = 0;
1553
1554 /*
1555 ** For each edge (d, c & f), calculate a scale, based on the gcd
1556 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1557 ** gcd-based scale factor or f_Scale.
1558 */
1559 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001560 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001561 hgds = gd_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001562 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001563 hgcs = gc_Scale / 2;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001564 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001565 hgfs = gf_Scale / 2;
1566
1567 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1568
1569 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1570 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1571 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1572 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1573
1574 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1575 if (md >= pAS_Info->maxH1)
1576 break;
1577
1578 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1579 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1580
1581 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1582 if (md == ma)
1583 continue;
1584
1585 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1586 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1587 if (mc != md) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001588 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1589 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001590 f_Spur =
1591 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1592 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1593
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001594 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1595 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001596 return 1;
1597 }
1598
1599 /* Location of Zero-IF-spur to be checked */
1600 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1601 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1602 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1603 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1604 if (me != mf) {
1605 f_nsLO1 = n * (f_LO1 / gf_Scale);
1606 f_nsLO2 = me * (f_LO2 / gf_Scale);
1607 f_Spur =
1608 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1609 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1610
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001611 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1612 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001613 return 1;
1614 }
1615
1616 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1617 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1618 if (ma != mb) {
1619 f_nsLO1 = n * (f_LO1 / gc_Scale);
1620 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1621 f_Spur =
1622 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1623 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1624
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001625 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1626 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001627 return 1;
1628 }
1629 }
1630
1631#if MT2063_TUNER_CNT > 1
1632 /* If no spur found, see if there are more tuners on the same board */
1633 for (index = 0; index < TunerCount; ++index) {
1634 adj = TunerList[index];
1635 if (pAS_Info == adj) /* skip over our own data, don't process it */
1636 continue;
1637
1638 /* Look for LO-related spurs from the adjacent tuner generated into my IF output */
1639 if (IsSpurInAdjTunerBand(1, /* check my IF output */
1640 pAS_Info->f_LO1, /* my fLO1 */
1641 adj->f_LO1, /* the other tuner's fLO1 */
1642 pAS_Info->f_LO2, /* my fLO2 */
1643 pAS_Info->f_out, /* my fOut */
1644 pAS_Info->f_out_bw, /* my output IF bandwidth */
1645 pAS_Info->f_zif_bw, /* my Zero-IF bandwidth */
1646 pAS_Info->maxH2, fp, /* minimum amount to move LO's positive */
1647 fm)) /* miminum amount to move LO's negative */
1648 return 1;
1649 /* Look for LO-related spurs from my tuner generated into the adjacent tuner's IF output */
1650 if (IsSpurInAdjTunerBand(0, /* check his IF output */
1651 pAS_Info->f_LO1, /* my fLO1 */
1652 adj->f_LO1, /* the other tuner's fLO1 */
1653 adj->f_LO2, /* the other tuner's fLO2 */
1654 adj->f_out, /* the other tuner's fOut */
1655 adj->f_out_bw, /* the other tuner's output IF bandwidth */
1656 pAS_Info->f_zif_bw, /* the other tuner's Zero-IF bandwidth */
1657 adj->maxH2, fp, /* minimum amount to move LO's positive */
1658 fm)) /* miminum amount to move LO's negative */
1659 return 1;
1660 }
1661#endif
1662 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001663 return 0;
1664}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001665
1666/*****************************************************************************
1667**
1668** Name: MT_AvoidSpurs
1669**
1670** Description: Main entry point to avoid spurs.
1671** Checks for existing spurs in present LO1, LO2 freqs
1672** and if present, chooses spur-free LO1, LO2 combination
1673** that tunes the same input/output frequencies.
1674**
1675** Revision History:
1676**
1677** SCR Date Author Description
1678** -------------------------------------------------------------------------
1679** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1680**
1681*****************************************************************************/
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03001682static u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001683{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001684 u32 status = 0;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001685 u32 fm, fp; /* restricted range on LO's */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001686 pAS_Info->bSpurAvoided = 0;
1687 pAS_Info->nSpursFound = 0;
1688
1689 if (pAS_Info->maxH1 == 0)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001690 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001691
1692 /*
1693 ** Avoid LO Generated Spurs
1694 **
1695 ** Make sure that have no LO-related spurs within the IF output
1696 ** bandwidth.
1697 **
1698 ** If there is an LO spur in this band, start at the current IF1 frequency
1699 ** and work out until we find a spur-free frequency or run up against the
1700 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1701 ** will be unchanged if a spur-free setting is not found.
1702 */
1703 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1704 if (pAS_Info->bSpurPresent) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001705 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1706 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1707 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1708 u32 delta_IF1;
1709 u32 new_IF1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001710
1711 /*
1712 ** Spur was found, attempt to find a spur-free 1st IF
1713 */
1714 do {
1715 pAS_Info->nSpursFound++;
1716
1717 /* Raise f_IF1_upper, if needed */
1718 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1719
1720 /* Choose next IF1 that is closest to f_IF1_CENTER */
1721 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1722
1723 if (new_IF1 > zfIF1) {
1724 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1725 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1726 } else {
1727 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1728 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1729 }
1730 zfIF1 = new_IF1;
1731
1732 if (zfIF1 > pAS_Info->f_if1_Center)
1733 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1734 else
1735 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1736 }
1737 /*
1738 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1739 ** and there is a spur in the band (again)
1740 */
1741 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1742 pAS_Info->f_if1_bw)
1743 && (pAS_Info->bSpurPresent =
1744 IsSpurInBand(pAS_Info, &fm, &fp)));
1745
1746 /*
1747 ** Use the LO-spur free values found. If the search went all the way to
1748 ** the 1st IF band edge and always found spurs, just leave the original
1749 ** choice. It's as "good" as any other.
1750 */
1751 if (pAS_Info->bSpurPresent == 1) {
1752 status |= MT2063_SPUR_PRESENT_ERR;
1753 pAS_Info->f_LO1 = zfLO1;
1754 pAS_Info->f_LO2 = zfLO2;
1755 } else
1756 pAS_Info->bSpurAvoided = 1;
1757 }
1758
1759 status |=
1760 ((pAS_Info->
1761 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1762
1763 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001764}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001765
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001766//end of mt2063_spuravoid.c
1767//=================================================================
1768//#################################################################
1769//=================================================================
1770
1771/*
1772** The expected version of MT_AvoidSpursData_t
1773** If the version is different, an updated file is needed from Microtune
1774*/
1775/* Expecting version 1.21 of the Spur Avoidance API */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001776
1777typedef enum {
1778 MT2063_SET_ATTEN,
1779 MT2063_INCR_ATTEN,
1780 MT2063_DECR_ATTEN
1781} MT2063_ATTEN_CNTL_MODE;
1782
1783//#define TUNER_MT2063_OPTIMIZATION
1784/*
1785** Constants used by the tuning algorithm
1786*/
1787#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1788#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1789#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1790#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1791#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1792#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1793#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1794#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1795#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1796#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1797#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1798#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1799#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1800#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1801#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1802#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1803#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1804#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1805
1806/*
1807** Define the supported Part/Rev codes for the MT2063
1808*/
1809#define MT2063_B0 (0x9B)
1810#define MT2063_B1 (0x9C)
1811#define MT2063_B2 (0x9D)
1812#define MT2063_B3 (0x9E)
1813
1814/*
1815** The number of Tuner Registers
1816*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001817static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001818
1819#define USE_GLOBAL_TUNER 0
1820
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001821static u32 nMT2063MaxTuners = 1;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001822static u32 nMT2063OpenTuners = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001823
1824/*
1825** Constants for setting receiver modes.
1826** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1827** (DNC1GC & DNC2GC are the values, which are used, when the specific
1828** DNC Output is selected, the other is always off)
1829**
1830** If PAL-L or L' is received, set:
1831** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1832**
1833** --------------+----------------------------------------------
1834** Mode 0 : | MT2063_CABLE_QAM
1835** Mode 1 : | MT2063_CABLE_ANALOG
1836** Mode 2 : | MT2063_OFFAIR_COFDM
1837** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1838** Mode 4 : | MT2063_OFFAIR_ANALOG
1839** Mode 5 : | MT2063_OFFAIR_8VSB
1840** --------------+----+----+----+----+-----+-----+--------------
1841** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1842** --------------+----+----+----+----+-----+-----+
1843**
1844**
1845*/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001846static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1847static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1848static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1849static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1850static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1851static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1852static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1853static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1854static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1855static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1856static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1857static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1858static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1859static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001860
1861/*
1862** Local Function Prototypes - not available for external access.
1863*/
1864
1865/* Forward declaration(s): */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001866static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1867 u32 f_LO_Step, u32 f_Ref);
1868static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1869 u32 f_LO_Step, u32 f_Ref);
1870static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1871 u32 denom);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001872
1873/******************************************************************************
1874**
1875** Name: MT2063_Open
1876**
1877** Description: Initialize the tuner's register values.
1878**
1879** Parameters: MT2063_Addr - Serial bus address of the tuner.
1880** hMT2063 - Tuner handle passed back.
1881** hUserData - User-defined data, if needed for the
1882** MT_ReadSub() & MT_WriteSub functions.
1883**
1884** Returns: status:
1885** MT_OK - No errors
1886** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1887** MT_TUNER_INIT_ERR - Tuner initialization failed
1888** MT_COMM_ERR - Serial bus communications error
1889** MT_ARG_NULL - Null pointer argument passed
1890** MT_TUNER_CNT_ERR - Too many tuners open
1891**
1892** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1893** MT_WriteSub - Write byte(s) of data to the two-wire bus
1894**
1895** Revision History:
1896**
1897** SCR Date Author Description
1898** -------------------------------------------------------------------------
1899** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1900**
1901******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001902static u32 MT2063_Open(struct dvb_frontend *fe)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001903{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001904 u32 status; /* Status to be returned. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001905 struct mt2063_state *state = fe->tuner_priv;
1906
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001907 /* Default tuner handle to NULL. If successful, it will be reassigned */
1908
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001909 if (state->MT2063_init == false)
1910 state->rcvr_mode = MT2063_CABLE_QAM;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001911
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001912 status = MT2063_RegisterTuner(&state->AS_Data);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001913 if (status >= 0) {
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001914 state->rcvr_mode = MT2063_CABLE_QAM;
1915 status = MT2063_ReInit(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001916 }
1917
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001918 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001919 /* MT2063_Close handles the un-registration of the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001920 MT2063_Close(state);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001921 else {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001922 state->MT2063_init = true;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001923 }
1924
1925 return (status);
1926}
1927
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001928/******************************************************************************
1929**
1930** Name: MT2063_Close
1931**
1932** Description: Release the handle to the tuner.
1933**
1934** Parameters: hMT2063 - Handle to the MT2063 tuner
1935**
1936** Returns: status:
1937** MT_OK - No errors
1938** MT_INV_HANDLE - Invalid tuner handle
1939**
1940** Dependencies: mt_errordef.h - definition of error codes
1941**
1942** Revision History:
1943**
1944** SCR Date Author Description
1945** -------------------------------------------------------------------------
1946** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1947**
1948******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001949static u32 MT2063_Close(struct mt2063_state *state)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001950{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001951 /* Unregister tuner with SpurAvoidance routines (if needed) */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001952 MT2063_UnRegisterTuner(&state->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001953 /* Now remove the tuner from our own list of tuners */
Mauro Carvalho Chehaba0813ea2011-07-20 21:19:08 -03001954
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001955 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001956}
1957
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001958/****************************************************************************
1959**
1960** Name: MT2063_GetLocked
1961**
1962** Description: Checks to see if LO1 and LO2 are locked.
1963**
1964** Parameters: h - Open handle to the tuner (from MT2063_Open).
1965**
1966** Returns: status:
1967** MT_OK - No errors
1968** MT_UPC_UNLOCK - Upconverter PLL unlocked
1969** MT_DNC_UNLOCK - Downconverter PLL unlocked
1970** MT_COMM_ERR - Serial bus communications error
1971** MT_INV_HANDLE - Invalid tuner handle
1972**
1973** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1974** MT_Sleep - Delay execution for x milliseconds
1975**
1976** Revision History:
1977**
1978** SCR Date Author Description
1979** -------------------------------------------------------------------------
1980** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1981**
1982****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001983static u32 MT2063_GetLocked(struct mt2063_state *pInfo)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001984{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001985 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1986 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1987 const u32 nMaxLoops = nMaxWait / nPollRate;
1988 const u8 LO1LK = 0x80;
1989 u8 LO2LK = 0x08;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03001990 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03001991 u32 nDelays = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001992
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001993 /* LO2 Lock bit was in a different place for B0 version */
1994 if (pInfo->tuner_id == MT2063_B0)
1995 LO2LK = 0x40;
1996
1997 do {
1998 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03001999 MT2063_ReadSub(pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002000 MT2063_REG_LO_STATUS,
2001 &pInfo->reg[MT2063_REG_LO_STATUS], 1);
2002
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002003 if (status < 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002004 return (status);
2005
2006 if ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
2007 (LO1LK | LO2LK)) {
2008 return (status);
2009 }
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03002010 msleep(nPollRate); /* Wait between retries */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002011 }
2012 while (++nDelays < nMaxLoops);
2013
2014 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
2015 status |= MT2063_UPC_UNLOCK;
2016 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
2017 status |= MT2063_DNC_UNLOCK;
2018
2019 return (status);
2020}
2021
2022/****************************************************************************
2023**
2024** Name: MT2063_GetParam
2025**
2026** Description: Gets a tuning algorithm parameter.
2027**
2028** This function provides access to the internals of the
2029** tuning algorithm - mostly for testing purposes.
2030**
2031** Parameters: h - Tuner handle (returned by MT2063_Open)
2032** param - Tuning algorithm parameter
2033** (see enum MT2063_Param)
2034** pValue - ptr to returned value
2035**
2036** param Description
2037** ---------------------- --------------------------------
2038** MT2063_IC_ADDR Serial Bus address of this tuner
2039** MT2063_MAX_OPEN Max # of MT2063's allowed open
2040** MT2063_NUM_OPEN # of MT2063's open
2041** MT2063_SRO_FREQ crystal frequency
2042** MT2063_STEPSIZE minimum tuning step size
2043** MT2063_INPUT_FREQ input center frequency
2044** MT2063_LO1_FREQ LO1 Frequency
2045** MT2063_LO1_STEPSIZE LO1 minimum step size
2046** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2047** MT2063_IF1_ACTUAL Current 1st IF in use
2048** MT2063_IF1_REQUEST Requested 1st IF
2049** MT2063_IF1_CENTER Center of 1st IF SAW filter
2050** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
2051** MT2063_ZIF_BW zero-IF bandwidth
2052** MT2063_LO2_FREQ LO2 Frequency
2053** MT2063_LO2_STEPSIZE LO2 minimum step size
2054** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
2055** MT2063_OUTPUT_FREQ output center frequency
2056** MT2063_OUTPUT_BW output bandwidth
2057** MT2063_LO_SEPARATION min inter-tuner LO separation
2058** MT2063_AS_ALG ID of avoid-spurs algorithm in use
2059** MT2063_MAX_HARM1 max # of intra-tuner harmonics
2060** MT2063_MAX_HARM2 max # of inter-tuner harmonics
2061** MT2063_EXCL_ZONES # of 1st IF exclusion zones
2062** MT2063_NUM_SPURS # of spurs found/avoided
2063** MT2063_SPUR_AVOIDED >0 spurs avoided
2064** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
2065** MT2063_RCVR_MODE Predefined modes.
2066** MT2063_ACLNA LNA attenuator gain code
2067** MT2063_ACRF RF attenuator gain code
2068** MT2063_ACFIF FIF attenuator gain code
2069** MT2063_ACLNA_MAX LNA attenuator limit
2070** MT2063_ACRF_MAX RF attenuator limit
2071** MT2063_ACFIF_MAX FIF attenuator limit
2072** MT2063_PD1 Actual value of PD1
2073** MT2063_PD2 Actual value of PD2
2074** MT2063_DNC_OUTPUT_ENABLE DNC output selection
2075** MT2063_VGAGC VGA gain code
2076** MT2063_VGAOI VGA output current
2077** MT2063_TAGC TAGC setting
2078** MT2063_AMPGC AMP gain code
2079** MT2063_AVOID_DECT Avoid DECT Frequencies
2080** MT2063_CTFILT_SW Cleartune filter selection
2081**
2082** Usage: status |= MT2063_GetParam(hMT2063,
2083** MT2063_IF1_ACTUAL,
2084** &f_IF1_Actual);
2085**
2086** Returns: status:
2087** MT_OK - No errors
2088** MT_INV_HANDLE - Invalid tuner handle
2089** MT_ARG_NULL - Null pointer argument passed
2090** MT_ARG_RANGE - Invalid parameter requested
2091**
2092** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2093**
2094** See Also: MT2063_SetParam, MT2063_Open
2095**
2096** Revision History:
2097**
2098** SCR Date Author Description
2099** -------------------------------------------------------------------------
2100** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2101** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
2102** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
2103** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
2104** in GetParam.
2105** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2106** Split SetParam up to ACLNA / ACLNA_MAX
2107** removed ACLNA_INRC/DECR (+RF & FIF)
2108** removed GCUAUTO / BYPATNDN/UP
2109** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
2110** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2111** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2112**
2113****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002114static u32 MT2063_GetParam(struct mt2063_state *pInfo, enum MT2063_Param param, u32 *pValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002115{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002116 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002117 u32 Div;
2118 u32 Num;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002119
2120 if (pValue == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002121 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002122
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002123 switch (param) {
2124 /* Serial Bus address of this tuner */
2125 case MT2063_IC_ADDR:
2126 *pValue = pInfo->config->tuner_address;
2127 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002128
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002129 /* Max # of MT2063's allowed to be open */
2130 case MT2063_MAX_OPEN:
2131 *pValue = nMT2063MaxTuners;
2132 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002133
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002134 /* # of MT2063's open */
2135 case MT2063_NUM_OPEN:
2136 *pValue = nMT2063OpenTuners;
2137 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002138
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002139 /* crystal frequency */
2140 case MT2063_SRO_FREQ:
2141 *pValue = pInfo->AS_Data.f_ref;
2142 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002143
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002144 /* minimum tuning step size */
2145 case MT2063_STEPSIZE:
2146 *pValue = pInfo->AS_Data.f_LO2_Step;
2147 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002148
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002149 /* input center frequency */
2150 case MT2063_INPUT_FREQ:
2151 *pValue = pInfo->AS_Data.f_in;
2152 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002153
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002154 /* LO1 Frequency */
2155 case MT2063_LO1_FREQ:
2156 {
2157 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
2158 status |=
2159 MT2063_ReadSub(pInfo,
2160 MT2063_REG_LO1C_1,
2161 &pInfo->
2162 reg[MT2063_REG_LO1C_1], 2);
2163 Div = pInfo->reg[MT2063_REG_LO1C_1];
2164 Num = pInfo->reg[MT2063_REG_LO1C_2] & 0x3F;
2165 pInfo->AS_Data.f_LO1 =
2166 (pInfo->AS_Data.f_ref * Div) +
2167 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2168 f_ref, Num, 64);
2169 }
2170 *pValue = pInfo->AS_Data.f_LO1;
2171 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002172
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002173 /* LO1 minimum step size */
2174 case MT2063_LO1_STEPSIZE:
2175 *pValue = pInfo->AS_Data.f_LO1_Step;
2176 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002177
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002178 /* LO1 FracN keep-out region */
2179 case MT2063_LO1_FRACN_AVOID_PARAM:
2180 *pValue = pInfo->AS_Data.f_LO1_FracN_Avoid;
2181 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002182
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002183 /* Current 1st IF in use */
2184 case MT2063_IF1_ACTUAL:
2185 *pValue = pInfo->f_IF1_actual;
2186 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002187
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002188 /* Requested 1st IF */
2189 case MT2063_IF1_REQUEST:
2190 *pValue = pInfo->AS_Data.f_if1_Request;
2191 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002192
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002193 /* Center of 1st IF SAW filter */
2194 case MT2063_IF1_CENTER:
2195 *pValue = pInfo->AS_Data.f_if1_Center;
2196 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002197
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002198 /* Bandwidth of 1st IF SAW filter */
2199 case MT2063_IF1_BW:
2200 *pValue = pInfo->AS_Data.f_if1_bw;
2201 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002202
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002203 /* zero-IF bandwidth */
2204 case MT2063_ZIF_BW:
2205 *pValue = pInfo->AS_Data.f_zif_bw;
2206 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002207
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002208 /* LO2 Frequency */
2209 case MT2063_LO2_FREQ:
2210 {
2211 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
2212 status |=
2213 MT2063_ReadSub(pInfo,
2214 MT2063_REG_LO2C_1,
2215 &pInfo->
2216 reg[MT2063_REG_LO2C_1], 3);
2217 Div =
2218 (pInfo->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
2219 Num =
2220 ((pInfo->
2221 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
2222 (pInfo->
2223 reg[MT2063_REG_LO2C_2] << 4) | (pInfo->
2224 reg
2225 [MT2063_REG_LO2C_3]
2226 & 0x00F);
2227 pInfo->AS_Data.f_LO2 =
2228 (pInfo->AS_Data.f_ref * Div) +
2229 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2230 f_ref, Num, 8191);
2231 }
2232 *pValue = pInfo->AS_Data.f_LO2;
2233 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002234
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002235 /* LO2 minimum step size */
2236 case MT2063_LO2_STEPSIZE:
2237 *pValue = pInfo->AS_Data.f_LO2_Step;
2238 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002239
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002240 /* LO2 FracN keep-out region */
2241 case MT2063_LO2_FRACN_AVOID:
2242 *pValue = pInfo->AS_Data.f_LO2_FracN_Avoid;
2243 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002244
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002245 /* output center frequency */
2246 case MT2063_OUTPUT_FREQ:
2247 *pValue = pInfo->AS_Data.f_out;
2248 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002249
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002250 /* output bandwidth */
2251 case MT2063_OUTPUT_BW:
2252 *pValue = pInfo->AS_Data.f_out_bw - 750000;
2253 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002254
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002255 /* min inter-tuner LO separation */
2256 case MT2063_LO_SEPARATION:
2257 *pValue = pInfo->AS_Data.f_min_LO_Separation;
2258 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002259
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002260 /* ID of avoid-spurs algorithm in use */
2261 case MT2063_AS_ALG:
2262 *pValue = pInfo->AS_Data.nAS_Algorithm;
2263 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002264
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002265 /* max # of intra-tuner harmonics */
2266 case MT2063_MAX_HARM1:
2267 *pValue = pInfo->AS_Data.maxH1;
2268 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002269
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002270 /* max # of inter-tuner harmonics */
2271 case MT2063_MAX_HARM2:
2272 *pValue = pInfo->AS_Data.maxH2;
2273 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002274
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002275 /* # of 1st IF exclusion zones */
2276 case MT2063_EXCL_ZONES:
2277 *pValue = pInfo->AS_Data.nZones;
2278 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002279
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002280 /* # of spurs found/avoided */
2281 case MT2063_NUM_SPURS:
2282 *pValue = pInfo->AS_Data.nSpursFound;
2283 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002284
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002285 /* >0 spurs avoided */
2286 case MT2063_SPUR_AVOIDED:
2287 *pValue = pInfo->AS_Data.bSpurAvoided;
2288 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002289
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002290 /* >0 spurs in output (mathematically) */
2291 case MT2063_SPUR_PRESENT:
2292 *pValue = pInfo->AS_Data.bSpurPresent;
2293 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002294
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002295 /* Predefined receiver setup combination */
2296 case MT2063_RCVR_MODE:
2297 *pValue = pInfo->rcvr_mode;
2298 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002299
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002300 case MT2063_PD1:
2301 case MT2063_PD2: {
2302 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
2303 u8 orig = (pInfo->reg[MT2063_REG_BYP_CTRL]);
2304 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
2305 int i;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002306
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002307 *pValue = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002308
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002309 /* Initiate ADC output to reg 0x0A */
2310 if (reg != orig)
2311 status |=
2312 MT2063_WriteSub(pInfo,
2313 MT2063_REG_BYP_CTRL,
2314 &reg, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002315
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002316 if (status < 0)
2317 return (status);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002318
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002319 for (i = 0; i < 8; i++) {
2320 status |=
2321 MT2063_ReadSub(pInfo,
2322 MT2063_REG_ADC_OUT,
2323 &pInfo->
2324 reg
2325 [MT2063_REG_ADC_OUT],
2326 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002327
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002328 if (status >= 0)
2329 *pValue +=
2330 pInfo->
2331 reg[MT2063_REG_ADC_OUT];
2332 else {
2333 if (i)
2334 *pValue /= i;
2335 return (status);
2336 }
2337 }
2338 *pValue /= 8; /* divide by number of reads */
2339 *pValue >>= 2; /* only want 6 MSB's out of 8 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002340
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002341 /* Restore value of Register BYP_CTRL */
2342 if (reg != orig)
2343 status |=
2344 MT2063_WriteSub(pInfo,
2345 MT2063_REG_BYP_CTRL,
2346 &orig, 1);
2347 }
2348 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002349
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002350 /* Get LNA attenuator code */
2351 case MT2063_ACLNA:
2352 {
2353 u8 val;
2354 status |=
2355 MT2063_GetReg(pInfo, MT2063_REG_XO_STATUS,
2356 &val);
2357 *pValue = val & 0x1f;
2358 }
2359 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002360
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002361 /* Get RF attenuator code */
2362 case MT2063_ACRF:
2363 {
2364 u8 val;
2365 status |=
2366 MT2063_GetReg(pInfo, MT2063_REG_RF_STATUS,
2367 &val);
2368 *pValue = val & 0x1f;
2369 }
2370 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002371
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002372 /* Get FIF attenuator code */
2373 case MT2063_ACFIF:
2374 {
2375 u8 val;
2376 status |=
2377 MT2063_GetReg(pInfo, MT2063_REG_FIF_STATUS,
2378 &val);
2379 *pValue = val & 0x1f;
2380 }
2381 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002382
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002383 /* Get LNA attenuator limit */
2384 case MT2063_ACLNA_MAX:
2385 {
2386 u8 val;
2387 status |=
2388 MT2063_GetReg(pInfo, MT2063_REG_LNA_OV,
2389 &val);
2390 *pValue = val & 0x1f;
2391 }
2392 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002393
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002394 /* Get RF attenuator limit */
2395 case MT2063_ACRF_MAX:
2396 {
2397 u8 val;
2398 status |=
2399 MT2063_GetReg(pInfo, MT2063_REG_RF_OV,
2400 &val);
2401 *pValue = val & 0x1f;
2402 }
2403 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002404
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002405 /* Get FIF attenuator limit */
2406 case MT2063_ACFIF_MAX:
2407 {
2408 u8 val;
2409 status |=
2410 MT2063_GetReg(pInfo, MT2063_REG_FIF_OV,
2411 &val);
2412 *pValue = val & 0x1f;
2413 }
2414 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002415
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002416 /* Get current used DNC output */
2417 case MT2063_DNC_OUTPUT_ENABLE:
2418 {
2419 if ((pInfo->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
2420 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2421 *pValue =
2422 (u32) MT2063_DNC_NONE;
2423 else
2424 *pValue =
2425 (u32) MT2063_DNC_2;
2426 } else { /* DNC1 is on */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002427
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002428 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2429 *pValue =
2430 (u32) MT2063_DNC_1;
2431 else
2432 *pValue =
2433 (u32) MT2063_DNC_BOTH;
2434 }
2435 }
2436 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002437
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002438 /* Get VGA Gain Code */
2439 case MT2063_VGAGC:
2440 *pValue = ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
2441 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002442
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002443 /* Get VGA bias current */
2444 case MT2063_VGAOI:
2445 *pValue = (pInfo->reg[MT2063_REG_RSVD_31] & 0x07);
2446 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002447
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002448 /* Get TAGC setting */
2449 case MT2063_TAGC:
2450 *pValue = (pInfo->reg[MT2063_REG_RSVD_1E] & 0x03);
2451 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002452
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002453 /* Get AMP Gain Code */
2454 case MT2063_AMPGC:
2455 *pValue = (pInfo->reg[MT2063_REG_TEMP_SEL] & 0x03);
2456 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002457
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002458 /* Avoid DECT Frequencies */
2459 case MT2063_AVOID_DECT:
2460 *pValue = pInfo->AS_Data.avoidDECT;
2461 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002462
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002463 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2464 case MT2063_CTFILT_SW:
2465 *pValue = pInfo->ctfilt_sw;
2466 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002467
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002468 case MT2063_EOP:
2469 default:
2470 status |= -ERANGE;
2471 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002472 return (status);
2473}
2474
2475/****************************************************************************
2476**
2477** Name: MT2063_GetReg
2478**
2479** Description: Gets an MT2063 register.
2480**
2481** Parameters: h - Tuner handle (returned by MT2063_Open)
2482** reg - MT2063 register/subaddress location
2483** *val - MT2063 register/subaddress value
2484**
2485** Returns: status:
2486** MT_OK - No errors
2487** MT_COMM_ERR - Serial bus communications error
2488** MT_INV_HANDLE - Invalid tuner handle
2489** MT_ARG_NULL - Null pointer argument passed
2490** MT_ARG_RANGE - Argument out of range
2491**
2492** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2493**
2494** Use this function if you need to read a register from
2495** the MT2063.
2496**
2497** Revision History:
2498**
2499** SCR Date Author Description
2500** -------------------------------------------------------------------------
2501** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2502**
2503****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002504static u32 MT2063_GetReg(struct mt2063_state *pInfo, u8 reg, u8 * val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002505{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002506 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002507
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002508 if (val == NULL)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002509 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002510
2511 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002512 return -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002513
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002514 status = MT2063_ReadSub(pInfo, reg, &pInfo->reg[reg], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002515
2516 return (status);
2517}
2518
2519/******************************************************************************
2520**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002521** Name: MT2063_SetReceiverMode
2522**
2523** Description: Set the MT2063 receiver mode
2524**
2525** --------------+----------------------------------------------
2526** Mode 0 : | MT2063_CABLE_QAM
2527** Mode 1 : | MT2063_CABLE_ANALOG
2528** Mode 2 : | MT2063_OFFAIR_COFDM
2529** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2530** Mode 4 : | MT2063_OFFAIR_ANALOG
2531** Mode 5 : | MT2063_OFFAIR_8VSB
2532** --------------+----+----+----+----+-----+--------------------
2533** (DNC1GC & DNC2GC are the values, which are used, when the specific
2534** DNC Output is selected, the other is always off)
2535**
2536** |<---------- Mode -------------->|
2537** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2538** ------------+-----+-----+-----+-----+-----+-----+
2539** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2540** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2541** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2542** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2543** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2544** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2545** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2546** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2547** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2548** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2549** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2550** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2551** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2552** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2553** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2554**
2555**
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002556** Parameters: pInfo - ptr to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002557** Mode - desired reciever mode
2558**
2559** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2560**
2561** Returns: status:
2562** MT_OK - No errors
2563** MT_COMM_ERR - Serial bus communications error
2564**
2565** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2566** Assumes that the tuner cache is valid.
2567**
2568** Revision History:
2569**
2570** SCR Date Author Description
2571** -------------------------------------------------------------------------
2572** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2573** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2574** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2575** modulation
2576** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2577** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2578** the same settings as with MT Launcher
2579** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2580** Add SetParam DNC_OUTPUT_ENABLE
2581** Removed VGAGC from receiver mode,
2582** default now 1
2583** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2584** Add SetParam AMPGC, removed from rcvr-mode
2585** Corrected names of GCU values
2586** reorganized receiver modes, removed,
2587** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2588** Actualized Receiver-Mode values
2589** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2590** N/A 11-27-2007 PINZ Improved buffered writing
2591** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2592** correct wakeup of the LNA after shutdown
2593** Set AFCsd = 1 as default
2594** Changed CAP1sel default
2595** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2596** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2597** Split SetParam up to ACLNA / ACLNA_MAX
2598** removed ACLNA_INRC/DECR (+RF & FIF)
2599** removed GCUAUTO / BYPATNDN/UP
2600**
2601******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002602static u32 MT2063_SetReceiverMode(struct mt2063_state *pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002603 enum MT2063_RCVR_MODES Mode)
2604{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002605 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002606 u8 val;
2607 u32 longval;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002608
2609 if (Mode >= MT2063_NUM_RCVR_MODES)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002610 status = -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002611
2612 /* RFAGCen */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002613 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002614 val =
2615 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002616 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002617 ? 0x40 :
2618 0x00);
2619 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2620 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2621 }
2622 }
2623
2624 /* LNARin */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002625 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002626 status |= MT2063_SetParam(pInfo, MT2063_LNA_RIN, LNARIN[Mode]);
2627 }
2628
2629 /* FIFFQEN and FIFFQ */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002630 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002631 val =
2632 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002633 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002634 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
2635 if (pInfo->reg[MT2063_REG_FIFF_CTRL2] != val) {
2636 status |=
2637 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL2, val);
2638 /* trigger FIFF calibration, needed after changing FIFFQ */
2639 val =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002640 (pInfo->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002641 status |=
2642 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2643 val =
2644 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002645 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002646 status |=
2647 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2648 }
2649 }
2650
2651 /* DNC1GC & DNC2GC */
2652 status |= MT2063_GetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, &longval);
2653 status |= MT2063_SetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, longval);
2654
2655 /* acLNAmax */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002656 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002657 status |=
2658 MT2063_SetParam(pInfo, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
2659 }
2660
2661 /* LNATGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002662 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002663 status |= MT2063_SetParam(pInfo, MT2063_LNA_TGT, LNATGT[Mode]);
2664 }
2665
2666 /* ACRF */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002667 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002668 status |=
2669 MT2063_SetParam(pInfo, MT2063_ACRF_MAX, ACRFMAX[Mode]);
2670 }
2671
2672 /* PD1TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002673 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002674 status |= MT2063_SetParam(pInfo, MT2063_PD1_TGT, PD1TGT[Mode]);
2675 }
2676
2677 /* FIFATN */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002678 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002679 status |=
2680 MT2063_SetParam(pInfo, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
2681 }
2682
2683 /* PD2TGT */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002684 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002685 status |= MT2063_SetParam(pInfo, MT2063_PD2_TGT, PD2TGT[Mode]);
2686 }
2687
2688 /* Ignore ATN Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002689 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002690 val =
2691 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002692 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002693 ? 0x80 :
2694 0x00);
2695 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
2696 status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val);
2697 }
2698 }
2699
2700 /* Ignore FIF Overload */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002701 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002702 val =
2703 (pInfo->
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002704 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002705 (FIFOVDIS[Mode] ? 0x80 : 0x00);
2706 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2707 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2708 }
2709 }
2710
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002711 if (status >= 0)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002712 pInfo->rcvr_mode = Mode;
2713
2714 return (status);
2715}
2716
2717/******************************************************************************
2718**
2719** Name: MT2063_ReInit
2720**
2721** Description: Initialize the tuner's register values.
2722**
2723** Parameters: h - Tuner handle (returned by MT2063_Open)
2724**
2725** Returns: status:
2726** MT_OK - No errors
2727** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2728** MT_INV_HANDLE - Invalid tuner handle
2729** MT_COMM_ERR - Serial bus communications error
2730**
2731** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2732** MT_WriteSub - Write byte(s) of data to the two-wire bus
2733**
2734** Revision History:
2735**
2736** SCR Date Author Description
2737** -------------------------------------------------------------------------
2738** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2739** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2740** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2741** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2742** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2743** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2744** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2745** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2746** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2747** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2748** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2749**
2750******************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002751static u32 MT2063_ReInit(struct mt2063_state *pInfo)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002752{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002753 u8 all_resets = 0xF0; /* reset/load bits */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002754 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabf8676952011-07-20 22:00:30 -03002755 u8 *def = NULL;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002756 u32 FCRUN;
2757 s32 maxReads;
2758 u32 fcu_osc;
2759 u32 i;
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002760 u8 MT2063B0_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002761 0x19, 0x05,
2762 0x1B, 0x1D,
2763 0x1C, 0x1F,
2764 0x1D, 0x0F,
2765 0x1E, 0x3F,
2766 0x1F, 0x0F,
2767 0x20, 0x3F,
2768 0x22, 0x21,
2769 0x23, 0x3F,
2770 0x24, 0x20,
2771 0x25, 0x3F,
2772 0x27, 0xEE,
2773 0x2C, 0x27, /* bit at 0x20 is cleared below */
2774 0x30, 0x03,
2775 0x2C, 0x07, /* bit at 0x20 is cleared here */
2776 0x2D, 0x87,
2777 0x2E, 0xAA,
2778 0x28, 0xE1, /* Set the FIFCrst bit here */
2779 0x28, 0xE0, /* Clear the FIFCrst bit here */
2780 0x00
2781 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002782 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002783 u8 MT2063B1_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002784 0x05, 0xF0,
2785 0x11, 0x10, /* New Enable AFCsd */
2786 0x19, 0x05,
2787 0x1A, 0x6C,
2788 0x1B, 0x24,
2789 0x1C, 0x28,
2790 0x1D, 0x8F,
2791 0x1E, 0x14,
2792 0x1F, 0x8F,
2793 0x20, 0x57,
2794 0x22, 0x21, /* New - ver 1.03 */
2795 0x23, 0x3C, /* New - ver 1.10 */
2796 0x24, 0x20, /* New - ver 1.03 */
2797 0x2C, 0x24, /* bit at 0x20 is cleared below */
2798 0x2D, 0x87, /* FIFFQ=0 */
2799 0x2F, 0xF3,
2800 0x30, 0x0C, /* New - ver 1.11 */
2801 0x31, 0x1B, /* New - ver 1.11 */
2802 0x2C, 0x04, /* bit at 0x20 is cleared here */
2803 0x28, 0xE1, /* Set the FIFCrst bit here */
2804 0x28, 0xE0, /* Clear the FIFCrst bit here */
2805 0x00
2806 };
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002807 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002808 u8 MT2063B3_defaults[] = { /* Reg, Value */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002809 0x05, 0xF0,
2810 0x19, 0x3D,
2811 0x2C, 0x24, /* bit at 0x20 is cleared below */
2812 0x2C, 0x04, /* bit at 0x20 is cleared here */
2813 0x28, 0xE1, /* Set the FIFCrst bit here */
2814 0x28, 0xE0, /* Clear the FIFCrst bit here */
2815 0x00
2816 };
2817
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002818 /* Read the Part/Rev code from the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002819 status = MT2063_ReadSub(pInfo, MT2063_REG_PART_REV, pInfo->reg, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002820 if (status < 0)
2821 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002822
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002823 /* Check the part/rev code */
2824 if (((pInfo->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2825 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2826 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
2827 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002828
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002829 /* Check the 2nd byte of the Part/Rev code from the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002830 status = MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002831 MT2063_REG_RSVD_3B,
2832 &pInfo->reg[MT2063_REG_RSVD_3B], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002833
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002834 if (status >= 0
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002835 &&((pInfo->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002836 return -ENODEV; /* Wrong tuner Part/Rev code */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002837
2838 /* Reset the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002839 status = MT2063_WriteSub(pInfo, MT2063_REG_LO2CQ_3, &all_resets, 1);
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002840 if (status < 0)
2841 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002842
2843 /* change all of the default values that vary from the HW reset values */
2844 /* def = (pInfo->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2845 switch (pInfo->reg[MT2063_REG_PART_REV]) {
2846 case MT2063_B3:
2847 def = MT2063B3_defaults;
2848 break;
2849
2850 case MT2063_B1:
2851 def = MT2063B1_defaults;
2852 break;
2853
2854 case MT2063_B0:
2855 def = MT2063B0_defaults;
2856 break;
2857
2858 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002859 return -ENODEV;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002860 break;
2861 }
2862
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002863 while (status >= 0 && *def) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03002864 u8 reg = *def++;
2865 u8 val = *def++;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002866 status = MT2063_WriteSub(pInfo, reg, &val, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002867 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002868 if (status < 0)
2869 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002870
2871 /* Wait for FIFF location to complete. */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002872 FCRUN = 1;
2873 maxReads = 10;
2874 while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
2875 msleep(2);
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002876 status = MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002877 MT2063_REG_XO_STATUS,
2878 &pInfo->
2879 reg[MT2063_REG_XO_STATUS], 1);
2880 FCRUN = (pInfo->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002881 }
2882
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002883 if (FCRUN != 0)
2884 return -ENODEV;
2885
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002886 status = MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002887 MT2063_REG_FIFFC,
2888 &pInfo->reg[MT2063_REG_FIFFC], 1);
2889 if (status < 0)
2890 return status;
2891
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002892 /* Read back all the registers from the tuner */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002893 status = MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002894 MT2063_REG_PART_REV,
2895 pInfo->reg, MT2063_REG_END_REGS);
2896 if (status < 0)
2897 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002898
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002899 /* Initialize the tuner state. */
2900 pInfo->tuner_id = pInfo->reg[MT2063_REG_PART_REV];
2901 pInfo->AS_Data.f_ref = MT2063_REF_FREQ;
2902 pInfo->AS_Data.f_if1_Center = (pInfo->AS_Data.f_ref / 8) *
2903 ((u32) pInfo->reg[MT2063_REG_FIFFC] + 640);
2904 pInfo->AS_Data.f_if1_bw = MT2063_IF1_BW;
2905 pInfo->AS_Data.f_out = 43750000UL;
2906 pInfo->AS_Data.f_out_bw = 6750000UL;
2907 pInfo->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2908 pInfo->AS_Data.f_LO1_Step = pInfo->AS_Data.f_ref / 64;
2909 pInfo->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2910 pInfo->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2911 pInfo->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2912 pInfo->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2913 pInfo->AS_Data.f_if1_Request = pInfo->AS_Data.f_if1_Center;
2914 pInfo->AS_Data.f_LO1 = 2181000000UL;
2915 pInfo->AS_Data.f_LO2 = 1486249786UL;
2916 pInfo->f_IF1_actual = pInfo->AS_Data.f_if1_Center;
2917 pInfo->AS_Data.f_in = pInfo->AS_Data.f_LO1 - pInfo->f_IF1_actual;
2918 pInfo->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2919 pInfo->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2920 pInfo->num_regs = MT2063_REG_END_REGS;
2921 pInfo->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2922 pInfo->ctfilt_sw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002923
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002924 pInfo->CTFiltMax[0] = 69230000;
2925 pInfo->CTFiltMax[1] = 105770000;
2926 pInfo->CTFiltMax[2] = 140350000;
2927 pInfo->CTFiltMax[3] = 177110000;
2928 pInfo->CTFiltMax[4] = 212860000;
2929 pInfo->CTFiltMax[5] = 241130000;
2930 pInfo->CTFiltMax[6] = 274370000;
2931 pInfo->CTFiltMax[7] = 309820000;
2932 pInfo->CTFiltMax[8] = 342450000;
2933 pInfo->CTFiltMax[9] = 378870000;
2934 pInfo->CTFiltMax[10] = 416210000;
2935 pInfo->CTFiltMax[11] = 456500000;
2936 pInfo->CTFiltMax[12] = 495790000;
2937 pInfo->CTFiltMax[13] = 534530000;
2938 pInfo->CTFiltMax[14] = 572610000;
2939 pInfo->CTFiltMax[15] = 598970000;
2940 pInfo->CTFiltMax[16] = 635910000;
2941 pInfo->CTFiltMax[17] = 672130000;
2942 pInfo->CTFiltMax[18] = 714840000;
2943 pInfo->CTFiltMax[19] = 739660000;
2944 pInfo->CTFiltMax[20] = 770410000;
2945 pInfo->CTFiltMax[21] = 814660000;
2946 pInfo->CTFiltMax[22] = 846950000;
2947 pInfo->CTFiltMax[23] = 867820000;
2948 pInfo->CTFiltMax[24] = 915980000;
2949 pInfo->CTFiltMax[25] = 947450000;
2950 pInfo->CTFiltMax[26] = 983110000;
2951 pInfo->CTFiltMax[27] = 1021630000;
2952 pInfo->CTFiltMax[28] = 1061870000;
2953 pInfo->CTFiltMax[29] = 1098330000;
2954 pInfo->CTFiltMax[30] = 1138990000;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002955
2956 /*
2957 ** Fetch the FCU osc value and use it and the fRef value to
2958 ** scale all of the Band Max values
2959 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002960
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002961 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002962 status = MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002963 MT2063_REG_CTUNE_CTRL,
2964 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2965 if (status < 0)
2966 return status;
2967 /* Read the ClearTune filter calibration value */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002968 status = MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002969 MT2063_REG_FIFFC,
2970 &pInfo->reg[MT2063_REG_FIFFC], 1);
2971 if (status < 0)
2972 return status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002973
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002974 fcu_osc = pInfo->reg[MT2063_REG_FIFFC];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002975
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002976 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03002977 status = MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03002978 MT2063_REG_CTUNE_CTRL,
2979 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2980 if (status < 0)
2981 return status;
2982
2983 /* Adjust each of the values in the ClearTune filter cross-over table */
2984 for (i = 0; i < 31; i++)
2985 pInfo->CTFiltMax[i] =(pInfo->CTFiltMax[i] / 768) * (fcu_osc + 640);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002986
2987 return (status);
2988}
2989
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03002990/****************************************************************************
2991**
2992** Name: MT2063_SetParam
2993**
2994** Description: Sets a tuning algorithm parameter.
2995**
2996** This function provides access to the internals of the
2997** tuning algorithm. You can override many of the tuning
2998** algorithm defaults using this function.
2999**
3000** Parameters: h - Tuner handle (returned by MT2063_Open)
3001** param - Tuning algorithm parameter
3002** (see enum MT2063_Param)
3003** nValue - value to be set
3004**
3005** param Description
3006** ---------------------- --------------------------------
3007** MT2063_SRO_FREQ crystal frequency
3008** MT2063_STEPSIZE minimum tuning step size
3009** MT2063_LO1_FREQ LO1 frequency
3010** MT2063_LO1_STEPSIZE LO1 minimum step size
3011** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
3012** MT2063_IF1_REQUEST Requested 1st IF
3013** MT2063_ZIF_BW zero-IF bandwidth
3014** MT2063_LO2_FREQ LO2 frequency
3015** MT2063_LO2_STEPSIZE LO2 minimum step size
3016** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
3017** MT2063_OUTPUT_FREQ output center frequency
3018** MT2063_OUTPUT_BW output bandwidth
3019** MT2063_LO_SEPARATION min inter-tuner LO separation
3020** MT2063_MAX_HARM1 max # of intra-tuner harmonics
3021** MT2063_MAX_HARM2 max # of inter-tuner harmonics
3022** MT2063_RCVR_MODE Predefined modes
3023** MT2063_LNA_RIN Set LNA Rin (*)
3024** MT2063_LNA_TGT Set target power level at LNA (*)
3025** MT2063_PD1_TGT Set target power level at PD1 (*)
3026** MT2063_PD2_TGT Set target power level at PD2 (*)
3027** MT2063_ACLNA_MAX LNA attenuator limit (*)
3028** MT2063_ACRF_MAX RF attenuator limit (*)
3029** MT2063_ACFIF_MAX FIF attenuator limit (*)
3030** MT2063_DNC_OUTPUT_ENABLE DNC output selection
3031** MT2063_VGAGC VGA gain code
3032** MT2063_VGAOI VGA output current
3033** MT2063_TAGC TAGC setting
3034** MT2063_AMPGC AMP gain code
3035** MT2063_AVOID_DECT Avoid DECT Frequencies
3036** MT2063_CTFILT_SW Cleartune filter selection
3037**
3038** (*) This parameter is set by MT2063_RCVR_MODE, do not call
3039** additionally.
3040**
3041** Usage: status |= MT2063_SetParam(hMT2063,
3042** MT2063_STEPSIZE,
3043** 50000);
3044**
3045** Returns: status:
3046** MT_OK - No errors
3047** MT_INV_HANDLE - Invalid tuner handle
3048** MT_ARG_NULL - Null pointer argument passed
3049** MT_ARG_RANGE - Invalid parameter requested
3050** or set value out of range
3051** or non-writable parameter
3052**
3053** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3054**
3055** See Also: MT2063_GetParam, MT2063_Open
3056**
3057** Revision History:
3058**
3059** SCR Date Author Description
3060** -------------------------------------------------------------------------
3061** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3062** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
3063** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
3064** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
3065** Split SetParam up to ACLNA / ACLNA_MAX
3066** removed ACLNA_INRC/DECR (+RF & FIF)
3067** removed GCUAUTO / BYPATNDN/UP
3068** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3069** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3070** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3071**
3072****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003073static u32 MT2063_SetParam(struct mt2063_state *pInfo,
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03003074 enum MT2063_Param param,
3075 enum MT2063_DNC_Output_Enable nValue)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003076{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003077 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003078 u8 val = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003079
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003080 switch (param) {
3081 /* crystal frequency */
3082 case MT2063_SRO_FREQ:
3083 pInfo->AS_Data.f_ref = nValue;
3084 pInfo->AS_Data.f_LO1_FracN_Avoid = 0;
3085 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
3086 pInfo->AS_Data.f_LO1_Step = nValue / 64;
3087 pInfo->AS_Data.f_if1_Center =
3088 (pInfo->AS_Data.f_ref / 8) *
3089 (pInfo->reg[MT2063_REG_FIFFC] + 640);
3090 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003091
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003092 /* minimum tuning step size */
3093 case MT2063_STEPSIZE:
3094 pInfo->AS_Data.f_LO2_Step = nValue;
3095 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003096
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003097 /* LO1 frequency */
3098 case MT2063_LO1_FREQ:
3099 {
3100 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3101 /* Capture the Divider and Numerator portions of other LO */
3102 u8 tempLO2CQ[3];
3103 u8 tempLO2C[3];
3104 u8 tmpOneShot;
3105 u32 Div, FracN;
3106 u8 restore = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003107
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003108 /* Buffer the queue for restoration later and get actual LO2 values. */
3109 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003110 MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003111 MT2063_REG_LO2CQ_1,
3112 &(tempLO2CQ[0]), 3);
3113 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003114 MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003115 MT2063_REG_LO2C_1,
3116 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003117
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003118 /* clear the one-shot bits */
3119 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
3120 tempLO2C[2] = tempLO2C[2] & 0x0F;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003121
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003122 /* only write the queue values if they are different from the actual. */
3123 if ((tempLO2CQ[0] != tempLO2C[0]) ||
3124 (tempLO2CQ[1] != tempLO2C[1]) ||
3125 (tempLO2CQ[2] != tempLO2C[2])) {
3126 /* put actual LO2 value into queue (with 0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003127 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003128 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003129 MT2063_REG_LO2CQ_1,
3130 &(tempLO2C[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003131
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003132 if (status == 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003133 /* cache the bytes just written. */
3134 pInfo->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003135 tempLO2C[0];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003136 pInfo->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003137 tempLO2C[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003138 pInfo->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003139 tempLO2C[2];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003140 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003141 restore = 1;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003142 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003143
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003144 /* Calculate the Divider and Numberator components of LO1 */
3145 status =
3146 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
3147 pInfo->AS_Data.f_ref /
3148 64,
3149 pInfo->AS_Data.f_ref);
3150 pInfo->reg[MT2063_REG_LO1CQ_1] =
3151 (u8) (Div & 0x00FF);
3152 pInfo->reg[MT2063_REG_LO1CQ_2] =
3153 (u8) (FracN);
3154 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003155 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003156 MT2063_REG_LO1CQ_1,
3157 &pInfo->
3158 reg[MT2063_REG_LO1CQ_1], 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003159
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003160 /* set the one-shot bit to load the pair of LO values */
3161 tmpOneShot = tempLO2CQ[2] | 0xE0;
3162 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003163 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003164 MT2063_REG_LO2CQ_3,
3165 &tmpOneShot, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003166
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003167 /* only restore the queue values if they were different from the actual. */
3168 if (restore) {
3169 /* put actual LO2 value into queue (0 in one-shot bits) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003170 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003171 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003172 MT2063_REG_LO2CQ_1,
3173 &(tempLO2CQ[0]), 3);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003174
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003175 /* cache the bytes just written. */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003176 pInfo->reg[MT2063_REG_LO2CQ_1] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003177 tempLO2CQ[0];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003178 pInfo->reg[MT2063_REG_LO2CQ_2] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003179 tempLO2CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003180 pInfo->reg[MT2063_REG_LO2CQ_3] =
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003181 tempLO2CQ[2];
3182 }
3183
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003184 MT2063_GetParam(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003185 MT2063_LO1_FREQ,
3186 &pInfo->AS_Data.f_LO1);
3187 }
3188 break;
3189
3190 /* LO1 minimum step size */
3191 case MT2063_LO1_STEPSIZE:
3192 pInfo->AS_Data.f_LO1_Step = nValue;
3193 break;
3194
3195 /* LO1 FracN keep-out region */
3196 case MT2063_LO1_FRACN_AVOID_PARAM:
3197 pInfo->AS_Data.f_LO1_FracN_Avoid = nValue;
3198 break;
3199
3200 /* Requested 1st IF */
3201 case MT2063_IF1_REQUEST:
3202 pInfo->AS_Data.f_if1_Request = nValue;
3203 break;
3204
3205 /* zero-IF bandwidth */
3206 case MT2063_ZIF_BW:
3207 pInfo->AS_Data.f_zif_bw = nValue;
3208 break;
3209
3210 /* LO2 frequency */
3211 case MT2063_LO2_FREQ:
3212 {
3213 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3214 /* Capture the Divider and Numerator portions of other LO */
3215 u8 tempLO1CQ[2];
3216 u8 tempLO1C[2];
3217 u32 Div2;
3218 u32 FracN2;
3219 u8 tmpOneShot;
3220 u8 restore = 0;
3221
3222 /* Buffer the queue for restoration later and get actual LO2 values. */
3223 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003224 MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003225 MT2063_REG_LO1CQ_1,
3226 &(tempLO1CQ[0]), 2);
3227 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003228 MT2063_ReadSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003229 MT2063_REG_LO1C_1,
3230 &(tempLO1C[0]), 2);
3231
3232 /* only write the queue values if they are different from the actual. */
3233 if ((tempLO1CQ[0] != tempLO1C[0])
3234 || (tempLO1CQ[1] != tempLO1C[1])) {
3235 /* put actual LO1 value into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003236 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003237 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003238 MT2063_REG_LO1CQ_1,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003239 &(tempLO1C[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003240
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003241 /* cache the bytes just written. */
3242 pInfo->reg[MT2063_REG_LO1CQ_1] =
3243 tempLO1C[0];
3244 pInfo->reg[MT2063_REG_LO1CQ_2] =
3245 tempLO1C[1];
3246 restore = 1;
3247 }
3248
3249 /* Calculate the Divider and Numberator components of LO2 */
3250 status =
3251 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
3252 pInfo->AS_Data.f_ref /
3253 8191,
3254 pInfo->AS_Data.f_ref);
3255 pInfo->reg[MT2063_REG_LO2CQ_1] =
3256 (u8) ((Div2 << 1) |
3257 ((FracN2 >> 12) & 0x01)) & 0xFF;
3258 pInfo->reg[MT2063_REG_LO2CQ_2] =
3259 (u8) ((FracN2 >> 4) & 0xFF);
3260 pInfo->reg[MT2063_REG_LO2CQ_3] =
3261 (u8) ((FracN2 & 0x0F));
3262 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003263 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003264 MT2063_REG_LO1CQ_1,
3265 &pInfo->
3266 reg[MT2063_REG_LO1CQ_1], 3);
3267
3268 /* set the one-shot bit to load the LO values */
3269 tmpOneShot =
3270 pInfo->reg[MT2063_REG_LO2CQ_3] | 0xE0;
3271 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003272 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003273 MT2063_REG_LO2CQ_3,
3274 &tmpOneShot, 1);
3275
3276 /* only restore LO1 queue value if they were different from the actual. */
3277 if (restore) {
3278 /* put previous LO1 queue value back into queue */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003279 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003280 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003281 MT2063_REG_LO1CQ_1,
3282 &(tempLO1CQ[0]), 2);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003283
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003284 /* cache the bytes just written. */
3285 pInfo->reg[MT2063_REG_LO1CQ_1] =
3286 tempLO1CQ[0];
3287 pInfo->reg[MT2063_REG_LO1CQ_2] =
3288 tempLO1CQ[1];
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003289 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003290
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003291 MT2063_GetParam(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003292 MT2063_LO2_FREQ,
3293 &pInfo->AS_Data.f_LO2);
3294 }
3295 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003296
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003297 /* LO2 minimum step size */
3298 case MT2063_LO2_STEPSIZE:
3299 pInfo->AS_Data.f_LO2_Step = nValue;
3300 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003301
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003302 /* LO2 FracN keep-out region */
3303 case MT2063_LO2_FRACN_AVOID:
3304 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue;
3305 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003306
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003307 /* output center frequency */
3308 case MT2063_OUTPUT_FREQ:
3309 pInfo->AS_Data.f_out = nValue;
3310 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003311
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003312 /* output bandwidth */
3313 case MT2063_OUTPUT_BW:
3314 pInfo->AS_Data.f_out_bw = nValue + 750000;
3315 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003316
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003317 /* min inter-tuner LO separation */
3318 case MT2063_LO_SEPARATION:
3319 pInfo->AS_Data.f_min_LO_Separation = nValue;
3320 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003321
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003322 /* max # of intra-tuner harmonics */
3323 case MT2063_MAX_HARM1:
3324 pInfo->AS_Data.maxH1 = nValue;
3325 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003326
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003327 /* max # of inter-tuner harmonics */
3328 case MT2063_MAX_HARM2:
3329 pInfo->AS_Data.maxH2 = nValue;
3330 break;
3331
3332 case MT2063_RCVR_MODE:
3333 status |=
3334 MT2063_SetReceiverMode(pInfo,
3335 (enum MT2063_RCVR_MODES)
3336 nValue);
3337 break;
3338
3339 /* Set LNA Rin -- nValue is desired value */
3340 case MT2063_LNA_RIN:
3341 val =
3342 (pInfo->
3343 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
3344 (nValue & 0x03);
3345 if (pInfo->reg[MT2063_REG_CTRL_2C] != val) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003346 status |=
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003347 MT2063_SetReg(pInfo, MT2063_REG_CTRL_2C,
3348 val);
3349 }
3350 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003351
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003352 /* Set target power level at LNA -- nValue is desired value */
3353 case MT2063_LNA_TGT:
3354 val =
3355 (pInfo->
3356 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
3357 (nValue & 0x3F);
3358 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
3359 status |=
3360 MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT,
3361 val);
3362 }
3363 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003364
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003365 /* Set target power level at PD1 -- nValue is desired value */
3366 case MT2063_PD1_TGT:
3367 val =
3368 (pInfo->
3369 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
3370 (nValue & 0x3F);
3371 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
3372 status |=
3373 MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT,
3374 val);
3375 }
3376 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003377
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003378 /* Set target power level at PD2 -- nValue is desired value */
3379 case MT2063_PD2_TGT:
3380 val =
3381 (pInfo->
3382 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
3383 (nValue & 0x3F);
3384 if (pInfo->reg[MT2063_REG_PD2_TGT] != val) {
3385 status |=
3386 MT2063_SetReg(pInfo, MT2063_REG_PD2_TGT,
3387 val);
3388 }
3389 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003390
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003391 /* Set LNA atten limit -- nValue is desired value */
3392 case MT2063_ACLNA_MAX:
3393 val =
3394 (pInfo->
3395 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
3396 &
3397 0x1F);
3398 if (pInfo->reg[MT2063_REG_LNA_OV] != val) {
3399 status |=
3400 MT2063_SetReg(pInfo, MT2063_REG_LNA_OV,
3401 val);
3402 }
3403 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003404
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003405 /* Set RF atten limit -- nValue is desired value */
3406 case MT2063_ACRF_MAX:
3407 val =
3408 (pInfo->
3409 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
3410 &
3411 0x1F);
3412 if (pInfo->reg[MT2063_REG_RF_OV] != val) {
3413 status |=
3414 MT2063_SetReg(pInfo, MT2063_REG_RF_OV, val);
3415 }
3416 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003417
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003418 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
3419 case MT2063_ACFIF_MAX:
3420 if (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3
3421 && nValue > 5)
3422 nValue = 5;
3423 val =
3424 (pInfo->
3425 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
3426 &
3427 0x1F);
3428 if (pInfo->reg[MT2063_REG_FIF_OV] != val) {
3429 status |=
3430 MT2063_SetReg(pInfo, MT2063_REG_FIF_OV,
3431 val);
3432 }
3433 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003434
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003435 case MT2063_DNC_OUTPUT_ENABLE:
3436 /* selects, which DNC output is used */
Mauro Carvalho Chehab29a0a4f2011-07-20 23:44:10 -03003437 switch (nValue) {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003438 case MT2063_DNC_NONE:
3439 {
3440 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3441 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3442 val)
3443 status |=
3444 MT2063_SetReg(pInfo,
3445 MT2063_REG_DNC_GAIN,
3446 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003447
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003448 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3449 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3450 val)
3451 status |=
3452 MT2063_SetReg(pInfo,
3453 MT2063_REG_VGA_GAIN,
3454 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003455
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003456 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3457 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3458 val)
3459 status |=
3460 MT2063_SetReg(pInfo,
3461 MT2063_REG_RSVD_20,
3462 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003463
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003464 break;
3465 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003466 case MT2063_DNC_1:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003467 {
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003468 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3469 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3470 val)
3471 status |=
3472 MT2063_SetReg(pInfo,
3473 MT2063_REG_DNC_GAIN,
3474 val);
3475
3476 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3477 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3478 val)
3479 status |=
3480 MT2063_SetReg(pInfo,
3481 MT2063_REG_VGA_GAIN,
3482 val);
3483
3484 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3485 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3486 val)
3487 status |=
3488 MT2063_SetReg(pInfo,
3489 MT2063_REG_RSVD_20,
3490 val);
3491
3492 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003493 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003494 case MT2063_DNC_2:
3495 {
3496 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3497 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3498 val)
3499 status |=
3500 MT2063_SetReg(pInfo,
3501 MT2063_REG_DNC_GAIN,
3502 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003503
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003504 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3505 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3506 val)
3507 status |=
3508 MT2063_SetReg(pInfo,
3509 MT2063_REG_VGA_GAIN,
3510 val);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003511
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003512 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3513 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3514 val)
3515 status |=
3516 MT2063_SetReg(pInfo,
3517 MT2063_REG_RSVD_20,
3518 val);
3519
3520 break;
3521 }
3522 case MT2063_DNC_BOTH:
3523 {
3524 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3525 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3526 val)
3527 status |=
3528 MT2063_SetReg(pInfo,
3529 MT2063_REG_DNC_GAIN,
3530 val);
3531
3532 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3533 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3534 val)
3535 status |=
3536 MT2063_SetReg(pInfo,
3537 MT2063_REG_VGA_GAIN,
3538 val);
3539
3540 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3541 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3542 val)
3543 status |=
3544 MT2063_SetReg(pInfo,
3545 MT2063_REG_RSVD_20,
3546 val);
3547
3548 break;
3549 }
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003550 default:
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003551 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003552 }
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003553 break;
3554
3555 case MT2063_VGAGC:
3556 /* Set VGA gain code */
3557 val =
3558 (pInfo->
3559 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
3560 ((nValue & 0x03) << 2);
3561 if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) {
3562 status |=
3563 MT2063_SetReg(pInfo, MT2063_REG_VGA_GAIN,
3564 val);
3565 }
3566 break;
3567
3568 case MT2063_VGAOI:
3569 /* Set VGA bias current */
3570 val =
3571 (pInfo->
3572 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
3573 (nValue & 0x07);
3574 if (pInfo->reg[MT2063_REG_RSVD_31] != val) {
3575 status |=
3576 MT2063_SetReg(pInfo, MT2063_REG_RSVD_31,
3577 val);
3578 }
3579 break;
3580
3581 case MT2063_TAGC:
3582 /* Set TAGC */
3583 val =
3584 (pInfo->
3585 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
3586 (nValue & 0x03);
3587 if (pInfo->reg[MT2063_REG_RSVD_1E] != val) {
3588 status |=
3589 MT2063_SetReg(pInfo, MT2063_REG_RSVD_1E,
3590 val);
3591 }
3592 break;
3593
3594 case MT2063_AMPGC:
3595 /* Set Amp gain code */
3596 val =
3597 (pInfo->
3598 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
3599 (nValue & 0x03);
3600 if (pInfo->reg[MT2063_REG_TEMP_SEL] != val) {
3601 status |=
3602 MT2063_SetReg(pInfo, MT2063_REG_TEMP_SEL,
3603 val);
3604 }
3605 break;
3606
3607 /* Avoid DECT Frequencies */
3608 case MT2063_AVOID_DECT:
3609 {
3610 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3611 (enum MT2063_DECT_Avoid_Type)nValue;
3612 if ((newAvoidSetting >=
3613 MT2063_NO_DECT_AVOIDANCE)
3614 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
3615 pInfo->AS_Data.avoidDECT =
3616 newAvoidSetting;
3617 }
3618 }
3619 break;
3620
3621 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3622 case MT2063_CTFILT_SW:
3623 pInfo->ctfilt_sw = (nValue & 0x01);
3624 break;
3625
3626 /* These parameters are read-only */
3627 case MT2063_IC_ADDR:
3628 case MT2063_MAX_OPEN:
3629 case MT2063_NUM_OPEN:
3630 case MT2063_INPUT_FREQ:
3631 case MT2063_IF1_ACTUAL:
3632 case MT2063_IF1_CENTER:
3633 case MT2063_IF1_BW:
3634 case MT2063_AS_ALG:
3635 case MT2063_EXCL_ZONES:
3636 case MT2063_SPUR_AVOIDED:
3637 case MT2063_NUM_SPURS:
3638 case MT2063_SPUR_PRESENT:
3639 case MT2063_ACLNA:
3640 case MT2063_ACRF:
3641 case MT2063_ACFIF:
3642 case MT2063_EOP:
3643 default:
3644 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003645 }
3646 return (status);
3647}
3648
3649/****************************************************************************
3650**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003651** Name: MT2063_ClearPowerMaskBits
3652**
3653** Description: Clears the power-down mask bits for various sections of
3654** the MT2063
3655**
3656** Parameters: h - Tuner handle (returned by MT2063_Open)
3657** Bits - Mask bits to be cleared.
3658**
3659** See definition of MT2063_Mask_Bits type for description
3660** of each of the power bits.
3661**
3662** Returns: status:
3663** MT_OK - No errors
3664** MT_INV_HANDLE - Invalid tuner handle
3665** MT_COMM_ERR - Serial bus communications error
3666**
3667** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3668**
3669** Revision History:
3670**
3671** SCR Date Author Description
3672** -------------------------------------------------------------------------
3673** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3674**
3675****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003676static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *pInfo, enum MT2063_Mask_Bits Bits)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003677{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003678 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003679
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003680 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3681 if ((Bits & 0xFF00) != 0) {
3682 pInfo->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
3683 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003684 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003685 MT2063_REG_PWR_2,
3686 &pInfo->reg[MT2063_REG_PWR_2], 1);
3687 }
3688 if ((Bits & 0xFF) != 0) {
3689 pInfo->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
3690 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003691 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003692 MT2063_REG_PWR_1,
3693 &pInfo->reg[MT2063_REG_PWR_1], 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003694 }
3695
3696 return (status);
3697}
3698
3699/****************************************************************************
3700**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003701** Name: MT2063_SoftwareShutdown
3702**
3703** Description: Enables or disables software shutdown function. When
3704** Shutdown==1, any section whose power mask is set will be
3705** shutdown.
3706**
3707** Parameters: h - Tuner handle (returned by MT2063_Open)
3708** Shutdown - 1 = shutdown the masked sections, otherwise
3709** power all sections on
3710**
3711** Returns: status:
3712** MT_OK - No errors
3713** MT_INV_HANDLE - Invalid tuner handle
3714** MT_COMM_ERR - Serial bus communications error
3715**
3716** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3717**
3718** Revision History:
3719**
3720** SCR Date Author Description
3721** -------------------------------------------------------------------------
3722** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3723** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3724** correct wakeup of the LNA
3725**
3726****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003727static u32 MT2063_SoftwareShutdown(struct mt2063_state *pInfo, u8 Shutdown)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003728{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003729 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003730
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003731 if (Shutdown == 1)
3732 pInfo->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
3733 else
3734 pInfo->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003735
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003736 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003737 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003738 MT2063_REG_PWR_1,
3739 &pInfo->reg[MT2063_REG_PWR_1], 1);
3740
3741 if (Shutdown != 1) {
3742 pInfo->reg[MT2063_REG_BYP_CTRL] =
3743 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003744 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003745 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003746 MT2063_REG_BYP_CTRL,
3747 &pInfo->reg[MT2063_REG_BYP_CTRL],
3748 1);
3749 pInfo->reg[MT2063_REG_BYP_CTRL] =
3750 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F);
3751 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003752 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003753 MT2063_REG_BYP_CTRL,
3754 &pInfo->reg[MT2063_REG_BYP_CTRL],
3755 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003756 }
3757
3758 return (status);
3759}
3760
3761/****************************************************************************
3762**
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003763** Name: MT2063_SetReg
3764**
3765** Description: Sets an MT2063 register.
3766**
3767** Parameters: h - Tuner handle (returned by MT2063_Open)
3768** reg - MT2063 register/subaddress location
3769** val - MT2063 register/subaddress value
3770**
3771** Returns: status:
3772** MT_OK - No errors
3773** MT_COMM_ERR - Serial bus communications error
3774** MT_INV_HANDLE - Invalid tuner handle
3775** MT_ARG_RANGE - Argument out of range
3776**
3777** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3778**
3779** Use this function if you need to override a default
3780** register value
3781**
3782** Revision History:
3783**
3784** SCR Date Author Description
3785** -------------------------------------------------------------------------
3786** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3787**
3788****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003789static u32 MT2063_SetReg(struct mt2063_state *pInfo, u8 reg, u8 val)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003790{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003791 u32 status = 0; /* Status to be returned */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003792
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003793 if (reg >= MT2063_REG_END_REGS)
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003794 status |= -ERANGE;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003795
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003796 status = MT2063_WriteSub(pInfo, reg, &val,
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03003797 1);
3798 if (status >= 0)
3799 pInfo->reg[reg] = val;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003800
3801 return (status);
3802}
3803
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003804static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003805{
3806 return f_ref * (f_LO / f_ref)
3807 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
3808}
3809
3810/****************************************************************************
3811**
3812** Name: fLO_FractionalTerm
3813**
3814** Description: Calculates the portion contributed by FracN / denom.
3815**
3816** This function preserves maximum precision without
3817** risk of overflow. It accurately calculates
3818** f_ref * num / denom to within 1 HZ with fixed math.
3819**
3820** Parameters: num - Fractional portion of the multiplier
3821** denom - denominator portion of the ratio
3822** This routine successfully handles denom values
3823** up to and including 2^18.
3824** f_Ref - SRO frequency. This calculation handles
3825** f_ref as two separate 14-bit fields.
3826** Therefore, a maximum value of 2^28-1
3827** may safely be used for f_ref. This is
3828** the genesis of the magic number "14" and the
3829** magic mask value of 0x03FFF.
3830**
3831** Returns: f_ref * num / denom
3832**
3833** Revision History:
3834**
3835** SCR Date Author Description
3836** -------------------------------------------------------------------------
3837** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3838**
3839****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003840static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
3841 u32 num, u32 denom)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003842{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003843 u32 t1 = (f_ref >> 14) * num;
3844 u32 term1 = t1 / denom;
3845 u32 loss = t1 % denom;
3846 u32 term2 =
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003847 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
3848 return ((term1 << 14) + term2);
3849}
3850
3851/****************************************************************************
3852**
3853** Name: CalcLO1Mult
3854**
3855** Description: Calculates Integer divider value and the numerator
3856** value for a FracN PLL.
3857**
3858** This function assumes that the f_LO and f_Ref are
3859** evenly divisible by f_LO_Step.
3860**
3861** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3862** FracN - OUTPUT: Fractional portion of the multiplier
3863** f_LO - desired LO frequency.
3864** f_LO_Step - Minimum step size for the LO (in Hz).
3865** f_Ref - SRO frequency.
3866** f_Avoid - Range of PLL frequencies to avoid near
3867** integer multiples of f_Ref (in Hz).
3868**
3869** Returns: Recalculated LO frequency.
3870**
3871** Revision History:
3872**
3873** SCR Date Author Description
3874** -------------------------------------------------------------------------
3875** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3876**
3877****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003878static u32 MT2063_CalcLO1Mult(u32 * Div,
3879 u32 * FracN,
3880 u32 f_LO,
3881 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003882{
3883 /* Calculate the whole number portion of the divider */
3884 *Div = f_LO / f_Ref;
3885
3886 /* Calculate the numerator value (round to nearest f_LO_Step) */
3887 *FracN =
3888 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3889 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3890
3891 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
3892}
3893
3894/****************************************************************************
3895**
3896** Name: CalcLO2Mult
3897**
3898** Description: Calculates Integer divider value and the numerator
3899** value for a FracN PLL.
3900**
3901** This function assumes that the f_LO and f_Ref are
3902** evenly divisible by f_LO_Step.
3903**
3904** Parameters: Div - OUTPUT: Whole number portion of the multiplier
3905** FracN - OUTPUT: Fractional portion of the multiplier
3906** f_LO - desired LO frequency.
3907** f_LO_Step - Minimum step size for the LO (in Hz).
3908** f_Ref - SRO frequency.
3909** f_Avoid - Range of PLL frequencies to avoid near
3910** integer multiples of f_Ref (in Hz).
3911**
3912** Returns: Recalculated LO frequency.
3913**
3914** Revision History:
3915**
3916** SCR Date Author Description
3917** -------------------------------------------------------------------------
3918** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3919**
3920****************************************************************************/
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003921static u32 MT2063_CalcLO2Mult(u32 * Div,
3922 u32 * FracN,
3923 u32 f_LO,
3924 u32 f_LO_Step, u32 f_Ref)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003925{
3926 /* Calculate the whole number portion of the divider */
3927 *Div = f_LO / f_Ref;
3928
3929 /* Calculate the numerator value (round to nearest f_LO_Step) */
3930 *FracN =
3931 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
3932 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
3933
3934 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
3935 8191);
3936}
3937
3938/****************************************************************************
3939**
3940** Name: FindClearTuneFilter
3941**
3942** Description: Calculate the corrrect ClearTune filter to be used for
3943** a given input frequency.
3944**
3945** Parameters: pInfo - ptr to tuner data structure
3946** f_in - RF input center frequency (in Hz).
3947**
3948** Returns: ClearTune filter number (0-31)
3949**
3950** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
3951**
3952** Revision History:
3953**
3954** SCR Date Author Description
3955** -------------------------------------------------------------------------
3956** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
3957** cross-over frequency values.
3958**
3959****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03003960static u32 FindClearTuneFilter(struct mt2063_state *pInfo, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003961{
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03003962 u32 RFBand;
3963 u32 idx; /* index loop */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03003964
3965 /*
3966 ** Find RF Band setting
3967 */
3968 RFBand = 31; /* def when f_in > all */
3969 for (idx = 0; idx < 31; ++idx) {
3970 if (pInfo->CTFiltMax[idx] >= f_in) {
3971 RFBand = idx;
3972 break;
3973 }
3974 }
3975 return (RFBand);
3976}
3977
3978/****************************************************************************
3979**
3980** Name: MT2063_Tune
3981**
3982** Description: Change the tuner's tuned frequency to RFin.
3983**
3984** Parameters: h - Open handle to the tuner (from MT2063_Open).
3985** f_in - RF input center frequency (in Hz).
3986**
3987** Returns: status:
3988** MT_OK - No errors
3989** MT_INV_HANDLE - Invalid tuner handle
3990** MT_UPC_UNLOCK - Upconverter PLL unlocked
3991** MT_DNC_UNLOCK - Downconverter PLL unlocked
3992** MT_COMM_ERR - Serial bus communications error
3993** MT_SPUR_CNT_MASK - Count of avoided LO spurs
3994** MT_SPUR_PRESENT - LO spur possible in output
3995** MT_FIN_RANGE - Input freq out of range
3996** MT_FOUT_RANGE - Output freq out of range
3997** MT_UPC_RANGE - Upconverter freq out of range
3998** MT_DNC_RANGE - Downconverter freq out of range
3999**
4000** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
4001**
4002** MT_ReadSub - Read data from the two-wire serial bus
4003** MT_WriteSub - Write data to the two-wire serial bus
4004** MT_Sleep - Delay execution for x milliseconds
4005** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
4006**
4007** Revision History:
4008**
4009** SCR Date Author Description
4010** -------------------------------------------------------------------------
4011** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4012** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
4013** cross-over frequency values.
4014** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
4015** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
4016** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
4017**
4018****************************************************************************/
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004019static u32 MT2063_Tune(struct mt2063_state *pInfo, u32 f_in)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004020{ /* RF input center frequency */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004021
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004022 u32 status = 0; /* status of operation */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004023 u32 LO1; /* 1st LO register value */
4024 u32 Num1; /* Numerator for LO1 reg. value */
4025 u32 f_IF1; /* 1st IF requested */
4026 u32 LO2; /* 2nd LO register value */
4027 u32 Num2; /* Numerator for LO2 reg. value */
4028 u32 ofLO1, ofLO2; /* last time's LO frequencies */
4029 u32 ofin, ofout; /* last time's I/O frequencies */
4030 u8 fiffc = 0x80; /* FIFF center freq from tuner */
4031 u32 fiffof; /* Offset from FIFF center freq */
4032 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
4033 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
4034 u8 val;
4035 u32 RFBand;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004036
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004037 /* Check the input and output frequency ranges */
4038 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004039 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004040
4041 if ((pInfo->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
4042 || (pInfo->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004043 return -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004044
4045 /*
4046 ** Save original LO1 and LO2 register values
4047 */
4048 ofLO1 = pInfo->AS_Data.f_LO1;
4049 ofLO2 = pInfo->AS_Data.f_LO2;
4050 ofin = pInfo->AS_Data.f_in;
4051 ofout = pInfo->AS_Data.f_out;
4052
4053 /*
4054 ** Find and set RF Band setting
4055 */
4056 if (pInfo->ctfilt_sw == 1) {
4057 val = (pInfo->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
4058 if (pInfo->reg[MT2063_REG_CTUNE_CTRL] != val) {
4059 status |=
4060 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_CTRL, val);
4061 }
4062 val = pInfo->reg[MT2063_REG_CTUNE_OV];
4063 RFBand = FindClearTuneFilter(pInfo, f_in);
4064 pInfo->reg[MT2063_REG_CTUNE_OV] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004065 (u8) ((pInfo->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004066 | RFBand);
4067 if (pInfo->reg[MT2063_REG_CTUNE_OV] != val) {
4068 status |=
4069 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_OV, val);
4070 }
4071 }
4072
4073 /*
4074 ** Read the FIFF Center Frequency from the tuner
4075 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004076 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004077 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004078 MT2063_ReadSub(pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004079 MT2063_REG_FIFFC,
4080 &pInfo->reg[MT2063_REG_FIFFC], 1);
4081 fiffc = pInfo->reg[MT2063_REG_FIFFC];
4082 }
4083 /*
4084 ** Assign in the requested values
4085 */
4086 pInfo->AS_Data.f_in = f_in;
4087 /* Request a 1st IF such that LO1 is on a step size */
4088 pInfo->AS_Data.f_if1_Request =
4089 MT2063_Round_fLO(pInfo->AS_Data.f_if1_Request + f_in,
4090 pInfo->AS_Data.f_LO1_Step,
4091 pInfo->AS_Data.f_ref) - f_in;
4092
4093 /*
4094 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
4095 ** desired LO1 frequency
4096 */
4097 MT2063_ResetExclZones(&pInfo->AS_Data);
4098
4099 f_IF1 = MT2063_ChooseFirstIF(&pInfo->AS_Data);
4100
4101 pInfo->AS_Data.f_LO1 =
4102 MT2063_Round_fLO(f_IF1 + f_in, pInfo->AS_Data.f_LO1_Step,
4103 pInfo->AS_Data.f_ref);
4104
4105 pInfo->AS_Data.f_LO2 =
4106 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4107 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4108
4109 /*
4110 ** Check for any LO spurs in the output bandwidth and adjust
4111 ** the LO settings to avoid them if needed
4112 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004113 status |= MT2063_AvoidSpurs(pInfo, &pInfo->AS_Data);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004114 /*
4115 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
4116 ** Recalculate the LO frequencies and the values to be placed
4117 ** in the tuning registers.
4118 */
4119 pInfo->AS_Data.f_LO1 =
4120 MT2063_CalcLO1Mult(&LO1, &Num1, pInfo->AS_Data.f_LO1,
4121 pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref);
4122 pInfo->AS_Data.f_LO2 =
4123 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4124 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4125 pInfo->AS_Data.f_LO2 =
4126 MT2063_CalcLO2Mult(&LO2, &Num2, pInfo->AS_Data.f_LO2,
4127 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4128
4129 /*
4130 ** Check the upconverter and downconverter frequency ranges
4131 */
4132 if ((pInfo->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
4133 || (pInfo->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
4134 status |= MT2063_UPC_RANGE;
4135 if ((pInfo->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
4136 || (pInfo->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
4137 status |= MT2063_DNC_RANGE;
4138 /* LO2 Lock bit was in a different place for B0 version */
4139 if (pInfo->tuner_id == MT2063_B0)
4140 LO2LK = 0x40;
4141
4142 /*
4143 ** If we have the same LO frequencies and we're already locked,
4144 ** then skip re-programming the LO registers.
4145 */
4146 if ((ofLO1 != pInfo->AS_Data.f_LO1)
4147 || (ofLO2 != pInfo->AS_Data.f_LO2)
4148 || ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
4149 (LO1LK | LO2LK))) {
4150 /*
4151 ** Calculate the FIFFOF register value
4152 **
4153 ** IF1_Actual
4154 ** FIFFOF = ------------ - 8 * FIFFC - 4992
4155 ** f_ref/64
4156 */
4157 fiffof =
4158 (pInfo->AS_Data.f_LO1 -
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004159 f_in) / (pInfo->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004160 4992;
4161 if (fiffof > 0xFF)
4162 fiffof = 0xFF;
4163
4164 /*
4165 ** Place all of the calculated values into the local tuner
4166 ** register fields.
4167 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004168 if (status >= 0) {
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004169 pInfo->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
4170 pInfo->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
4171 pInfo->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004172 |(Num2 >> 12)); /* NUM2q (hi) */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004173 pInfo->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
4174 pInfo->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004175
4176 /*
4177 ** Now write out the computed register values
4178 ** IMPORTANT: There is a required order for writing
4179 ** (0x05 must follow all the others).
4180 */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004181 status |= MT2063_WriteSub(pInfo, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004182 if (pInfo->tuner_id == MT2063_B0) {
4183 /* Re-write the one-shot bits to trigger the tune operation */
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004184 status |= MT2063_WriteSub(pInfo, MT2063_REG_LO2CQ_3, &pInfo->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004185 }
4186 /* Write out the FIFF offset only if it's changing */
4187 if (pInfo->reg[MT2063_REG_FIFF_OFFSET] !=
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004188 (u8) fiffof) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004189 pInfo->reg[MT2063_REG_FIFF_OFFSET] =
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004190 (u8) fiffof;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004191 status |=
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004192 MT2063_WriteSub(pInfo,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004193 MT2063_REG_FIFF_OFFSET,
4194 &pInfo->
4195 reg[MT2063_REG_FIFF_OFFSET],
4196 1);
4197 }
4198 }
4199
4200 /*
4201 ** Check for LO's locking
4202 */
4203
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004204 if (status >= 0) {
4205 status |= MT2063_GetLocked(pInfo);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004206 }
4207 /*
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004208 ** If we locked OK, assign calculated data to mt2063_state structure
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004209 */
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004210 if (status >= 0) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004211 pInfo->f_IF1_actual = pInfo->AS_Data.f_LO1 - f_in;
4212 }
4213 }
4214
4215 return (status);
4216}
4217
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03004218static u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004219 enum MTTune_atv_standard tv_type)
4220{
4221
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004222 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004223
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004224 s32 pict_car = 0;
4225 s32 pict2chanb_vsb = 0;
4226 s32 pict2chanb_snd = 0;
4227 s32 pict2snd1 = 0;
4228 s32 pict2snd2 = 0;
4229 s32 ch_bw = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004230
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004231 s32 if_mid = 0;
4232 s32 rcvr_mode = 0;
4233 u32 mode_get = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004234
4235 switch (tv_type) {
4236 case MTTUNEA_PAL_B:{
4237 pict_car = 38900000;
4238 ch_bw = 8000000;
4239 pict2chanb_vsb = -1250000;
4240 pict2snd1 = 5500000;
4241 pict2snd2 = 5742000;
4242 rcvr_mode = 1;
4243 break;
4244 }
4245 case MTTUNEA_PAL_G:{
4246 pict_car = 38900000;
4247 ch_bw = 7000000;
4248 pict2chanb_vsb = -1250000;
4249 pict2snd1 = 5500000;
4250 pict2snd2 = 0;
4251 rcvr_mode = 1;
4252 break;
4253 }
4254 case MTTUNEA_PAL_I:{
4255 pict_car = 38900000;
4256 ch_bw = 8000000;
4257 pict2chanb_vsb = -1250000;
4258 pict2snd1 = 6000000;
4259 pict2snd2 = 0;
4260 rcvr_mode = 1;
4261 break;
4262 }
4263 case MTTUNEA_PAL_L:{
4264 pict_car = 38900000;
4265 ch_bw = 8000000;
4266 pict2chanb_vsb = -1250000;
4267 pict2snd1 = 6500000;
4268 pict2snd2 = 0;
4269 rcvr_mode = 1;
4270 break;
4271 }
4272 case MTTUNEA_PAL_MN:{
4273 pict_car = 38900000;
4274 ch_bw = 6000000;
4275 pict2chanb_vsb = -1250000;
4276 pict2snd1 = 4500000;
4277 pict2snd2 = 0;
4278 rcvr_mode = 1;
4279 break;
4280 }
4281 case MTTUNEA_PAL_DK:{
4282 pict_car = 38900000;
4283 ch_bw = 8000000;
4284 pict2chanb_vsb = -1250000;
4285 pict2snd1 = 6500000;
4286 pict2snd2 = 0;
4287 rcvr_mode = 1;
4288 break;
4289 }
4290 case MTTUNEA_DIGITAL:{
4291 pict_car = 36125000;
4292 ch_bw = 8000000;
4293 pict2chanb_vsb = -(ch_bw / 2);
4294 pict2snd1 = 0;
4295 pict2snd2 = 0;
4296 rcvr_mode = 2;
4297 break;
4298 }
4299 case MTTUNEA_FMRADIO:{
4300 pict_car = 38900000;
4301 ch_bw = 8000000;
4302 pict2chanb_vsb = -(ch_bw / 2);
4303 pict2snd1 = 0;
4304 pict2snd2 = 0;
4305 rcvr_mode = 4;
4306 //f_in -= 2900000;
4307 break;
4308 }
4309 case MTTUNEA_DVBC:{
4310 pict_car = 36125000;
4311 ch_bw = 8000000;
4312 pict2chanb_vsb = -(ch_bw / 2);
4313 pict2snd1 = 0;
4314 pict2snd2 = 0;
4315 rcvr_mode = MT2063_CABLE_QAM;
4316 break;
4317 }
4318 case MTTUNEA_DVBT:{
4319 pict_car = 36125000;
4320 ch_bw = bw_in; //8000000
4321 pict2chanb_vsb = -(ch_bw / 2);
4322 pict2snd1 = 0;
4323 pict2snd2 = 0;
4324 rcvr_mode = MT2063_OFFAIR_COFDM;
4325 break;
4326 }
4327 case MTTUNEA_UNKNOWN:
4328 break;
4329 default:
4330 break;
4331 }
4332
4333 pict2chanb_snd = pict2chanb_vsb - ch_bw;
4334 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
4335
4336 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
4337 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
4338 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
4339 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4340
4341 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
4342 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
4343 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4344
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004345 return (u32) status;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004346}
4347
4348static int mt2063_init(struct dvb_frontend *fe)
4349{
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004350 u32 status = -EINVAL;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004351 struct mt2063_state *state = fe->tuner_priv;
4352
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004353 status = MT2063_Open(fe);
4354 status |= MT2063_SoftwareShutdown(state, 1);
4355 status |= MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004356
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004357 if (0 != status) {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004358 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
4359 status);
4360 return -1;
4361 }
4362
4363 return 0;
4364}
4365
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004366static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
4367{
4368 int rc = 0;
4369
4370 //get tuner lock status
4371
4372 return rc;
4373}
4374
4375static int mt2063_get_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004376 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004377{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004378 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004379
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004380 switch (param) {
4381 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004382 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004383 break;
4384 case DVBFE_TUNER_TUNERSTEP:
4385 break;
4386 case DVBFE_TUNER_IFFREQ:
4387 break;
4388 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004389 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004390 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004391 case DVBFE_TUNER_REFCLOCK:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004392 tunstate->refclock = (u32) MT2063_GetLocked(state);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004393 break;
4394 default:
4395 break;
4396 }
4397
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004398 return (int)tunstate->refclock;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004399}
4400
4401static int mt2063_set_state(struct dvb_frontend *fe,
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004402 enum tuner_param param, struct tuner_state *tunstate)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004403{
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004404 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehabfdf77a42011-07-20 22:55:25 -03004405 u32 status = 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004406
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004407 switch (param) {
4408 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004409 //set frequency
4410
4411 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004412 MT_Tune_atv(state,
4413 tunstate->frequency, tunstate->bandwidth,
4414 state->tv_type);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004415
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004416 state->frequency = tunstate->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004417 break;
4418 case DVBFE_TUNER_TUNERSTEP:
4419 break;
4420 case DVBFE_TUNER_IFFREQ:
4421 break;
4422 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004423 //set bandwidth
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004424 state->bandwidth = tunstate->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004425 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004426 case DVBFE_TUNER_REFCLOCK:
4427
4428 break;
4429 case DVBFE_TUNER_OPEN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004430 status = MT2063_Open(fe);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004431 break;
4432 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004433 status = MT2063_SoftwareShutdown(state, 1);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004434 break;
4435 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
4436 status =
Mauro Carvalho Chehab51f0f7b2011-07-21 02:24:18 -03004437 MT2063_ClearPowerMaskBits(state,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004438 MT2063_ALL_SD);
4439 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004440 default:
4441 break;
4442 }
4443
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004444 return (int)status;
4445}
4446
4447static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004448{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004449 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004450
4451 fe->tuner_priv = NULL;
4452 kfree(state);
4453
4454 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004455}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004456
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004457static struct dvb_tuner_ops mt2063_ops = {
4458 .info = {
4459 .name = "MT2063 Silicon Tuner",
4460 .frequency_min = 45000000,
4461 .frequency_max = 850000000,
4462 .frequency_step = 0,
4463 },
4464
4465 .init = mt2063_init,
Mauro Carvalho Chehabbf975552011-07-20 21:43:30 -03004466 .sleep = MT2063_Sleep,
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004467 .get_status = mt2063_get_status,
4468 .get_state = mt2063_get_state,
4469 .set_state = mt2063_set_state,
4470 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004471};
4472
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004473struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4474 struct mt2063_config *config,
4475 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004476{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004477 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004478
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004479 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004480 if (state == NULL)
4481 goto error;
4482
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004483 state->config = config;
4484 state->i2c = i2c;
4485 state->frontend = fe;
4486 state->reference = config->refclock / 1000; /* kHz */
Mauro Carvalho Chehabcfde8922011-07-20 21:01:48 -03004487 state->MT2063_init = false;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004488 fe->tuner_priv = state;
4489 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004490
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004491 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004492 return fe;
4493
4494error:
4495 kfree(state);
4496 return NULL;
4497}
4498
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004499EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004500MODULE_PARM_DESC(verbose, "Set Verbosity level");
4501
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004502MODULE_AUTHOR("Henry");
4503MODULE_DESCRIPTION("MT2063 Silicon tuner");
4504MODULE_LICENSE("GPL");