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