blob: 1d36e51c40484aab46e99a159d2c691303bcac55 [file] [log] [blame]
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03002#include <linux/init.h>
3#include <linux/kernel.h>
4#include <linux/module.h>
5#include <linux/string.h>
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03006
7#include "drxk_type.h"
8#include "mt2063.h"
9
10/* Version of this module */
11#define MT2063_VERSION 10018 /* Version 01.18 */
12
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -030013static unsigned int verbose;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -030014module_param(verbose, int, 0644);
15
Mauro Carvalho Chehab0ff48432011-07-20 20:21:42 -030016
17/*****************/
18/* From drivers/media/common/tuners/mt2063_cfg.h */
19
20static unsigned int mt2063_setTune(struct dvb_frontend *fe, UData_t f_in,
21 UData_t bw_in,
22 enum MTTune_atv_standard tv_type)
23{
24 //return (int)MT_Tune_atv(h, f_in, bw_in, tv_type);
25
26 struct dvb_frontend_ops *frontend_ops = NULL;
27 struct dvb_tuner_ops *tuner_ops = NULL;
28 struct tuner_state t_state;
29 struct mt2063_state *mt2063State = fe->tuner_priv;
30 int err = 0;
31
32 t_state.frequency = f_in;
33 t_state.bandwidth = bw_in;
34 mt2063State->tv_type = tv_type;
35 if (&fe->ops)
36 frontend_ops = &fe->ops;
37 if (&frontend_ops->tuner_ops)
38 tuner_ops = &frontend_ops->tuner_ops;
39 if (tuner_ops->set_state) {
40 if ((err =
41 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
42 &t_state)) < 0) {
43 printk("%s: Invalid parameter\n", __func__);
44 return err;
45 }
46 }
47
48 return err;
49}
50
51static unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
52{
53 struct dvb_frontend_ops *frontend_ops = &fe->ops;
54 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
55 struct tuner_state t_state;
56 int err = 0;
57
58 if (&fe->ops)
59 frontend_ops = &fe->ops;
60 if (&frontend_ops->tuner_ops)
61 tuner_ops = &frontend_ops->tuner_ops;
62 if (tuner_ops->get_state) {
63 if ((err =
64 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
65 &t_state)) < 0) {
66 printk("%s: Invalid parameter\n", __func__);
67 return err;
68 }
69 }
70 return err;
71}
72
73static unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
74{
75 struct dvb_frontend_ops *frontend_ops = &fe->ops;
76 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
77 struct tuner_state t_state;
78 int err = 0;
79
80 if (&fe->ops)
81 frontend_ops = &fe->ops;
82 if (&frontend_ops->tuner_ops)
83 tuner_ops = &frontend_ops->tuner_ops;
84 if (tuner_ops->set_state) {
85 if ((err =
86 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
87 &t_state)) < 0) {
88 printk("%s: Invalid parameter\n", __func__);
89 return err;
90 }
91 }
92
93 return err;
94}
95
96static unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
97{
98 struct dvb_frontend_ops *frontend_ops = &fe->ops;
99 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
100 struct tuner_state t_state;
101 int err = 0;
102
103 if (&fe->ops)
104 frontend_ops = &fe->ops;
105 if (&frontend_ops->tuner_ops)
106 tuner_ops = &frontend_ops->tuner_ops;
107 if (tuner_ops->set_state) {
108 if ((err =
109 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
110 &t_state)) < 0) {
111 printk("%s: Invalid parameter\n", __func__);
112 return err;
113 }
114 }
115
116 return err;
117}
118
119static unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
120{
121 struct dvb_frontend_ops *frontend_ops = &fe->ops;
122 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
123 struct tuner_state t_state;
124 int err = 0;
125
126 if (&fe->ops)
127 frontend_ops = &fe->ops;
128 if (&frontend_ops->tuner_ops)
129 tuner_ops = &frontend_ops->tuner_ops;
130 if (tuner_ops->set_state) {
131 if ((err =
132 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
133 &t_state)) < 0) {
134 printk("%s: Invalid parameter\n", __func__);
135 return err;
136 }
137 }
138
139 return err;
140}
141
142/*****************/
143
144
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300145//i2c operation
146static int mt2063_writeregs(struct mt2063_state *state, u8 reg1,
147 u8 * data, int len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300148{
149 int ret;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300150 u8 buf[60]; /* = { reg1, data }; */
151
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300152 struct i2c_msg msg = {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300153 .addr = state->config->tuner_address,
154 .flags = 0,
155 .buf = buf,
156 .len = len + 1
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300157 };
158
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300159 msg.buf[0] = reg1;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300160 memcpy(msg.buf + 1, data, len);
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300161
162 //printk("mt2063_writeregs state->i2c=%p\n", state->i2c);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300163 ret = i2c_transfer(state->i2c, &msg, 1);
164
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300165 if (ret < 0)
166 printk("mt2063_writeregs error ret=%d\n", ret);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300167
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300168 return ret;
169}
170
171static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 * b, u8 len)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300172{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300173 int ret;
174 u8 b0[] = { reg1 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300175 struct i2c_msg msg[] = {
176 {
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300177 .addr = state->config->tuner_address,
178 .flags = I2C_M_RD,
179 .buf = b0,
180 .len = 1}, {
181 .addr = state->config->tuner_address,
182 .flags = I2C_M_RD,
183 .buf = b,
184 .len = len}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300185 };
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300186
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300187 //printk("mt2063_read_regs state->i2c=%p\n", state->i2c);
188 ret = i2c_transfer(state->i2c, msg, 2);
189 if (ret < 0)
190 printk("mt2063_readregs error ret=%d\n", ret);
191
192 return ret;
193}
194
195//context of mt2063_userdef.c <Henry> ======================================
196//#################################################################
197//=================================================================
198/*****************************************************************************
199**
200** Name: MT_WriteSub
201**
202** Description: Write values to device using a two-wire serial bus.
203**
204** Parameters: hUserData - User-specific I/O parameter that was
205** passed to tuner's Open function.
206** addr - device serial bus address (value passed
207** as parameter to MTxxxx_Open)
208** subAddress - serial bus sub-address (Register Address)
209** pData - pointer to the Data to be written to the
210** device
211** cnt - number of bytes/registers to be written
212**
213** Returns: status:
214** MT_OK - No errors
215** MT_COMM_ERR - Serial bus communications error
216** user-defined
217**
218** Notes: This is a callback function that is called from the
219** the tuning algorithm. You MUST provide code for this
220** function to write data using the tuner's 2-wire serial
221** bus.
222**
223** The hUserData parameter is a user-specific argument.
224** If additional arguments are needed for the user's
225** serial bus read/write functions, this argument can be
226** used to supply the necessary information.
227** The hUserData parameter is initialized in the tuner's Open
228** function.
229**
230** Revision History:
231**
232** SCR Date Author Description
233** -------------------------------------------------------------------------
234** N/A 03-25-2004 DAD Original
235**
236*****************************************************************************/
237UData_t MT2063_WriteSub(Handle_t hUserData,
238 UData_t addr,
239 U8Data subAddress, U8Data * pData, UData_t cnt)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -0300240{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -0300241 UData_t status = MT2063_OK; /* Status to be returned */
242 struct dvb_frontend *fe = hUserData;
243 struct mt2063_state *state = fe->tuner_priv;
244 /*
245 ** ToDo: Add code here to implement a serial-bus write
246 ** operation to the MTxxxx tuner. If successful,
247 ** return MT_OK.
248 */
249/* return status; */
250
251//#if !TUNER_CONTROL_BY_DRXK_DRIVER
252 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
253//#endif
254
255 if (mt2063_writeregs(state, subAddress, pData, cnt) < 0) {
256 status = MT2063_ERROR;
257 }
258//#if !TUNER_CONTROL_BY_DRXK_DRIVER
259 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
260//#endif
261
262 return (status);
263}
264
265/*****************************************************************************
266**
267** Name: MT_ReadSub
268**
269** Description: Read values from device using a two-wire serial bus.
270**
271** Parameters: hUserData - User-specific I/O parameter that was
272** passed to tuner's Open function.
273** addr - device serial bus address (value passed
274** as parameter to MTxxxx_Open)
275** subAddress - serial bus sub-address (Register Address)
276** pData - pointer to the Data to be written to the
277** device
278** cnt - number of bytes/registers to be written
279**
280** Returns: status:
281** MT_OK - No errors
282** MT_COMM_ERR - Serial bus communications error
283** user-defined
284**
285** Notes: This is a callback function that is called from the
286** the tuning algorithm. You MUST provide code for this
287** function to read data using the tuner's 2-wire serial
288** bus.
289**
290** The hUserData parameter is a user-specific argument.
291** If additional arguments are needed for the user's
292** serial bus read/write functions, this argument can be
293** used to supply the necessary information.
294** The hUserData parameter is initialized in the tuner's Open
295** function.
296**
297** Revision History:
298**
299** SCR Date Author Description
300** -------------------------------------------------------------------------
301** N/A 03-25-2004 DAD Original
302**
303*****************************************************************************/
304UData_t MT2063_ReadSub(Handle_t hUserData,
305 UData_t addr,
306 U8Data subAddress, U8Data * pData, UData_t cnt)
307{
308 /*
309 ** ToDo: Add code here to implement a serial-bus read
310 ** operation to the MTxxxx tuner. If successful,
311 ** return MT_OK.
312 */
313/* return status; */
314 UData_t status = MT2063_OK; /* Status to be returned */
315 struct dvb_frontend *fe = hUserData;
316 struct mt2063_state *state = fe->tuner_priv;
317 UData_t i = 0;
318//#if !TUNER_CONTROL_BY_DRXK_DRIVER
319 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
320//#endif
321
322 for (i = 0; i < cnt; i++) {
323 if (mt2063_read_regs(state, subAddress + i, pData + i, 1) < 0) {
324 status = MT2063_ERROR;
325 break;
326 }
327 }
328
329//#if !TUNER_CONTROL_BY_DRXK_DRIVER
330 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
331//#endif
332
333 return (status);
334}
335
336/*****************************************************************************
337**
338** Name: MT_Sleep
339**
340** Description: Delay execution for "nMinDelayTime" milliseconds
341**
342** Parameters: hUserData - User-specific I/O parameter that was
343** passed to tuner's Open function.
344** nMinDelayTime - Delay time in milliseconds
345**
346** Returns: None.
347**
348** Notes: This is a callback function that is called from the
349** the tuning algorithm. You MUST provide code that
350** blocks execution for the specified period of time.
351**
352** Revision History:
353**
354** SCR Date Author Description
355** -------------------------------------------------------------------------
356** N/A 03-25-2004 DAD Original
357**
358*****************************************************************************/
359void MT2063_Sleep(Handle_t hUserData, UData_t nMinDelayTime)
360{
361 /*
362 ** ToDo: Add code here to implement a OS blocking
363 ** for a period of "nMinDelayTime" milliseconds.
364 */
365 msleep(nMinDelayTime);
366}
367
368#if defined(MT2060_CNT)
369#if MT2060_CNT > 0
370/*****************************************************************************
371**
372** Name: MT_TunerGain (MT2060 only)
373**
374** Description: Measure the relative tuner gain using the demodulator
375**
376** Parameters: hUserData - User-specific I/O parameter that was
377** passed to tuner's Open function.
378** pMeas - Tuner gain (1/100 of dB scale).
379** ie. 1234 = 12.34 (dB)
380**
381** Returns: status:
382** MT_OK - No errors
383** user-defined errors could be set
384**
385** Notes: This is a callback function that is called from the
386** the 1st IF location routine. You MUST provide
387** code that measures the relative tuner gain in a dB
388** (not linear) scale. The return value is an integer
389** value scaled to 1/100 of a dB.
390**
391** Revision History:
392**
393** SCR Date Author Description
394** -------------------------------------------------------------------------
395** N/A 06-16-2004 DAD Original
396** N/A 11-30-2004 DAD Renamed from MT_DemodInputPower. This name
397** better describes what this function does.
398**
399*****************************************************************************/
400UData_t MT2060_TunerGain(Handle_t hUserData, SData_t * pMeas)
401{
402 UData_t status = MT2063_OK; /* Status to be returned */
403
404 /*
405 ** ToDo: Add code here to return the gain / power level measured
406 ** at the input to the demodulator.
407 */
408
409 return (status);
410}
411#endif
412#endif
413//end of mt2063_userdef.c
414//=================================================================
415//#################################################################
416//=================================================================
417
418//context of mt2063_spuravoid.c <Henry> ======================================
419//#################################################################
420//=================================================================
421
422/*****************************************************************************
423**
424** Name: mt_spuravoid.c
425**
426** Description: Microtune spur avoidance software module.
427** Supports Microtune tuner drivers.
428**
429** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
430** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
431**
432** Revision History:
433**
434** SCR Date Author Description
435** -------------------------------------------------------------------------
436** 082 03-25-2005 JWS Original multi-tuner support - requires
437** MTxxxx_CNT declarations
438** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
439** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
440** of compiler warnings
441** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
442** avoidance into a single module.
443** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
444** (f_min, f_max) < 0, ignore the entry.
445** 115 03-23-2007 DAD Fix declaration of spur due to truncation
446** errors.
447** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
448** tuner DLL.
449** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
450** multi-tuners that have
451** (delta IF1) > (f_out-f_outbw/2).
452** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
453** Added logic to force f_Center within 1/2 f_Step.
454** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
455** Type casts added to preserve correct sign.
456** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
457** frequencies into MT_ResetExclZones().
458** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
459**
460*****************************************************************************/
461
462#if !defined(MT2063_TUNER_CNT)
463#error MT2063_TUNER_CNT is not defined (see mt_userdef.h)
464#endif
465
466#if MT2063_TUNER_CNT == 0
467#error MT2063_TUNER_CNT must be updated in mt_userdef.h
468#endif
469
470/* Version of this module */
471#define MT2063_SPUR_VERSION 10201 /* Version 01.21 */
472
473/* Implement ceiling, floor functions. */
474#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
475#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
476#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
477#define ufloor(n, d) ((n)/(d))
478
479struct MT2063_FIFZone_t {
480 SData_t min_;
481 SData_t max_;
482};
483
484#if MT2063_TUNER_CNT > 1
485static struct MT2063_AvoidSpursData_t *TunerList[MT2063_TUNER_CNT];
486static UData_t TunerCount = 0;
487#endif
488
489UData_t MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
490{
491#if MT2063_TUNER_CNT == 1
492 pAS_Info->nAS_Algorithm = 1;
493 return MT2063_OK;
494#else
495 UData_t index;
496
497 pAS_Info->nAS_Algorithm = 2;
498
499 /*
500 ** Check to see if tuner is already registered
501 */
502 for (index = 0; index < TunerCount; index++) {
503 if (TunerList[index] == pAS_Info) {
504 return MT2063_OK; /* Already here - no problem */
505 }
506 }
507
508 /*
509 ** Add tuner to list - if there is room.
510 */
511 if (TunerCount < MT2063_TUNER_CNT) {
512 TunerList[TunerCount] = pAS_Info;
513 TunerCount++;
514 return MT2063_OK;
515 } else
516 return MT2063_TUNER_CNT_ERR;
517#endif
518}
519
520void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
521{
522#if MT2063_TUNER_CNT == 1
523 pAS_Info;
524#else
525
526 UData_t index;
527
528 for (index = 0; index < TunerCount; index++) {
529 if (TunerList[index] == pAS_Info) {
530 TunerList[index] = TunerList[--TunerCount];
531 }
532 }
533#endif
534}
535
536/*
537** Reset all exclusion zones.
538** Add zones to protect the PLL FracN regions near zero
539**
540** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
541** frequencies into MT_ResetExclZones().
542*/
543void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
544{
545 UData_t center;
546#if MT2063_TUNER_CNT > 1
547 UData_t index;
548 struct MT2063_AvoidSpursData_t *adj;
549#endif
550
551 pAS_Info->nZones = 0; /* this clears the used list */
552 pAS_Info->usedZones = NULL; /* reset ptr */
553 pAS_Info->freeZones = NULL; /* reset ptr */
554
555 center =
556 pAS_Info->f_ref *
557 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
558 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
559 while (center <
560 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
561 pAS_Info->f_LO1_FracN_Avoid) {
562 /* Exclude LO1 FracN */
563 MT2063_AddExclZone(pAS_Info,
564 center - pAS_Info->f_LO1_FracN_Avoid,
565 center - 1);
566 MT2063_AddExclZone(pAS_Info, center + 1,
567 center + pAS_Info->f_LO1_FracN_Avoid);
568 center += pAS_Info->f_ref;
569 }
570
571 center =
572 pAS_Info->f_ref *
573 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
574 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
575 while (center <
576 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
577 pAS_Info->f_LO2_FracN_Avoid) {
578 /* Exclude LO2 FracN */
579 MT2063_AddExclZone(pAS_Info,
580 center - pAS_Info->f_LO2_FracN_Avoid,
581 center - 1);
582 MT2063_AddExclZone(pAS_Info, center + 1,
583 center + pAS_Info->f_LO2_FracN_Avoid);
584 center += pAS_Info->f_ref;
585 }
586
587 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
588 /* Exclude LO1 values that conflict with DECT channels */
589 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
590 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
591 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
592 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
593 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
594 }
595
596 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
597 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
598 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
599 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
600 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
601 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
602 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
603 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
604 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
605 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
606 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
607 }
608#if MT2063_TUNER_CNT > 1
609 /*
610 ** Iterate through all adjacent tuners and exclude frequencies related to them
611 */
612 for (index = 0; index < TunerCount; ++index) {
613 adj = TunerList[index];
614 if (pAS_Info == adj) /* skip over our own data, don't process it */
615 continue;
616
617 /*
618 ** Add 1st IF exclusion zone covering adjacent tuner's LO2
619 ** at "adjfLO2 + f_out" +/- m_MinLOSpacing
620 */
621 if (adj->f_LO2 != 0)
622 MT2063_AddExclZone(pAS_Info,
623 (adj->f_LO2 + pAS_Info->f_out) -
624 pAS_Info->f_min_LO_Separation,
625 (adj->f_LO2 + pAS_Info->f_out) +
626 pAS_Info->f_min_LO_Separation);
627
628 /*
629 ** Add 1st IF exclusion zone covering adjacent tuner's LO1
630 ** at "adjfLO1 - f_in" +/- m_MinLOSpacing
631 */
632 if (adj->f_LO1 != 0)
633 MT2063_AddExclZone(pAS_Info,
634 (adj->f_LO1 - pAS_Info->f_in) -
635 pAS_Info->f_min_LO_Separation,
636 (adj->f_LO1 - pAS_Info->f_in) +
637 pAS_Info->f_min_LO_Separation);
638 }
639#endif
640}
641
642static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
643 *pAS_Info,
644 struct MT2063_ExclZone_t *pPrevNode)
645{
646 struct MT2063_ExclZone_t *pNode;
647 /* Check for a node in the free list */
648 if (pAS_Info->freeZones != NULL) {
649 /* Use one from the free list */
650 pNode = pAS_Info->freeZones;
651 pAS_Info->freeZones = pNode->next_;
652 } else {
653 /* Grab a node from the array */
654 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
655 }
656
657 if (pPrevNode != NULL) {
658 pNode->next_ = pPrevNode->next_;
659 pPrevNode->next_ = pNode;
660 } else { /* insert at the beginning of the list */
661
662 pNode->next_ = pAS_Info->usedZones;
663 pAS_Info->usedZones = pNode;
664 }
665
666 pAS_Info->nZones++;
667 return pNode;
668}
669
670static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
671 *pAS_Info,
672 struct MT2063_ExclZone_t *pPrevNode,
673 struct MT2063_ExclZone_t
674 *pNodeToRemove)
675{
676 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
677
678 /* Make previous node point to the subsequent node */
679 if (pPrevNode != NULL)
680 pPrevNode->next_ = pNext;
681
682 /* Add pNodeToRemove to the beginning of the freeZones */
683 pNodeToRemove->next_ = pAS_Info->freeZones;
684 pAS_Info->freeZones = pNodeToRemove;
685
686 /* Decrement node count */
687 pAS_Info->nZones--;
688
689 return pNext;
690}
691
692/*****************************************************************************
693**
694** Name: MT_AddExclZone
695**
696** Description: Add (and merge) an exclusion zone into the list.
697** If the range (f_min, f_max) is totally outside the
698** 1st IF BW, ignore the entry.
699** If the range (f_min, f_max) is negative, ignore the entry.
700**
701** Revision History:
702**
703** SCR Date Author Description
704** -------------------------------------------------------------------------
705** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
706** (f_min, f_max) < 0, ignore the entry.
707**
708*****************************************************************************/
709void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
710 UData_t f_min, UData_t f_max)
711{
712 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
713 struct MT2063_ExclZone_t *pPrev = NULL;
714 struct MT2063_ExclZone_t *pNext = NULL;
715
716 /* Check to see if this overlaps the 1st IF filter */
717 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
718 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
719 && (f_min < f_max)) {
720 /*
721 ** 1 2 3 4 5 6
722 **
723 ** New entry: |---| |--| |--| |-| |---| |--|
724 ** or or or or or
725 ** Existing: |--| |--| |--| |---| |-| |--|
726 */
727
728 /* Check for our place in the list */
729 while ((pNode != NULL) && (pNode->max_ < f_min)) {
730 pPrev = pNode;
731 pNode = pNode->next_;
732 }
733
734 if ((pNode != NULL) && (pNode->min_ < f_max)) {
735 /* Combine me with pNode */
736 if (f_min < pNode->min_)
737 pNode->min_ = f_min;
738 if (f_max > pNode->max_)
739 pNode->max_ = f_max;
740 } else {
741 pNode = InsertNode(pAS_Info, pPrev);
742 pNode->min_ = f_min;
743 pNode->max_ = f_max;
744 }
745
746 /* Look for merging possibilities */
747 pNext = pNode->next_;
748 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
749 if (pNext->max_ > pNode->max_)
750 pNode->max_ = pNext->max_;
751 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
752 }
753 }
754}
755
756/*****************************************************************************
757**
758** Name: MT_ChooseFirstIF
759**
760** Description: Choose the best available 1st IF
761** If f_Desired is not excluded, choose that first.
762** Otherwise, return the value closest to f_Center that is
763** not excluded
764**
765** Revision History:
766**
767** SCR Date Author Description
768** -------------------------------------------------------------------------
769** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
770** tuner DLL.
771** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
772** Added logic to force f_Center within 1/2 f_Step.
773**
774*****************************************************************************/
775UData_t MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
776{
777 /*
778 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
779 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
780 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
781 ** However, the sum must be.
782 */
783 const UData_t f_Desired =
784 pAS_Info->f_LO1_Step *
785 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
786 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
787 pAS_Info->f_in;
788 const UData_t f_Step =
789 (pAS_Info->f_LO1_Step >
790 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
791 f_LO2_Step;
792 UData_t f_Center;
793
794 SData_t i;
795 SData_t j = 0;
796 UData_t bDesiredExcluded = 0;
797 UData_t bZeroExcluded = 0;
798 SData_t tmpMin, tmpMax;
799 SData_t bestDiff;
800 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
801 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
802
803 if (pAS_Info->nZones == 0)
804 return f_Desired;
805
806 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
807 if (pAS_Info->f_if1_Center > f_Desired)
808 f_Center =
809 f_Desired +
810 f_Step *
811 ((pAS_Info->f_if1_Center - f_Desired +
812 f_Step / 2) / f_Step);
813 else
814 f_Center =
815 f_Desired -
816 f_Step *
817 ((f_Desired - pAS_Info->f_if1_Center +
818 f_Step / 2) / f_Step);
819
820 //assert;
821 //if (!abs((SData_t) f_Center - (SData_t) pAS_Info->f_if1_Center) <= (SData_t) (f_Step/2))
822 // return 0;
823
824 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
825 while (pNode != NULL) {
826 /* floor function */
827 tmpMin =
828 floor((SData_t) (pNode->min_ - f_Center), (SData_t) f_Step);
829
830 /* ceil function */
831 tmpMax =
832 ceil((SData_t) (pNode->max_ - f_Center), (SData_t) f_Step);
833
834 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
835 bDesiredExcluded = 1;
836
837 if ((tmpMin < 0) && (tmpMax > 0))
838 bZeroExcluded = 1;
839
840 /* See if this zone overlaps the previous */
841 if ((j > 0) && (tmpMin < zones[j - 1].max_))
842 zones[j - 1].max_ = tmpMax;
843 else {
844 /* Add new zone */
845 //assert(j<MT2063_MAX_ZONES);
846 //if (j>=MT2063_MAX_ZONES)
847 //break;
848
849 zones[j].min_ = tmpMin;
850 zones[j].max_ = tmpMax;
851 j++;
852 }
853 pNode = pNode->next_;
854 }
855
856 /*
857 ** If the desired is okay, return with it
858 */
859 if (bDesiredExcluded == 0)
860 return f_Desired;
861
862 /*
863 ** If the desired is excluded and the center is okay, return with it
864 */
865 if (bZeroExcluded == 0)
866 return f_Center;
867
868 /* Find the value closest to 0 (f_Center) */
869 bestDiff = zones[0].min_;
870 for (i = 0; i < j; i++) {
871 if (abs(zones[i].min_) < abs(bestDiff))
872 bestDiff = zones[i].min_;
873 if (abs(zones[i].max_) < abs(bestDiff))
874 bestDiff = zones[i].max_;
875 }
876
877 if (bestDiff < 0)
878 return f_Center - ((UData_t) (-bestDiff) * f_Step);
879
880 return f_Center + (bestDiff * f_Step);
881}
882
883/****************************************************************************
884**
885** Name: gcd
886**
887** Description: Uses Euclid's algorithm
888**
889** Parameters: u, v - unsigned values whose GCD is desired.
890**
891** Global: None
892**
893** Returns: greatest common divisor of u and v, if either value
894** is 0, the other value is returned as the result.
895**
896** Dependencies: None.
897**
898** Revision History:
899**
900** SCR Date Author Description
901** -------------------------------------------------------------------------
902** N/A 06-01-2004 JWS Original
903** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
904** unsigned numbers.
905**
906****************************************************************************/
907static UData_t MT2063_gcd(UData_t u, UData_t v)
908{
909 UData_t r;
910
911 while (v != 0) {
912 r = u % v;
913 u = v;
914 v = r;
915 }
916
917 return u;
918}
919
920/****************************************************************************
921**
922** Name: umax
923**
924** Description: Implements a simple maximum function for unsigned numbers.
925** Implemented as a function rather than a macro to avoid
926** multiple evaluation of the calling parameters.
927**
928** Parameters: a, b - Values to be compared
929**
930** Global: None
931**
932** Returns: larger of the input values.
933**
934** Dependencies: None.
935**
936** Revision History:
937**
938** SCR Date Author Description
939** -------------------------------------------------------------------------
940** N/A 06-02-2004 JWS Original
941**
942****************************************************************************/
943static UData_t MT2063_umax(UData_t a, UData_t b)
944{
945 return (a >= b) ? a : b;
946}
947
948#if MT2063_TUNER_CNT > 1
949static SData_t RoundAwayFromZero(SData_t n, SData_t d)
950{
951 return (n < 0) ? floor(n, d) : ceil(n, d);
952}
953
954/****************************************************************************
955**
956** Name: IsSpurInAdjTunerBand
957**
958** Description: Checks to see if a spur will be present within the IF's
959** bandwidth or near the zero IF.
960** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2)
961** and
962** (0 +/- fZIFBW/2)
963**
964** ma mb me mf mc md
965** <--+-+-+-----------------+-+-+-----------------+-+-+-->
966** | ^ 0 ^ |
967** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
968** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
969**
970** Note that some equations are doubled to prevent round-off
971** problems when calculating fIFBW/2
972**
973** The spur frequencies are computed as:
974**
975** fSpur = n * f1 - m * f2 - fOffset
976**
977** Parameters: f1 - The 1st local oscillator (LO) frequency
978** of the tuner whose output we are examining
979** f2 - The 1st local oscillator (LO) frequency
980** of the adjacent tuner
981** fOffset - The 2nd local oscillator of the tuner whose
982** output we are examining
983** fIFOut - Output IF center frequency
984** fIFBW - Output IF Bandwidth
985** nMaxH - max # of LO harmonics to search
986** fp - If spur, positive distance to spur-free band edge (returned)
987** fm - If spur, negative distance to spur-free band edge (returned)
988**
989** Returns: 1 if an LO spur would be present, otherwise 0.
990**
991** Dependencies: None.
992**
993** Revision History:
994**
995** SCR Date Author Description
996** -------------------------------------------------------------------------
997** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion.
998** 115 03-23-2007 DAD Fix declaration of spur due to truncation
999** errors.
1000** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
1001** multi-tuners that have
1002** (delta IF1) > (f_out-f_outbw/2).
1003** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
1004** Type casts added to preserve correct sign.
1005**
1006****************************************************************************/
1007static UData_t IsSpurInAdjTunerBand(UData_t bIsMyOutput,
1008 UData_t f1,
1009 UData_t f2,
1010 UData_t fOffset,
1011 UData_t fIFOut,
1012 UData_t fIFBW,
1013 UData_t fZIFBW,
1014 UData_t nMaxH, UData_t * fp, UData_t * fm)
1015{
1016 UData_t bSpurFound = 0;
1017
1018 const UData_t fHalf_IFBW = fIFBW / 2;
1019 const UData_t fHalf_ZIFBW = fZIFBW / 2;
1020
1021 /* Calculate a scale factor for all frequencies, so that our
1022 calculations all stay within 31 bits */
1023 const UData_t f_Scale =
1024 ((f1 +
1025 (fOffset + fIFOut +
1026 fHalf_IFBW) / nMaxH) / (MAX_UDATA / 2 / nMaxH)) + 1;
1027
1028 /*
1029 ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into
1030 ** signed data types (smaller than MAX_UDATA/2)
1031 */
1032 const SData_t _f1 = (SData_t) (f1 / f_Scale);
1033 const SData_t _f2 = (SData_t) (f2 / f_Scale);
1034 const SData_t _f3 = (SData_t) (fOffset / f_Scale);
1035
1036 const SData_t c = (SData_t) (fIFOut - fHalf_IFBW) / (SData_t) f_Scale;
1037 const SData_t d = (SData_t) ((fIFOut + fHalf_IFBW) / f_Scale);
1038 const SData_t f = (SData_t) (fHalf_ZIFBW / f_Scale);
1039
1040 SData_t ma, mb, mc, md, me, mf;
1041
1042 SData_t fp_ = 0;
1043 SData_t fm_ = 0;
1044 SData_t n;
1045
1046 /*
1047 ** If the other tuner does not have an LO frequency defined,
1048 ** assume that we cannot interfere with it
1049 */
1050 if (f2 == 0)
1051 return 0;
1052
1053 /* Check out all multiples of f1 from -nMaxH to +nMaxH */
1054 for (n = -(SData_t) nMaxH; n <= (SData_t) nMaxH; ++n) {
1055 const SData_t nf1 = n * _f1;
1056 md = (_f3 + d - nf1) / _f2;
1057
1058 /* If # f2 harmonics > nMaxH, then no spurs present */
1059 if (md <= -(SData_t) nMaxH)
1060 break;
1061
1062 ma = (_f3 - d - nf1) / _f2;
1063 if ((ma == md) || (ma >= (SData_t) (nMaxH)))
1064 continue;
1065
1066 mc = (_f3 + c - nf1) / _f2;
1067 if (mc != md) {
1068 const SData_t m = (n < 0) ? md : mc;
1069 const SData_t fspur = (nf1 + m * _f2 - _f3);
1070 const SData_t den = (bIsMyOutput ? n - 1 : n);
1071 if (den == 0) {
1072 fp_ = (d - fspur) * f_Scale;
1073 fm_ = (fspur - c) * f_Scale;
1074 } else {
1075 fp_ =
1076 (SData_t) RoundAwayFromZero((d - fspur) *
1077 f_Scale, den);
1078 fm_ =
1079 (SData_t) RoundAwayFromZero((fspur - c) *
1080 f_Scale, den);
1081 }
1082 if (((UData_t) abs(fm_) >= f_Scale)
1083 && ((UData_t) abs(fp_) >= f_Scale)) {
1084 bSpurFound = 1;
1085 break;
1086 }
1087 }
1088
1089 /* Location of Zero-IF-spur to be checked */
1090 mf = (_f3 + f - nf1) / _f2;
1091 me = (_f3 - f - nf1) / _f2;
1092 if (me != mf) {
1093 const SData_t m = (n < 0) ? mf : me;
1094 const SData_t fspur = (nf1 + m * _f2 - _f3);
1095 const SData_t den = (bIsMyOutput ? n - 1 : n);
1096 if (den == 0) {
1097 fp_ = (d - fspur) * f_Scale;
1098 fm_ = (fspur - c) * f_Scale;
1099 } else {
1100 fp_ =
1101 (SData_t) RoundAwayFromZero((f - fspur) *
1102 f_Scale, den);
1103 fm_ =
1104 (SData_t) RoundAwayFromZero((fspur + f) *
1105 f_Scale, den);
1106 }
1107 if (((UData_t) abs(fm_) >= f_Scale)
1108 && ((UData_t) abs(fp_) >= f_Scale)) {
1109 bSpurFound = 1;
1110 break;
1111 }
1112 }
1113
1114 mb = (_f3 - c - nf1) / _f2;
1115 if (ma != mb) {
1116 const SData_t m = (n < 0) ? mb : ma;
1117 const SData_t fspur = (nf1 + m * _f2 - _f3);
1118 const SData_t den = (bIsMyOutput ? n - 1 : n);
1119 if (den == 0) {
1120 fp_ = (d - fspur) * f_Scale;
1121 fm_ = (fspur - c) * f_Scale;
1122 } else {
1123 fp_ =
1124 (SData_t) RoundAwayFromZero((-c - fspur) *
1125 f_Scale, den);
1126 fm_ =
1127 (SData_t) RoundAwayFromZero((fspur + d) *
1128 f_Scale, den);
1129 }
1130 if (((UData_t) abs(fm_) >= f_Scale)
1131 && ((UData_t) abs(fp_) >= f_Scale)) {
1132 bSpurFound = 1;
1133 break;
1134 }
1135 }
1136 }
1137
1138 /*
1139 ** Verify that fm & fp are both positive
1140 ** Add one to ensure next 1st IF choice is not right on the edge
1141 */
1142 if (fp_ < 0) {
1143 *fp = -fm_ + 1;
1144 *fm = -fp_ + 1;
1145 } else if (fp_ > 0) {
1146 *fp = fp_ + 1;
1147 *fm = fm_ + 1;
1148 } else {
1149 *fp = 1;
1150 *fm = abs(fm_) + 1;
1151 }
1152
1153 return bSpurFound;
1154}
1155#endif
1156
1157/****************************************************************************
1158**
1159** Name: IsSpurInBand
1160**
1161** Description: Checks to see if a spur will be present within the IF's
1162** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1163**
1164** ma mb mc md
1165** <--+-+-+-------------------+-------------------+-+-+-->
1166** | ^ 0 ^ |
1167** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1168** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1169**
1170** Note that some equations are doubled to prevent round-off
1171** problems when calculating fIFBW/2
1172**
1173** Parameters: pAS_Info - Avoid Spurs information block
1174** fm - If spur, amount f_IF1 has to move negative
1175** fp - If spur, amount f_IF1 has to move positive
1176**
1177** Global: None
1178**
1179** Returns: 1 if an LO spur would be present, otherwise 0.
1180**
1181** Dependencies: None.
1182**
1183** Revision History:
1184**
1185** SCR Date Author Description
1186** -------------------------------------------------------------------------
1187** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1188**
1189****************************************************************************/
1190static UData_t IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1191 UData_t * fm, UData_t * fp)
1192{
1193 /*
1194 ** Calculate LO frequency settings.
1195 */
1196 UData_t n, n0;
1197 const UData_t f_LO1 = pAS_Info->f_LO1;
1198 const UData_t f_LO2 = pAS_Info->f_LO2;
1199 const UData_t d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1200 const UData_t c = d - pAS_Info->f_out_bw;
1201 const UData_t f = pAS_Info->f_zif_bw / 2;
1202 const UData_t f_Scale = (f_LO1 / (MAX_UDATA / 2 / pAS_Info->maxH1)) + 1;
1203 SData_t f_nsLO1, f_nsLO2;
1204 SData_t f_Spur;
1205 UData_t ma, mb, mc, md, me, mf;
1206 UData_t lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
1207#if MT2063_TUNER_CNT > 1
1208 UData_t index;
1209
1210 struct MT2063_AvoidSpursData_t *adj;
1211#endif
1212 *fm = 0;
1213
1214 /*
1215 ** For each edge (d, c & f), calculate a scale, based on the gcd
1216 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1217 ** gcd-based scale factor or f_Scale.
1218 */
1219 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
1220 gd_Scale = MT2063_umax((UData_t) MT2063_gcd(lo_gcd, d), f_Scale);
1221 hgds = gd_Scale / 2;
1222 gc_Scale = MT2063_umax((UData_t) MT2063_gcd(lo_gcd, c), f_Scale);
1223 hgcs = gc_Scale / 2;
1224 gf_Scale = MT2063_umax((UData_t) MT2063_gcd(lo_gcd, f), f_Scale);
1225 hgfs = gf_Scale / 2;
1226
1227 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1228
1229 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1230 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1231 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1232 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1233
1234 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1235 if (md >= pAS_Info->maxH1)
1236 break;
1237
1238 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1239 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1240
1241 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1242 if (md == ma)
1243 continue;
1244
1245 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1246 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1247 if (mc != md) {
1248 f_nsLO1 = (SData_t) (n * (f_LO1 / gc_Scale));
1249 f_nsLO2 = (SData_t) (mc * (f_LO2 / gc_Scale));
1250 f_Spur =
1251 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1252 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1253
1254 *fp = ((f_Spur - (SData_t) c) / (mc - n)) + 1;
1255 *fm = (((SData_t) d - f_Spur) / (mc - n)) + 1;
1256 return 1;
1257 }
1258
1259 /* Location of Zero-IF-spur to be checked */
1260 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1261 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1262 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1263 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1264 if (me != mf) {
1265 f_nsLO1 = n * (f_LO1 / gf_Scale);
1266 f_nsLO2 = me * (f_LO2 / gf_Scale);
1267 f_Spur =
1268 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1269 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1270
1271 *fp = ((f_Spur + (SData_t) f) / (me - n)) + 1;
1272 *fm = (((SData_t) f - f_Spur) / (me - n)) + 1;
1273 return 1;
1274 }
1275
1276 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1277 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1278 if (ma != mb) {
1279 f_nsLO1 = n * (f_LO1 / gc_Scale);
1280 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1281 f_Spur =
1282 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1283 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1284
1285 *fp = (((SData_t) d + f_Spur) / (ma - n)) + 1;
1286 *fm = (-(f_Spur + (SData_t) c) / (ma - n)) + 1;
1287 return 1;
1288 }
1289 }
1290
1291#if MT2063_TUNER_CNT > 1
1292 /* If no spur found, see if there are more tuners on the same board */
1293 for (index = 0; index < TunerCount; ++index) {
1294 adj = TunerList[index];
1295 if (pAS_Info == adj) /* skip over our own data, don't process it */
1296 continue;
1297
1298 /* Look for LO-related spurs from the adjacent tuner generated into my IF output */
1299 if (IsSpurInAdjTunerBand(1, /* check my IF output */
1300 pAS_Info->f_LO1, /* my fLO1 */
1301 adj->f_LO1, /* the other tuner's fLO1 */
1302 pAS_Info->f_LO2, /* my fLO2 */
1303 pAS_Info->f_out, /* my fOut */
1304 pAS_Info->f_out_bw, /* my output IF bandwidth */
1305 pAS_Info->f_zif_bw, /* my Zero-IF bandwidth */
1306 pAS_Info->maxH2, fp, /* minimum amount to move LO's positive */
1307 fm)) /* miminum amount to move LO's negative */
1308 return 1;
1309 /* Look for LO-related spurs from my tuner generated into the adjacent tuner's IF output */
1310 if (IsSpurInAdjTunerBand(0, /* check his IF output */
1311 pAS_Info->f_LO1, /* my fLO1 */
1312 adj->f_LO1, /* the other tuner's fLO1 */
1313 adj->f_LO2, /* the other tuner's fLO2 */
1314 adj->f_out, /* the other tuner's fOut */
1315 adj->f_out_bw, /* the other tuner's output IF bandwidth */
1316 pAS_Info->f_zif_bw, /* the other tuner's Zero-IF bandwidth */
1317 adj->maxH2, fp, /* minimum amount to move LO's positive */
1318 fm)) /* miminum amount to move LO's negative */
1319 return 1;
1320 }
1321#endif
1322 /* No spurs found */
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001323 return 0;
1324}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001325
1326/*****************************************************************************
1327**
1328** Name: MT_AvoidSpurs
1329**
1330** Description: Main entry point to avoid spurs.
1331** Checks for existing spurs in present LO1, LO2 freqs
1332** and if present, chooses spur-free LO1, LO2 combination
1333** that tunes the same input/output frequencies.
1334**
1335** Revision History:
1336**
1337** SCR Date Author Description
1338** -------------------------------------------------------------------------
1339** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1340**
1341*****************************************************************************/
1342UData_t MT2063_AvoidSpurs(Handle_t h, struct MT2063_AvoidSpursData_t * pAS_Info)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001343{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001344 UData_t status = MT2063_OK;
1345 UData_t fm, fp; /* restricted range on LO's */
1346 pAS_Info->bSpurAvoided = 0;
1347 pAS_Info->nSpursFound = 0;
1348
1349 if (pAS_Info->maxH1 == 0)
1350 return MT2063_OK;
1351
1352 /*
1353 ** Avoid LO Generated Spurs
1354 **
1355 ** Make sure that have no LO-related spurs within the IF output
1356 ** bandwidth.
1357 **
1358 ** If there is an LO spur in this band, start at the current IF1 frequency
1359 ** and work out until we find a spur-free frequency or run up against the
1360 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1361 ** will be unchanged if a spur-free setting is not found.
1362 */
1363 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1364 if (pAS_Info->bSpurPresent) {
1365 UData_t zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1366 UData_t zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1367 UData_t zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1368 UData_t delta_IF1;
1369 UData_t new_IF1;
1370
1371 /*
1372 ** Spur was found, attempt to find a spur-free 1st IF
1373 */
1374 do {
1375 pAS_Info->nSpursFound++;
1376
1377 /* Raise f_IF1_upper, if needed */
1378 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1379
1380 /* Choose next IF1 that is closest to f_IF1_CENTER */
1381 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1382
1383 if (new_IF1 > zfIF1) {
1384 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1385 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1386 } else {
1387 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1388 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1389 }
1390 zfIF1 = new_IF1;
1391
1392 if (zfIF1 > pAS_Info->f_if1_Center)
1393 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1394 else
1395 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1396 }
1397 /*
1398 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1399 ** and there is a spur in the band (again)
1400 */
1401 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1402 pAS_Info->f_if1_bw)
1403 && (pAS_Info->bSpurPresent =
1404 IsSpurInBand(pAS_Info, &fm, &fp)));
1405
1406 /*
1407 ** Use the LO-spur free values found. If the search went all the way to
1408 ** the 1st IF band edge and always found spurs, just leave the original
1409 ** choice. It's as "good" as any other.
1410 */
1411 if (pAS_Info->bSpurPresent == 1) {
1412 status |= MT2063_SPUR_PRESENT_ERR;
1413 pAS_Info->f_LO1 = zfLO1;
1414 pAS_Info->f_LO2 = zfLO2;
1415 } else
1416 pAS_Info->bSpurAvoided = 1;
1417 }
1418
1419 status |=
1420 ((pAS_Info->
1421 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1422
1423 return (status);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03001424}
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03001425
1426UData_t MT2063_AvoidSpursVersion(void)
1427{
1428 return (MT2063_SPUR_VERSION);
1429}
1430
1431//end of mt2063_spuravoid.c
1432//=================================================================
1433//#################################################################
1434//=================================================================
1435
1436/*
1437** The expected version of MT_AvoidSpursData_t
1438** If the version is different, an updated file is needed from Microtune
1439*/
1440/* Expecting version 1.21 of the Spur Avoidance API */
1441#define EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION 010201
1442
1443#if MT2063_AVOID_SPURS_INFO_VERSION < EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION
1444#error Contact Microtune for a newer version of MT_SpurAvoid.c
1445#elif MT2063_AVOID_SPURS_INFO_VERSION > EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION
1446#error Contact Microtune for a newer version of mt2063.c
1447#endif
1448
1449#ifndef MT2063_CNT
1450#error You must define MT2063_CNT in the "mt_userdef.h" file
1451#endif
1452
1453typedef enum {
1454 MT2063_SET_ATTEN,
1455 MT2063_INCR_ATTEN,
1456 MT2063_DECR_ATTEN
1457} MT2063_ATTEN_CNTL_MODE;
1458
1459//#define TUNER_MT2063_OPTIMIZATION
1460/*
1461** Constants used by the tuning algorithm
1462*/
1463#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1464#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1465#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1466#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1467#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1468#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1469#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1470#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1471#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1472#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1473#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1474#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1475#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1476#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1477#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1478#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1479#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1480#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1481
1482/*
1483** Define the supported Part/Rev codes for the MT2063
1484*/
1485#define MT2063_B0 (0x9B)
1486#define MT2063_B1 (0x9C)
1487#define MT2063_B2 (0x9D)
1488#define MT2063_B3 (0x9E)
1489
1490/*
1491** The number of Tuner Registers
1492*/
1493static const UData_t MT2063_Num_Registers = MT2063_REG_END_REGS;
1494
1495#define USE_GLOBAL_TUNER 0
1496
1497static UData_t nMT2063MaxTuners = MT2063_CNT;
1498static struct MT2063_Info_t MT2063_Info[MT2063_CNT];
1499static struct MT2063_Info_t *MT2063_Avail[MT2063_CNT];
1500static UData_t nMT2063OpenTuners = 0;
1501
1502/*
1503** Constants for setting receiver modes.
1504** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1505** (DNC1GC & DNC2GC are the values, which are used, when the specific
1506** DNC Output is selected, the other is always off)
1507**
1508** If PAL-L or L' is received, set:
1509** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1510**
1511** --------------+----------------------------------------------
1512** Mode 0 : | MT2063_CABLE_QAM
1513** Mode 1 : | MT2063_CABLE_ANALOG
1514** Mode 2 : | MT2063_OFFAIR_COFDM
1515** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1516** Mode 4 : | MT2063_OFFAIR_ANALOG
1517** Mode 5 : | MT2063_OFFAIR_8VSB
1518** --------------+----+----+----+----+-----+-----+--------------
1519** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1520** --------------+----+----+----+----+-----+-----+
1521**
1522**
1523*/
1524static const U8Data RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1525static const U8Data LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1526static const U8Data FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1527static const U8Data FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1528static const U8Data DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1529static const U8Data DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1530static const U8Data ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1531static const U8Data LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1532static const U8Data RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1533static const U8Data ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1534static const U8Data PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1535static const U8Data FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1536static const U8Data ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1537static const U8Data PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
1538
1539/*
1540** Local Function Prototypes - not available for external access.
1541*/
1542
1543/* Forward declaration(s): */
1544static UData_t MT2063_CalcLO1Mult(UData_t * Div, UData_t * FracN, UData_t f_LO,
1545 UData_t f_LO_Step, UData_t f_Ref);
1546static UData_t MT2063_CalcLO2Mult(UData_t * Div, UData_t * FracN, UData_t f_LO,
1547 UData_t f_LO_Step, UData_t f_Ref);
1548static UData_t MT2063_fLO_FractionalTerm(UData_t f_ref, UData_t num,
1549 UData_t denom);
1550
1551/******************************************************************************
1552**
1553** Name: MT2063_Open
1554**
1555** Description: Initialize the tuner's register values.
1556**
1557** Parameters: MT2063_Addr - Serial bus address of the tuner.
1558** hMT2063 - Tuner handle passed back.
1559** hUserData - User-defined data, if needed for the
1560** MT_ReadSub() & MT_WriteSub functions.
1561**
1562** Returns: status:
1563** MT_OK - No errors
1564** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1565** MT_TUNER_INIT_ERR - Tuner initialization failed
1566** MT_COMM_ERR - Serial bus communications error
1567** MT_ARG_NULL - Null pointer argument passed
1568** MT_TUNER_CNT_ERR - Too many tuners open
1569**
1570** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1571** MT_WriteSub - Write byte(s) of data to the two-wire bus
1572**
1573** Revision History:
1574**
1575** SCR Date Author Description
1576** -------------------------------------------------------------------------
1577** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1578**
1579******************************************************************************/
1580UData_t MT2063_Open(UData_t MT2063_Addr, Handle_t * hMT2063, Handle_t hUserData)
1581{
1582 UData_t status = MT2063_OK; /* Status to be returned. */
1583 SData_t i;
1584 struct MT2063_Info_t *pInfo = NULL;
1585 struct dvb_frontend *fe = (struct dvb_frontend *)hUserData;
1586 struct mt2063_state *state = fe->tuner_priv;
1587
1588 /* Check the argument before using */
1589 if (hMT2063 == NULL) {
1590 return MT2063_ARG_NULL;
1591 }
1592
1593 /* Default tuner handle to NULL. If successful, it will be reassigned */
1594
1595#if USE_GLOBAL_TUNER
1596 *hMT2063 = NULL;
1597
1598 /*
1599 ** If this is our first tuner, initialize the address fields and
1600 ** the list of available control blocks.
1601 */
1602 if (nMT2063OpenTuners == 0) {
1603 for (i = MT2063_CNT - 1; i >= 0; i--) {
1604 MT2063_Info[i].handle = NULL;
1605 MT2063_Info[i].address = MAX_UDATA;
1606 MT2063_Info[i].rcvr_mode = MT2063_CABLE_QAM;
1607 MT2063_Info[i].hUserData = NULL;
1608 MT2063_Avail[i] = &MT2063_Info[i];
1609 }
1610 }
1611
1612 /*
1613 ** Look for an existing MT2063_State_t entry with this address.
1614 */
1615 for (i = MT2063_CNT - 1; i >= 0; i--) {
1616 /*
1617 ** If an open'ed handle provided, we'll re-initialize that structure.
1618 **
1619 ** We recognize an open tuner because the address and hUserData are
1620 ** the same as one that has already been opened
1621 */
1622 if ((MT2063_Info[i].address == MT2063_Addr) &&
1623 (MT2063_Info[i].hUserData == hUserData)) {
1624 pInfo = &MT2063_Info[i];
1625 break;
1626 }
1627 }
1628
1629 /* If not found, choose an empty spot. */
1630 if (pInfo == NULL) {
1631 /* Check to see that we're not over-allocating */
1632 if (nMT2063OpenTuners == MT2063_CNT) {
1633 return MT2063_TUNER_CNT_ERR;
1634 }
1635 /* Use the next available block from the list */
1636 pInfo = MT2063_Avail[nMT2063OpenTuners];
1637 nMT2063OpenTuners++;
1638 }
1639#else
1640 if (state->MT2063_init == FALSE) {
1641 pInfo = kzalloc(sizeof(struct MT2063_Info_t), GFP_KERNEL);
1642 if (pInfo == NULL) {
1643 return MT2063_TUNER_OPEN_ERR;
1644 }
1645 pInfo->handle = NULL;
1646 pInfo->address = MAX_UDATA;
1647 pInfo->rcvr_mode = MT2063_CABLE_QAM;
1648 pInfo->hUserData = NULL;
1649 } else {
1650 pInfo = *hMT2063;
1651 }
1652#endif
1653
1654 if (MT2063_NO_ERROR(status)) {
1655 status |= MT2063_RegisterTuner(&pInfo->AS_Data);
1656 }
1657
1658 if (MT2063_NO_ERROR(status)) {
1659 pInfo->handle = (Handle_t) pInfo;
1660
1661 pInfo->hUserData = hUserData;
1662 pInfo->address = MT2063_Addr;
1663 pInfo->rcvr_mode = MT2063_CABLE_QAM;
1664 status |= MT2063_ReInit((Handle_t) pInfo);
1665 }
1666
1667 if (MT2063_IS_ERROR(status))
1668 /* MT2063_Close handles the un-registration of the tuner */
1669 MT2063_Close((Handle_t) pInfo);
1670 else {
1671 state->MT2063_init = TRUE;
1672 *hMT2063 = pInfo->handle;
1673
1674 }
1675
1676 return (status);
1677}
1678
1679static UData_t MT2063_IsValidHandle(struct MT2063_Info_t *handle)
1680{
1681 return ((handle != NULL) && (handle->handle == handle)) ? 1 : 0;
1682}
1683
1684/******************************************************************************
1685**
1686** Name: MT2063_Close
1687**
1688** Description: Release the handle to the tuner.
1689**
1690** Parameters: hMT2063 - Handle to the MT2063 tuner
1691**
1692** Returns: status:
1693** MT_OK - No errors
1694** MT_INV_HANDLE - Invalid tuner handle
1695**
1696** Dependencies: mt_errordef.h - definition of error codes
1697**
1698** Revision History:
1699**
1700** SCR Date Author Description
1701** -------------------------------------------------------------------------
1702** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1703**
1704******************************************************************************/
1705UData_t MT2063_Close(Handle_t hMT2063)
1706{
1707 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)hMT2063;
1708
1709 if (!MT2063_IsValidHandle(pInfo))
1710 return MT2063_INV_HANDLE;
1711
1712 /* Unregister tuner with SpurAvoidance routines (if needed) */
1713 MT2063_UnRegisterTuner(&pInfo->AS_Data);
1714 /* Now remove the tuner from our own list of tuners */
1715 pInfo->handle = NULL;
1716 pInfo->address = MAX_UDATA;
1717 pInfo->hUserData = NULL;
1718#if USE_GLOBAL_TUNER
1719 nMT2063OpenTuners--;
1720 MT2063_Avail[nMT2063OpenTuners] = pInfo; /* Return control block to available list */
1721#else
1722 //kfree(pInfo);
1723 //pInfo = NULL;
1724#endif
1725 return MT2063_OK;
1726}
1727
1728/******************************************************************************
1729**
1730** Name: MT2063_GetGPIO
1731**
1732** Description: Get the current MT2063 GPIO value.
1733**
1734** Parameters: h - Open handle to the tuner (from MT2063_Open).
1735** gpio_id - Selects GPIO0, GPIO1 or GPIO2
1736** attr - Selects input readback, I/O direction or
1737** output value
1738** *value - current setting of GPIO pin
1739**
1740** Usage: status = MT2063_GetGPIO(hMT2063, MT2063_GPIO_OUT, &value);
1741**
1742** Returns: status:
1743** MT_OK - No errors
1744** MT_COMM_ERR - Serial bus communications error
1745** MT_INV_HANDLE - Invalid tuner handle
1746** MT_ARG_NULL - Null pointer argument passed
1747**
1748** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1749**
1750** Revision History:
1751**
1752** SCR Date Author Description
1753** -------------------------------------------------------------------------
1754** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1755**
1756******************************************************************************/
1757UData_t MT2063_GetGPIO(Handle_t h, enum MT2063_GPIO_ID gpio_id,
1758 enum MT2063_GPIO_Attr attr, UData_t * value)
1759{
1760 UData_t status = MT2063_OK; /* Status to be returned */
1761 U8Data regno;
1762 SData_t shift;
1763 static U8Data GPIOreg[3] =
1764 { MT2063_REG_RF_STATUS, MT2063_REG_FIF_OV, MT2063_REG_RF_OV };
1765 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1766
1767 if (MT2063_IsValidHandle(pInfo) == 0)
1768 return MT2063_INV_HANDLE;
1769
1770 if (value == NULL)
1771 return MT2063_ARG_NULL;
1772
1773 regno = GPIOreg[attr];
1774
1775 /* We'll read the register just in case the write didn't work last time */
1776 status =
1777 MT2063_ReadSub(pInfo->hUserData, pInfo->address, regno,
1778 &pInfo->reg[regno], 1);
1779
1780 shift = (gpio_id - MT2063_GPIO0 + 5);
1781 *value = (pInfo->reg[regno] >> shift) & 1;
1782
1783 return (status);
1784}
1785
1786/****************************************************************************
1787**
1788** Name: MT2063_GetLocked
1789**
1790** Description: Checks to see if LO1 and LO2 are locked.
1791**
1792** Parameters: h - Open handle to the tuner (from MT2063_Open).
1793**
1794** Returns: status:
1795** MT_OK - No errors
1796** MT_UPC_UNLOCK - Upconverter PLL unlocked
1797** MT_DNC_UNLOCK - Downconverter PLL unlocked
1798** MT_COMM_ERR - Serial bus communications error
1799** MT_INV_HANDLE - Invalid tuner handle
1800**
1801** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1802** MT_Sleep - Delay execution for x milliseconds
1803**
1804** Revision History:
1805**
1806** SCR Date Author Description
1807** -------------------------------------------------------------------------
1808** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1809**
1810****************************************************************************/
1811UData_t MT2063_GetLocked(Handle_t h)
1812{
1813 const UData_t nMaxWait = 100; /* wait a maximum of 100 msec */
1814 const UData_t nPollRate = 2; /* poll status bits every 2 ms */
1815 const UData_t nMaxLoops = nMaxWait / nPollRate;
1816 const U8Data LO1LK = 0x80;
1817 U8Data LO2LK = 0x08;
1818 UData_t status = MT2063_OK; /* Status to be returned */
1819 UData_t nDelays = 0;
1820 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1821
1822 if (MT2063_IsValidHandle(pInfo) == 0)
1823 return MT2063_INV_HANDLE;
1824
1825 /* LO2 Lock bit was in a different place for B0 version */
1826 if (pInfo->tuner_id == MT2063_B0)
1827 LO2LK = 0x40;
1828
1829 do {
1830 status |=
1831 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
1832 MT2063_REG_LO_STATUS,
1833 &pInfo->reg[MT2063_REG_LO_STATUS], 1);
1834
1835 if (MT2063_IS_ERROR(status))
1836 return (status);
1837
1838 if ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
1839 (LO1LK | LO2LK)) {
1840 return (status);
1841 }
1842 MT2063_Sleep(pInfo->hUserData, nPollRate); /* Wait between retries */
1843 }
1844 while (++nDelays < nMaxLoops);
1845
1846 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
1847 status |= MT2063_UPC_UNLOCK;
1848 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
1849 status |= MT2063_DNC_UNLOCK;
1850
1851 return (status);
1852}
1853
1854/****************************************************************************
1855**
1856** Name: MT2063_GetParam
1857**
1858** Description: Gets a tuning algorithm parameter.
1859**
1860** This function provides access to the internals of the
1861** tuning algorithm - mostly for testing purposes.
1862**
1863** Parameters: h - Tuner handle (returned by MT2063_Open)
1864** param - Tuning algorithm parameter
1865** (see enum MT2063_Param)
1866** pValue - ptr to returned value
1867**
1868** param Description
1869** ---------------------- --------------------------------
1870** MT2063_IC_ADDR Serial Bus address of this tuner
1871** MT2063_MAX_OPEN Max # of MT2063's allowed open
1872** MT2063_NUM_OPEN # of MT2063's open
1873** MT2063_SRO_FREQ crystal frequency
1874** MT2063_STEPSIZE minimum tuning step size
1875** MT2063_INPUT_FREQ input center frequency
1876** MT2063_LO1_FREQ LO1 Frequency
1877** MT2063_LO1_STEPSIZE LO1 minimum step size
1878** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1879** MT2063_IF1_ACTUAL Current 1st IF in use
1880** MT2063_IF1_REQUEST Requested 1st IF
1881** MT2063_IF1_CENTER Center of 1st IF SAW filter
1882** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1883** MT2063_ZIF_BW zero-IF bandwidth
1884** MT2063_LO2_FREQ LO2 Frequency
1885** MT2063_LO2_STEPSIZE LO2 minimum step size
1886** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1887** MT2063_OUTPUT_FREQ output center frequency
1888** MT2063_OUTPUT_BW output bandwidth
1889** MT2063_LO_SEPARATION min inter-tuner LO separation
1890** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1891** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1892** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1893** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1894** MT2063_NUM_SPURS # of spurs found/avoided
1895** MT2063_SPUR_AVOIDED >0 spurs avoided
1896** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1897** MT2063_RCVR_MODE Predefined modes.
1898** MT2063_ACLNA LNA attenuator gain code
1899** MT2063_ACRF RF attenuator gain code
1900** MT2063_ACFIF FIF attenuator gain code
1901** MT2063_ACLNA_MAX LNA attenuator limit
1902** MT2063_ACRF_MAX RF attenuator limit
1903** MT2063_ACFIF_MAX FIF attenuator limit
1904** MT2063_PD1 Actual value of PD1
1905** MT2063_PD2 Actual value of PD2
1906** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1907** MT2063_VGAGC VGA gain code
1908** MT2063_VGAOI VGA output current
1909** MT2063_TAGC TAGC setting
1910** MT2063_AMPGC AMP gain code
1911** MT2063_AVOID_DECT Avoid DECT Frequencies
1912** MT2063_CTFILT_SW Cleartune filter selection
1913**
1914** Usage: status |= MT2063_GetParam(hMT2063,
1915** MT2063_IF1_ACTUAL,
1916** &f_IF1_Actual);
1917**
1918** Returns: status:
1919** MT_OK - No errors
1920** MT_INV_HANDLE - Invalid tuner handle
1921** MT_ARG_NULL - Null pointer argument passed
1922** MT_ARG_RANGE - Invalid parameter requested
1923**
1924** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1925**
1926** See Also: MT2063_SetParam, MT2063_Open
1927**
1928** Revision History:
1929**
1930** SCR Date Author Description
1931** -------------------------------------------------------------------------
1932** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1933** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1934** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1935** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1936** in GetParam.
1937** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1938** Split SetParam up to ACLNA / ACLNA_MAX
1939** removed ACLNA_INRC/DECR (+RF & FIF)
1940** removed GCUAUTO / BYPATNDN/UP
1941** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1942** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1943** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1944**
1945****************************************************************************/
1946UData_t MT2063_GetParam(Handle_t h, enum MT2063_Param param, UData_t * pValue)
1947{
1948 UData_t status = MT2063_OK; /* Status to be returned */
1949 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1950 UData_t Div;
1951 UData_t Num;
1952
1953 if (pValue == NULL)
1954 status |= MT2063_ARG_NULL;
1955
1956 /* Verify that the handle passed points to a valid tuner */
1957 if (MT2063_IsValidHandle(pInfo) == 0)
1958 status |= MT2063_INV_HANDLE;
1959
1960 if (MT2063_NO_ERROR(status)) {
1961 switch (param) {
1962 /* Serial Bus address of this tuner */
1963 case MT2063_IC_ADDR:
1964 *pValue = pInfo->address;
1965 break;
1966
1967 /* Max # of MT2063's allowed to be open */
1968 case MT2063_MAX_OPEN:
1969 *pValue = nMT2063MaxTuners;
1970 break;
1971
1972 /* # of MT2063's open */
1973 case MT2063_NUM_OPEN:
1974 *pValue = nMT2063OpenTuners;
1975 break;
1976
1977 /* crystal frequency */
1978 case MT2063_SRO_FREQ:
1979 *pValue = pInfo->AS_Data.f_ref;
1980 break;
1981
1982 /* minimum tuning step size */
1983 case MT2063_STEPSIZE:
1984 *pValue = pInfo->AS_Data.f_LO2_Step;
1985 break;
1986
1987 /* input center frequency */
1988 case MT2063_INPUT_FREQ:
1989 *pValue = pInfo->AS_Data.f_in;
1990 break;
1991
1992 /* LO1 Frequency */
1993 case MT2063_LO1_FREQ:
1994 {
1995 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1996 status |=
1997 MT2063_ReadSub(pInfo->hUserData,
1998 pInfo->address,
1999 MT2063_REG_LO1C_1,
2000 &pInfo->
2001 reg[MT2063_REG_LO1C_1], 2);
2002 Div = pInfo->reg[MT2063_REG_LO1C_1];
2003 Num = pInfo->reg[MT2063_REG_LO1C_2] & 0x3F;
2004 pInfo->AS_Data.f_LO1 =
2005 (pInfo->AS_Data.f_ref * Div) +
2006 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2007 f_ref, Num, 64);
2008 }
2009 *pValue = pInfo->AS_Data.f_LO1;
2010 break;
2011
2012 /* LO1 minimum step size */
2013 case MT2063_LO1_STEPSIZE:
2014 *pValue = pInfo->AS_Data.f_LO1_Step;
2015 break;
2016
2017 /* LO1 FracN keep-out region */
2018 case MT2063_LO1_FRACN_AVOID_PARAM:
2019 *pValue = pInfo->AS_Data.f_LO1_FracN_Avoid;
2020 break;
2021
2022 /* Current 1st IF in use */
2023 case MT2063_IF1_ACTUAL:
2024 *pValue = pInfo->f_IF1_actual;
2025 break;
2026
2027 /* Requested 1st IF */
2028 case MT2063_IF1_REQUEST:
2029 *pValue = pInfo->AS_Data.f_if1_Request;
2030 break;
2031
2032 /* Center of 1st IF SAW filter */
2033 case MT2063_IF1_CENTER:
2034 *pValue = pInfo->AS_Data.f_if1_Center;
2035 break;
2036
2037 /* Bandwidth of 1st IF SAW filter */
2038 case MT2063_IF1_BW:
2039 *pValue = pInfo->AS_Data.f_if1_bw;
2040 break;
2041
2042 /* zero-IF bandwidth */
2043 case MT2063_ZIF_BW:
2044 *pValue = pInfo->AS_Data.f_zif_bw;
2045 break;
2046
2047 /* LO2 Frequency */
2048 case MT2063_LO2_FREQ:
2049 {
2050 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
2051 status |=
2052 MT2063_ReadSub(pInfo->hUserData,
2053 pInfo->address,
2054 MT2063_REG_LO2C_1,
2055 &pInfo->
2056 reg[MT2063_REG_LO2C_1], 3);
2057 Div =
2058 (pInfo->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
2059 Num =
2060 ((pInfo->
2061 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
2062 (pInfo->
2063 reg[MT2063_REG_LO2C_2] << 4) | (pInfo->
2064 reg
2065 [MT2063_REG_LO2C_3]
2066 & 0x00F);
2067 pInfo->AS_Data.f_LO2 =
2068 (pInfo->AS_Data.f_ref * Div) +
2069 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
2070 f_ref, Num, 8191);
2071 }
2072 *pValue = pInfo->AS_Data.f_LO2;
2073 break;
2074
2075 /* LO2 minimum step size */
2076 case MT2063_LO2_STEPSIZE:
2077 *pValue = pInfo->AS_Data.f_LO2_Step;
2078 break;
2079
2080 /* LO2 FracN keep-out region */
2081 case MT2063_LO2_FRACN_AVOID:
2082 *pValue = pInfo->AS_Data.f_LO2_FracN_Avoid;
2083 break;
2084
2085 /* output center frequency */
2086 case MT2063_OUTPUT_FREQ:
2087 *pValue = pInfo->AS_Data.f_out;
2088 break;
2089
2090 /* output bandwidth */
2091 case MT2063_OUTPUT_BW:
2092 *pValue = pInfo->AS_Data.f_out_bw - 750000;
2093 break;
2094
2095 /* min inter-tuner LO separation */
2096 case MT2063_LO_SEPARATION:
2097 *pValue = pInfo->AS_Data.f_min_LO_Separation;
2098 break;
2099
2100 /* ID of avoid-spurs algorithm in use */
2101 case MT2063_AS_ALG:
2102 *pValue = pInfo->AS_Data.nAS_Algorithm;
2103 break;
2104
2105 /* max # of intra-tuner harmonics */
2106 case MT2063_MAX_HARM1:
2107 *pValue = pInfo->AS_Data.maxH1;
2108 break;
2109
2110 /* max # of inter-tuner harmonics */
2111 case MT2063_MAX_HARM2:
2112 *pValue = pInfo->AS_Data.maxH2;
2113 break;
2114
2115 /* # of 1st IF exclusion zones */
2116 case MT2063_EXCL_ZONES:
2117 *pValue = pInfo->AS_Data.nZones;
2118 break;
2119
2120 /* # of spurs found/avoided */
2121 case MT2063_NUM_SPURS:
2122 *pValue = pInfo->AS_Data.nSpursFound;
2123 break;
2124
2125 /* >0 spurs avoided */
2126 case MT2063_SPUR_AVOIDED:
2127 *pValue = pInfo->AS_Data.bSpurAvoided;
2128 break;
2129
2130 /* >0 spurs in output (mathematically) */
2131 case MT2063_SPUR_PRESENT:
2132 *pValue = pInfo->AS_Data.bSpurPresent;
2133 break;
2134
2135 /* Predefined receiver setup combination */
2136 case MT2063_RCVR_MODE:
2137 *pValue = pInfo->rcvr_mode;
2138 break;
2139
2140 case MT2063_PD1:
2141 case MT2063_PD2:
2142 {
2143 U8Data mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
2144 U8Data orig = (pInfo->reg[MT2063_REG_BYP_CTRL]);
2145 U8Data reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
2146 int i;
2147
2148 *pValue = 0;
2149
2150 /* Initiate ADC output to reg 0x0A */
2151 if (reg != orig)
2152 status |=
2153 MT2063_WriteSub(pInfo->hUserData,
2154 pInfo->address,
2155 MT2063_REG_BYP_CTRL,
2156 &reg, 1);
2157
2158 if (MT2063_IS_ERROR(status))
2159 return (status);
2160
2161 for (i = 0; i < 8; i++) {
2162 status |=
2163 MT2063_ReadSub(pInfo->hUserData,
2164 pInfo->address,
2165 MT2063_REG_ADC_OUT,
2166 &pInfo->
2167 reg
2168 [MT2063_REG_ADC_OUT],
2169 1);
2170
2171 if (MT2063_NO_ERROR(status))
2172 *pValue +=
2173 pInfo->
2174 reg[MT2063_REG_ADC_OUT];
2175 else {
2176 if (i)
2177 *pValue /= i;
2178 return (status);
2179 }
2180 }
2181 *pValue /= 8; /* divide by number of reads */
2182 *pValue >>= 2; /* only want 6 MSB's out of 8 */
2183
2184 /* Restore value of Register BYP_CTRL */
2185 if (reg != orig)
2186 status |=
2187 MT2063_WriteSub(pInfo->hUserData,
2188 pInfo->address,
2189 MT2063_REG_BYP_CTRL,
2190 &orig, 1);
2191 }
2192 break;
2193
2194 /* Get LNA attenuator code */
2195 case MT2063_ACLNA:
2196 {
2197 U8Data val;
2198 status |=
2199 MT2063_GetReg(pInfo, MT2063_REG_XO_STATUS,
2200 &val);
2201 *pValue = val & 0x1f;
2202 }
2203 break;
2204
2205 /* Get RF attenuator code */
2206 case MT2063_ACRF:
2207 {
2208 U8Data val;
2209 status |=
2210 MT2063_GetReg(pInfo, MT2063_REG_RF_STATUS,
2211 &val);
2212 *pValue = val & 0x1f;
2213 }
2214 break;
2215
2216 /* Get FIF attenuator code */
2217 case MT2063_ACFIF:
2218 {
2219 U8Data val;
2220 status |=
2221 MT2063_GetReg(pInfo, MT2063_REG_FIF_STATUS,
2222 &val);
2223 *pValue = val & 0x1f;
2224 }
2225 break;
2226
2227 /* Get LNA attenuator limit */
2228 case MT2063_ACLNA_MAX:
2229 {
2230 U8Data val;
2231 status |=
2232 MT2063_GetReg(pInfo, MT2063_REG_LNA_OV,
2233 &val);
2234 *pValue = val & 0x1f;
2235 }
2236 break;
2237
2238 /* Get RF attenuator limit */
2239 case MT2063_ACRF_MAX:
2240 {
2241 U8Data val;
2242 status |=
2243 MT2063_GetReg(pInfo, MT2063_REG_RF_OV,
2244 &val);
2245 *pValue = val & 0x1f;
2246 }
2247 break;
2248
2249 /* Get FIF attenuator limit */
2250 case MT2063_ACFIF_MAX:
2251 {
2252 U8Data val;
2253 status |=
2254 MT2063_GetReg(pInfo, MT2063_REG_FIF_OV,
2255 &val);
2256 *pValue = val & 0x1f;
2257 }
2258 break;
2259
2260 /* Get current used DNC output */
2261 case MT2063_DNC_OUTPUT_ENABLE:
2262 {
2263 if ((pInfo->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
2264 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2265 *pValue =
2266 (UData_t) MT2063_DNC_NONE;
2267 else
2268 *pValue =
2269 (UData_t) MT2063_DNC_2;
2270 } else { /* DNC1 is on */
2271
2272 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2273 *pValue =
2274 (UData_t) MT2063_DNC_1;
2275 else
2276 *pValue =
2277 (UData_t) MT2063_DNC_BOTH;
2278 }
2279 }
2280 break;
2281
2282 /* Get VGA Gain Code */
2283 case MT2063_VGAGC:
2284 *pValue =
2285 ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
2286 break;
2287
2288 /* Get VGA bias current */
2289 case MT2063_VGAOI:
2290 *pValue = (pInfo->reg[MT2063_REG_RSVD_31] & 0x07);
2291 break;
2292
2293 /* Get TAGC setting */
2294 case MT2063_TAGC:
2295 *pValue = (pInfo->reg[MT2063_REG_RSVD_1E] & 0x03);
2296 break;
2297
2298 /* Get AMP Gain Code */
2299 case MT2063_AMPGC:
2300 *pValue = (pInfo->reg[MT2063_REG_TEMP_SEL] & 0x03);
2301 break;
2302
2303 /* Avoid DECT Frequencies */
2304 case MT2063_AVOID_DECT:
2305 *pValue = pInfo->AS_Data.avoidDECT;
2306 break;
2307
2308 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2309 case MT2063_CTFILT_SW:
2310 *pValue = pInfo->ctfilt_sw;
2311 break;
2312
2313 case MT2063_EOP:
2314 default:
2315 status |= MT2063_ARG_RANGE;
2316 }
2317 }
2318 return (status);
2319}
2320
2321/****************************************************************************
2322**
2323** Name: MT2063_GetReg
2324**
2325** Description: Gets an MT2063 register.
2326**
2327** Parameters: h - Tuner handle (returned by MT2063_Open)
2328** reg - MT2063 register/subaddress location
2329** *val - MT2063 register/subaddress value
2330**
2331** Returns: status:
2332** MT_OK - No errors
2333** MT_COMM_ERR - Serial bus communications error
2334** MT_INV_HANDLE - Invalid tuner handle
2335** MT_ARG_NULL - Null pointer argument passed
2336** MT_ARG_RANGE - Argument out of range
2337**
2338** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2339**
2340** Use this function if you need to read a register from
2341** the MT2063.
2342**
2343** Revision History:
2344**
2345** SCR Date Author Description
2346** -------------------------------------------------------------------------
2347** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2348**
2349****************************************************************************/
2350UData_t MT2063_GetReg(Handle_t h, U8Data reg, U8Data * val)
2351{
2352 UData_t status = MT2063_OK; /* Status to be returned */
2353 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2354
2355 /* Verify that the handle passed points to a valid tuner */
2356 if (MT2063_IsValidHandle(pInfo) == 0)
2357 status |= MT2063_INV_HANDLE;
2358
2359 if (val == NULL)
2360 status |= MT2063_ARG_NULL;
2361
2362 if (reg >= MT2063_REG_END_REGS)
2363 status |= MT2063_ARG_RANGE;
2364
2365 if (MT2063_NO_ERROR(status)) {
2366 status |=
2367 MT2063_ReadSub(pInfo->hUserData, pInfo->address, reg,
2368 &pInfo->reg[reg], 1);
2369 if (MT2063_NO_ERROR(status))
2370 *val = pInfo->reg[reg];
2371 }
2372
2373 return (status);
2374}
2375
2376/******************************************************************************
2377**
2378** Name: MT2063_GetTemp
2379**
2380** Description: Get the MT2063 Temperature register.
2381**
2382** Parameters: h - Open handle to the tuner (from MT2063_Open).
2383** *value - value read from the register
2384**
2385** Binary
2386** Value Returned Value Approx Temp
2387** ---------------------------------------------
2388** MT2063_T_0C 0000 0C
2389** MT2063_T_10C 0001 10C
2390** MT2063_T_20C 0010 20C
2391** MT2063_T_30C 0011 30C
2392** MT2063_T_40C 0100 40C
2393** MT2063_T_50C 0101 50C
2394** MT2063_T_60C 0110 60C
2395** MT2063_T_70C 0111 70C
2396** MT2063_T_80C 1000 80C
2397** MT2063_T_90C 1001 90C
2398** MT2063_T_100C 1010 100C
2399** MT2063_T_110C 1011 110C
2400** MT2063_T_120C 1100 120C
2401** MT2063_T_130C 1101 130C
2402** MT2063_T_140C 1110 140C
2403** MT2063_T_150C 1111 150C
2404**
2405** Returns: status:
2406** MT_OK - No errors
2407** MT_COMM_ERR - Serial bus communications error
2408** MT_INV_HANDLE - Invalid tuner handle
2409** MT_ARG_NULL - Null pointer argument passed
2410** MT_ARG_RANGE - Argument out of range
2411**
2412** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2413** MT_WriteSub - Write byte(s) of data to the two-wire bus
2414**
2415** Revision History:
2416**
2417** SCR Date Author Description
2418** -------------------------------------------------------------------------
2419** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2420**
2421******************************************************************************/
2422UData_t MT2063_GetTemp(Handle_t h, enum MT2063_Temperature * value)
2423{
2424 UData_t status = MT2063_OK; /* Status to be returned */
2425 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2426
2427 if (MT2063_IsValidHandle(pInfo) == 0)
2428 return MT2063_INV_HANDLE;
2429
2430 if (value == NULL)
2431 return MT2063_ARG_NULL;
2432
2433 if ((MT2063_NO_ERROR(status))
2434 && ((pInfo->reg[MT2063_REG_TEMP_SEL] & 0xE0) != 0x00)) {
2435 pInfo->reg[MT2063_REG_TEMP_SEL] &= (0x1F);
2436 status |= MT2063_WriteSub(pInfo->hUserData,
2437 pInfo->address,
2438 MT2063_REG_TEMP_SEL,
2439 &pInfo->reg[MT2063_REG_TEMP_SEL], 1);
2440 }
2441
2442 if (MT2063_NO_ERROR(status))
2443 status |= MT2063_ReadSub(pInfo->hUserData,
2444 pInfo->address,
2445 MT2063_REG_TEMP_STATUS,
2446 &pInfo->reg[MT2063_REG_TEMP_STATUS],
2447 1);
2448
2449 if (MT2063_NO_ERROR(status))
2450 *value =
2451 (enum MT2063_Temperature)(pInfo->
2452 reg[MT2063_REG_TEMP_STATUS] >> 4);
2453
2454 return (status);
2455}
2456
2457/****************************************************************************
2458**
2459** Name: MT2063_GetUserData
2460**
2461** Description: Gets the user-defined data item.
2462**
2463** Parameters: h - Tuner handle (returned by MT2063_Open)
2464**
2465** Returns: status:
2466** MT_OK - No errors
2467** MT_INV_HANDLE - Invalid tuner handle
2468** MT_ARG_NULL - Null pointer argument passed
2469**
2470** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2471**
2472** The hUserData parameter is a user-specific argument
2473** that is stored internally with the other tuner-
2474** specific information.
2475**
2476** For example, if additional arguments are needed
2477** for the user to identify the device communicating
2478** with the tuner, this argument can be used to supply
2479** the necessary information.
2480**
2481** The hUserData parameter is initialized in the tuner's
2482** Open function to NULL.
2483**
2484** See Also: MT2063_Open
2485**
2486** Revision History:
2487**
2488** SCR Date Author Description
2489** -------------------------------------------------------------------------
2490** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2491**
2492****************************************************************************/
2493UData_t MT2063_GetUserData(Handle_t h, Handle_t * hUserData)
2494{
2495 UData_t status = MT2063_OK; /* Status to be returned */
2496 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2497
2498 /* Verify that the handle passed points to a valid tuner */
2499 if (MT2063_IsValidHandle(pInfo) == 0)
2500 status = MT2063_INV_HANDLE;
2501
2502 if (hUserData == NULL)
2503 status |= MT2063_ARG_NULL;
2504
2505 if (MT2063_NO_ERROR(status))
2506 *hUserData = pInfo->hUserData;
2507
2508 return (status);
2509}
2510
2511/******************************************************************************
2512**
2513** Name: MT2063_SetReceiverMode
2514**
2515** Description: Set the MT2063 receiver mode
2516**
2517** --------------+----------------------------------------------
2518** Mode 0 : | MT2063_CABLE_QAM
2519** Mode 1 : | MT2063_CABLE_ANALOG
2520** Mode 2 : | MT2063_OFFAIR_COFDM
2521** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2522** Mode 4 : | MT2063_OFFAIR_ANALOG
2523** Mode 5 : | MT2063_OFFAIR_8VSB
2524** --------------+----+----+----+----+-----+--------------------
2525** (DNC1GC & DNC2GC are the values, which are used, when the specific
2526** DNC Output is selected, the other is always off)
2527**
2528** |<---------- Mode -------------->|
2529** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2530** ------------+-----+-----+-----+-----+-----+-----+
2531** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2532** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2533** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2534** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2535** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2536** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2537** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2538** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2539** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2540** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2541** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2542** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2543** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2544** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2545** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2546**
2547**
2548** Parameters: pInfo - ptr to MT2063_Info_t structure
2549** Mode - desired reciever mode
2550**
2551** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2552**
2553** Returns: status:
2554** MT_OK - No errors
2555** MT_COMM_ERR - Serial bus communications error
2556**
2557** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2558** Assumes that the tuner cache is valid.
2559**
2560** Revision History:
2561**
2562** SCR Date Author Description
2563** -------------------------------------------------------------------------
2564** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2565** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2566** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2567** modulation
2568** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2569** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2570** the same settings as with MT Launcher
2571** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2572** Add SetParam DNC_OUTPUT_ENABLE
2573** Removed VGAGC from receiver mode,
2574** default now 1
2575** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2576** Add SetParam AMPGC, removed from rcvr-mode
2577** Corrected names of GCU values
2578** reorganized receiver modes, removed,
2579** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2580** Actualized Receiver-Mode values
2581** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2582** N/A 11-27-2007 PINZ Improved buffered writing
2583** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2584** correct wakeup of the LNA after shutdown
2585** Set AFCsd = 1 as default
2586** Changed CAP1sel default
2587** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2588** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2589** Split SetParam up to ACLNA / ACLNA_MAX
2590** removed ACLNA_INRC/DECR (+RF & FIF)
2591** removed GCUAUTO / BYPATNDN/UP
2592**
2593******************************************************************************/
2594static UData_t MT2063_SetReceiverMode(struct MT2063_Info_t *pInfo,
2595 enum MT2063_RCVR_MODES Mode)
2596{
2597 UData_t status = MT2063_OK; /* Status to be returned */
2598 U8Data val;
2599 UData_t longval;
2600
2601 if (Mode >= MT2063_NUM_RCVR_MODES)
2602 status = MT2063_ARG_RANGE;
2603
2604 /* RFAGCen */
2605 if (MT2063_NO_ERROR(status)) {
2606 val =
2607 (pInfo->
2608 reg[MT2063_REG_PD1_TGT] & (U8Data) ~ 0x40) | (RFAGCEN[Mode]
2609 ? 0x40 :
2610 0x00);
2611 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2612 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2613 }
2614 }
2615
2616 /* LNARin */
2617 if (MT2063_NO_ERROR(status)) {
2618 status |= MT2063_SetParam(pInfo, MT2063_LNA_RIN, LNARIN[Mode]);
2619 }
2620
2621 /* FIFFQEN and FIFFQ */
2622 if (MT2063_NO_ERROR(status)) {
2623 val =
2624 (pInfo->
2625 reg[MT2063_REG_FIFF_CTRL2] & (U8Data) ~ 0xF0) |
2626 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
2627 if (pInfo->reg[MT2063_REG_FIFF_CTRL2] != val) {
2628 status |=
2629 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL2, val);
2630 /* trigger FIFF calibration, needed after changing FIFFQ */
2631 val =
2632 (pInfo->reg[MT2063_REG_FIFF_CTRL] | (U8Data) 0x01);
2633 status |=
2634 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2635 val =
2636 (pInfo->
2637 reg[MT2063_REG_FIFF_CTRL] & (U8Data) ~ 0x01);
2638 status |=
2639 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2640 }
2641 }
2642
2643 /* DNC1GC & DNC2GC */
2644 status |= MT2063_GetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, &longval);
2645 status |= MT2063_SetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, longval);
2646
2647 /* acLNAmax */
2648 if (MT2063_NO_ERROR(status)) {
2649 status |=
2650 MT2063_SetParam(pInfo, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
2651 }
2652
2653 /* LNATGT */
2654 if (MT2063_NO_ERROR(status)) {
2655 status |= MT2063_SetParam(pInfo, MT2063_LNA_TGT, LNATGT[Mode]);
2656 }
2657
2658 /* ACRF */
2659 if (MT2063_NO_ERROR(status)) {
2660 status |=
2661 MT2063_SetParam(pInfo, MT2063_ACRF_MAX, ACRFMAX[Mode]);
2662 }
2663
2664 /* PD1TGT */
2665 if (MT2063_NO_ERROR(status)) {
2666 status |= MT2063_SetParam(pInfo, MT2063_PD1_TGT, PD1TGT[Mode]);
2667 }
2668
2669 /* FIFATN */
2670 if (MT2063_NO_ERROR(status)) {
2671 status |=
2672 MT2063_SetParam(pInfo, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
2673 }
2674
2675 /* PD2TGT */
2676 if (MT2063_NO_ERROR(status)) {
2677 status |= MT2063_SetParam(pInfo, MT2063_PD2_TGT, PD2TGT[Mode]);
2678 }
2679
2680 /* Ignore ATN Overload */
2681 if (MT2063_NO_ERROR(status)) {
2682 val =
2683 (pInfo->
2684 reg[MT2063_REG_LNA_TGT] & (U8Data) ~ 0x80) | (RFOVDIS[Mode]
2685 ? 0x80 :
2686 0x00);
2687 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
2688 status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val);
2689 }
2690 }
2691
2692 /* Ignore FIF Overload */
2693 if (MT2063_NO_ERROR(status)) {
2694 val =
2695 (pInfo->
2696 reg[MT2063_REG_PD1_TGT] & (U8Data) ~ 0x80) |
2697 (FIFOVDIS[Mode] ? 0x80 : 0x00);
2698 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2699 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2700 }
2701 }
2702
2703 if (MT2063_NO_ERROR(status))
2704 pInfo->rcvr_mode = Mode;
2705
2706 return (status);
2707}
2708
2709/******************************************************************************
2710**
2711** Name: MT2063_ReInit
2712**
2713** Description: Initialize the tuner's register values.
2714**
2715** Parameters: h - Tuner handle (returned by MT2063_Open)
2716**
2717** Returns: status:
2718** MT_OK - No errors
2719** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2720** MT_INV_HANDLE - Invalid tuner handle
2721** MT_COMM_ERR - Serial bus communications error
2722**
2723** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2724** MT_WriteSub - Write byte(s) of data to the two-wire bus
2725**
2726** Revision History:
2727**
2728** SCR Date Author Description
2729** -------------------------------------------------------------------------
2730** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2731** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2732** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2733** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2734** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2735** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2736** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2737** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2738** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2739** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2740** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2741**
2742******************************************************************************/
2743UData_t MT2063_ReInit(Handle_t h)
2744{
2745 U8Data all_resets = 0xF0; /* reset/load bits */
2746 UData_t status = MT2063_OK; /* Status to be returned */
2747 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2748 U8Data *def;
2749
2750 U8Data MT2063B0_defaults[] = { /* Reg, Value */
2751 0x19, 0x05,
2752 0x1B, 0x1D,
2753 0x1C, 0x1F,
2754 0x1D, 0x0F,
2755 0x1E, 0x3F,
2756 0x1F, 0x0F,
2757 0x20, 0x3F,
2758 0x22, 0x21,
2759 0x23, 0x3F,
2760 0x24, 0x20,
2761 0x25, 0x3F,
2762 0x27, 0xEE,
2763 0x2C, 0x27, /* bit at 0x20 is cleared below */
2764 0x30, 0x03,
2765 0x2C, 0x07, /* bit at 0x20 is cleared here */
2766 0x2D, 0x87,
2767 0x2E, 0xAA,
2768 0x28, 0xE1, /* Set the FIFCrst bit here */
2769 0x28, 0xE0, /* Clear the FIFCrst bit here */
2770 0x00
2771 };
2772
2773 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2774 U8Data MT2063B1_defaults[] = { /* Reg, Value */
2775 0x05, 0xF0,
2776 0x11, 0x10, /* New Enable AFCsd */
2777 0x19, 0x05,
2778 0x1A, 0x6C,
2779 0x1B, 0x24,
2780 0x1C, 0x28,
2781 0x1D, 0x8F,
2782 0x1E, 0x14,
2783 0x1F, 0x8F,
2784 0x20, 0x57,
2785 0x22, 0x21, /* New - ver 1.03 */
2786 0x23, 0x3C, /* New - ver 1.10 */
2787 0x24, 0x20, /* New - ver 1.03 */
2788 0x2C, 0x24, /* bit at 0x20 is cleared below */
2789 0x2D, 0x87, /* FIFFQ=0 */
2790 0x2F, 0xF3,
2791 0x30, 0x0C, /* New - ver 1.11 */
2792 0x31, 0x1B, /* New - ver 1.11 */
2793 0x2C, 0x04, /* bit at 0x20 is cleared here */
2794 0x28, 0xE1, /* Set the FIFCrst bit here */
2795 0x28, 0xE0, /* Clear the FIFCrst bit here */
2796 0x00
2797 };
2798
2799 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2800 U8Data MT2063B3_defaults[] = { /* Reg, Value */
2801 0x05, 0xF0,
2802 0x19, 0x3D,
2803 0x2C, 0x24, /* bit at 0x20 is cleared below */
2804 0x2C, 0x04, /* bit at 0x20 is cleared here */
2805 0x28, 0xE1, /* Set the FIFCrst bit here */
2806 0x28, 0xE0, /* Clear the FIFCrst bit here */
2807 0x00
2808 };
2809
2810 /* Verify that the handle passed points to a valid tuner */
2811 if (MT2063_IsValidHandle(pInfo) == 0)
2812 status |= MT2063_INV_HANDLE;
2813
2814 /* Read the Part/Rev code from the tuner */
2815 if (MT2063_NO_ERROR(status)) {
2816 status |=
2817 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2818 MT2063_REG_PART_REV, pInfo->reg, 1);
2819 }
2820
2821 if (MT2063_NO_ERROR(status) /* Check the part/rev code */
2822 &&((pInfo->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2823 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2824 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
2825 status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */
2826
2827 /* Read the Part/Rev code (2nd byte) from the tuner */
2828 if (MT2063_NO_ERROR(status))
2829 status |=
2830 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2831 MT2063_REG_RSVD_3B,
2832 &pInfo->reg[MT2063_REG_RSVD_3B], 1);
2833
2834 if (MT2063_NO_ERROR(status) /* Check the 2nd part/rev code */
2835 &&((pInfo->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
2836 status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */
2837
2838 /* Reset the tuner */
2839 if (MT2063_NO_ERROR(status))
2840 status |= MT2063_WriteSub(pInfo->hUserData,
2841 pInfo->address,
2842 MT2063_REG_LO2CQ_3, &all_resets, 1);
2843
2844 /* change all of the default values that vary from the HW reset values */
2845 /* def = (pInfo->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2846 switch (pInfo->reg[MT2063_REG_PART_REV]) {
2847 case MT2063_B3:
2848 def = MT2063B3_defaults;
2849 break;
2850
2851 case MT2063_B1:
2852 def = MT2063B1_defaults;
2853 break;
2854
2855 case MT2063_B0:
2856 def = MT2063B0_defaults;
2857 break;
2858
2859 default:
2860 status |= MT2063_TUNER_ID_ERR;
2861 break;
2862 }
2863
2864 while (MT2063_NO_ERROR(status) && *def) {
2865 U8Data reg = *def++;
2866 U8Data val = *def++;
2867 status |=
2868 MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
2869 1);
2870 }
2871
2872 /* Wait for FIFF location to complete. */
2873 if (MT2063_NO_ERROR(status)) {
2874 UData_t FCRUN = 1;
2875 SData_t maxReads = 10;
2876 while (MT2063_NO_ERROR(status) && (FCRUN != 0)
2877 && (maxReads-- > 0)) {
2878 MT2063_Sleep(pInfo->hUserData, 2);
2879 status |= MT2063_ReadSub(pInfo->hUserData,
2880 pInfo->address,
2881 MT2063_REG_XO_STATUS,
2882 &pInfo->
2883 reg[MT2063_REG_XO_STATUS], 1);
2884 FCRUN = (pInfo->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
2885 }
2886
2887 if (FCRUN != 0)
2888 status |= MT2063_TUNER_INIT_ERR | MT2063_TUNER_TIMEOUT;
2889
2890 if (MT2063_NO_ERROR(status)) /* Re-read FIFFC value */
2891 status |=
2892 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2893 MT2063_REG_FIFFC,
2894 &pInfo->reg[MT2063_REG_FIFFC], 1);
2895 }
2896
2897 /* Read back all the registers from the tuner */
2898 if (MT2063_NO_ERROR(status))
2899 status |= MT2063_ReadSub(pInfo->hUserData,
2900 pInfo->address,
2901 MT2063_REG_PART_REV,
2902 pInfo->reg, MT2063_REG_END_REGS);
2903
2904 if (MT2063_NO_ERROR(status)) {
2905 /* Initialize the tuner state. */
2906 pInfo->version = MT2063_VERSION;
2907 pInfo->tuner_id = pInfo->reg[MT2063_REG_PART_REV];
2908 pInfo->AS_Data.f_ref = MT2063_REF_FREQ;
2909 pInfo->AS_Data.f_if1_Center =
2910 (pInfo->AS_Data.f_ref / 8) *
2911 ((UData_t) pInfo->reg[MT2063_REG_FIFFC] + 640);
2912 pInfo->AS_Data.f_if1_bw = MT2063_IF1_BW;
2913 pInfo->AS_Data.f_out = 43750000UL;
2914 pInfo->AS_Data.f_out_bw = 6750000UL;
2915 pInfo->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2916 pInfo->AS_Data.f_LO1_Step = pInfo->AS_Data.f_ref / 64;
2917 pInfo->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2918 pInfo->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2919 pInfo->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2920 pInfo->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2921 pInfo->AS_Data.f_if1_Request = pInfo->AS_Data.f_if1_Center;
2922 pInfo->AS_Data.f_LO1 = 2181000000UL;
2923 pInfo->AS_Data.f_LO2 = 1486249786UL;
2924 pInfo->f_IF1_actual = pInfo->AS_Data.f_if1_Center;
2925 pInfo->AS_Data.f_in =
2926 pInfo->AS_Data.f_LO1 - pInfo->f_IF1_actual;
2927 pInfo->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2928 pInfo->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2929 pInfo->num_regs = MT2063_REG_END_REGS;
2930 pInfo->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2931 pInfo->ctfilt_sw = 0;
2932 }
2933
2934 if (MT2063_NO_ERROR(status)) {
2935 pInfo->CTFiltMax[0] = 69230000;
2936 pInfo->CTFiltMax[1] = 105770000;
2937 pInfo->CTFiltMax[2] = 140350000;
2938 pInfo->CTFiltMax[3] = 177110000;
2939 pInfo->CTFiltMax[4] = 212860000;
2940 pInfo->CTFiltMax[5] = 241130000;
2941 pInfo->CTFiltMax[6] = 274370000;
2942 pInfo->CTFiltMax[7] = 309820000;
2943 pInfo->CTFiltMax[8] = 342450000;
2944 pInfo->CTFiltMax[9] = 378870000;
2945 pInfo->CTFiltMax[10] = 416210000;
2946 pInfo->CTFiltMax[11] = 456500000;
2947 pInfo->CTFiltMax[12] = 495790000;
2948 pInfo->CTFiltMax[13] = 534530000;
2949 pInfo->CTFiltMax[14] = 572610000;
2950 pInfo->CTFiltMax[15] = 598970000;
2951 pInfo->CTFiltMax[16] = 635910000;
2952 pInfo->CTFiltMax[17] = 672130000;
2953 pInfo->CTFiltMax[18] = 714840000;
2954 pInfo->CTFiltMax[19] = 739660000;
2955 pInfo->CTFiltMax[20] = 770410000;
2956 pInfo->CTFiltMax[21] = 814660000;
2957 pInfo->CTFiltMax[22] = 846950000;
2958 pInfo->CTFiltMax[23] = 867820000;
2959 pInfo->CTFiltMax[24] = 915980000;
2960 pInfo->CTFiltMax[25] = 947450000;
2961 pInfo->CTFiltMax[26] = 983110000;
2962 pInfo->CTFiltMax[27] = 1021630000;
2963 pInfo->CTFiltMax[28] = 1061870000;
2964 pInfo->CTFiltMax[29] = 1098330000;
2965 pInfo->CTFiltMax[30] = 1138990000;
2966 }
2967
2968 /*
2969 ** Fetch the FCU osc value and use it and the fRef value to
2970 ** scale all of the Band Max values
2971 */
2972 if (MT2063_NO_ERROR(status)) {
2973 UData_t fcu_osc;
2974 UData_t i;
2975
2976 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
2977 status |=
2978 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
2979 MT2063_REG_CTUNE_CTRL,
2980 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2981 /* Read the ClearTune filter calibration value */
2982 status |=
2983 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2984 MT2063_REG_FIFFC,
2985 &pInfo->reg[MT2063_REG_FIFFC], 1);
2986 fcu_osc = pInfo->reg[MT2063_REG_FIFFC];
2987
2988 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
2989 status |=
2990 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
2991 MT2063_REG_CTUNE_CTRL,
2992 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2993
2994 /* Adjust each of the values in the ClearTune filter cross-over table */
2995 for (i = 0; i < 31; i++) {
2996 pInfo->CTFiltMax[i] =
2997 (pInfo->CTFiltMax[i] / 768) * (fcu_osc + 640);
2998 }
2999 }
3000
3001 return (status);
3002}
3003
3004/******************************************************************************
3005**
3006** Name: MT2063_SetGPIO
3007**
3008** Description: Modify the MT2063 GPIO value.
3009**
3010** Parameters: h - Open handle to the tuner (from MT2063_Open).
3011** gpio_id - Selects GPIO0, GPIO1 or GPIO2
3012** attr - Selects input readback, I/O direction or
3013** output value
3014** value - value to set GPIO pin 15, 14 or 19
3015**
3016** Usage: status = MT2063_SetGPIO(hMT2063, MT2063_GPIO1, MT2063_GPIO_OUT, 1);
3017**
3018** Returns: status:
3019** MT_OK - No errors
3020** MT_COMM_ERR - Serial bus communications error
3021** MT_INV_HANDLE - Invalid tuner handle
3022**
3023** Dependencies: MT_WriteSub - Write byte(s) of data to the two-wire-bus
3024**
3025** Revision History:
3026**
3027** SCR Date Author Description
3028** -------------------------------------------------------------------------
3029** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3030**
3031******************************************************************************/
3032UData_t MT2063_SetGPIO(Handle_t h, enum MT2063_GPIO_ID gpio_id,
3033 enum MT2063_GPIO_Attr attr, UData_t value)
3034{
3035 UData_t status = MT2063_OK; /* Status to be returned */
3036 U8Data regno;
3037 SData_t shift;
3038 static U8Data GPIOreg[3] = { 0x15, 0x19, 0x18 };
3039 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3040
3041 if (MT2063_IsValidHandle(pInfo) == 0)
3042 return MT2063_INV_HANDLE;
3043
3044 regno = GPIOreg[attr];
3045
3046 shift = (gpio_id - MT2063_GPIO0 + 5);
3047
3048 if (value & 0x01)
3049 pInfo->reg[regno] |= (0x01 << shift);
3050 else
3051 pInfo->reg[regno] &= ~(0x01 << shift);
3052 status =
3053 MT2063_WriteSub(pInfo->hUserData, pInfo->address, regno,
3054 &pInfo->reg[regno], 1);
3055
3056 return (status);
3057}
3058
3059/****************************************************************************
3060**
3061** Name: MT2063_SetParam
3062**
3063** Description: Sets a tuning algorithm parameter.
3064**
3065** This function provides access to the internals of the
3066** tuning algorithm. You can override many of the tuning
3067** algorithm defaults using this function.
3068**
3069** Parameters: h - Tuner handle (returned by MT2063_Open)
3070** param - Tuning algorithm parameter
3071** (see enum MT2063_Param)
3072** nValue - value to be set
3073**
3074** param Description
3075** ---------------------- --------------------------------
3076** MT2063_SRO_FREQ crystal frequency
3077** MT2063_STEPSIZE minimum tuning step size
3078** MT2063_LO1_FREQ LO1 frequency
3079** MT2063_LO1_STEPSIZE LO1 minimum step size
3080** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
3081** MT2063_IF1_REQUEST Requested 1st IF
3082** MT2063_ZIF_BW zero-IF bandwidth
3083** MT2063_LO2_FREQ LO2 frequency
3084** MT2063_LO2_STEPSIZE LO2 minimum step size
3085** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
3086** MT2063_OUTPUT_FREQ output center frequency
3087** MT2063_OUTPUT_BW output bandwidth
3088** MT2063_LO_SEPARATION min inter-tuner LO separation
3089** MT2063_MAX_HARM1 max # of intra-tuner harmonics
3090** MT2063_MAX_HARM2 max # of inter-tuner harmonics
3091** MT2063_RCVR_MODE Predefined modes
3092** MT2063_LNA_RIN Set LNA Rin (*)
3093** MT2063_LNA_TGT Set target power level at LNA (*)
3094** MT2063_PD1_TGT Set target power level at PD1 (*)
3095** MT2063_PD2_TGT Set target power level at PD2 (*)
3096** MT2063_ACLNA_MAX LNA attenuator limit (*)
3097** MT2063_ACRF_MAX RF attenuator limit (*)
3098** MT2063_ACFIF_MAX FIF attenuator limit (*)
3099** MT2063_DNC_OUTPUT_ENABLE DNC output selection
3100** MT2063_VGAGC VGA gain code
3101** MT2063_VGAOI VGA output current
3102** MT2063_TAGC TAGC setting
3103** MT2063_AMPGC AMP gain code
3104** MT2063_AVOID_DECT Avoid DECT Frequencies
3105** MT2063_CTFILT_SW Cleartune filter selection
3106**
3107** (*) This parameter is set by MT2063_RCVR_MODE, do not call
3108** additionally.
3109**
3110** Usage: status |= MT2063_SetParam(hMT2063,
3111** MT2063_STEPSIZE,
3112** 50000);
3113**
3114** Returns: status:
3115** MT_OK - No errors
3116** MT_INV_HANDLE - Invalid tuner handle
3117** MT_ARG_NULL - Null pointer argument passed
3118** MT_ARG_RANGE - Invalid parameter requested
3119** or set value out of range
3120** or non-writable parameter
3121**
3122** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3123**
3124** See Also: MT2063_GetParam, MT2063_Open
3125**
3126** Revision History:
3127**
3128** SCR Date Author Description
3129** -------------------------------------------------------------------------
3130** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3131** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
3132** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
3133** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
3134** Split SetParam up to ACLNA / ACLNA_MAX
3135** removed ACLNA_INRC/DECR (+RF & FIF)
3136** removed GCUAUTO / BYPATNDN/UP
3137** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3138** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3139** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3140**
3141****************************************************************************/
3142UData_t MT2063_SetParam(Handle_t h, enum MT2063_Param param, UData_t nValue)
3143{
3144 UData_t status = MT2063_OK; /* Status to be returned */
3145 U8Data val = 0;
3146 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3147
3148 /* Verify that the handle passed points to a valid tuner */
3149 if (MT2063_IsValidHandle(pInfo) == 0)
3150 status |= MT2063_INV_HANDLE;
3151
3152 if (MT2063_NO_ERROR(status)) {
3153 switch (param) {
3154 /* crystal frequency */
3155 case MT2063_SRO_FREQ:
3156 pInfo->AS_Data.f_ref = nValue;
3157 pInfo->AS_Data.f_LO1_FracN_Avoid = 0;
3158 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
3159 pInfo->AS_Data.f_LO1_Step = nValue / 64;
3160 pInfo->AS_Data.f_if1_Center =
3161 (pInfo->AS_Data.f_ref / 8) *
3162 (pInfo->reg[MT2063_REG_FIFFC] + 640);
3163 break;
3164
3165 /* minimum tuning step size */
3166 case MT2063_STEPSIZE:
3167 pInfo->AS_Data.f_LO2_Step = nValue;
3168 break;
3169
3170 /* LO1 frequency */
3171 case MT2063_LO1_FREQ:
3172 {
3173 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3174 /* Capture the Divider and Numerator portions of other LO */
3175 U8Data tempLO2CQ[3];
3176 U8Data tempLO2C[3];
3177 U8Data tmpOneShot;
3178 UData_t Div, FracN;
3179 U8Data restore = 0;
3180
3181 /* Buffer the queue for restoration later and get actual LO2 values. */
3182 status |=
3183 MT2063_ReadSub(pInfo->hUserData,
3184 pInfo->address,
3185 MT2063_REG_LO2CQ_1,
3186 &(tempLO2CQ[0]), 3);
3187 status |=
3188 MT2063_ReadSub(pInfo->hUserData,
3189 pInfo->address,
3190 MT2063_REG_LO2C_1,
3191 &(tempLO2C[0]), 3);
3192
3193 /* clear the one-shot bits */
3194 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
3195 tempLO2C[2] = tempLO2C[2] & 0x0F;
3196
3197 /* only write the queue values if they are different from the actual. */
3198 if ((tempLO2CQ[0] != tempLO2C[0]) ||
3199 (tempLO2CQ[1] != tempLO2C[1]) ||
3200 (tempLO2CQ[2] != tempLO2C[2])) {
3201 /* put actual LO2 value into queue (with 0 in one-shot bits) */
3202 status |=
3203 MT2063_WriteSub(pInfo->hUserData,
3204 pInfo->address,
3205 MT2063_REG_LO2CQ_1,
3206 &(tempLO2C[0]), 3);
3207
3208 if (status == MT2063_OK) {
3209 /* cache the bytes just written. */
3210 pInfo->reg[MT2063_REG_LO2CQ_1] =
3211 tempLO2C[0];
3212 pInfo->reg[MT2063_REG_LO2CQ_2] =
3213 tempLO2C[1];
3214 pInfo->reg[MT2063_REG_LO2CQ_3] =
3215 tempLO2C[2];
3216 }
3217 restore = 1;
3218 }
3219
3220 /* Calculate the Divider and Numberator components of LO1 */
3221 status =
3222 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
3223 pInfo->AS_Data.f_ref /
3224 64,
3225 pInfo->AS_Data.f_ref);
3226 pInfo->reg[MT2063_REG_LO1CQ_1] =
3227 (U8Data) (Div & 0x00FF);
3228 pInfo->reg[MT2063_REG_LO1CQ_2] =
3229 (U8Data) (FracN);
3230 status |=
3231 MT2063_WriteSub(pInfo->hUserData,
3232 pInfo->address,
3233 MT2063_REG_LO1CQ_1,
3234 &pInfo->
3235 reg[MT2063_REG_LO1CQ_1], 2);
3236
3237 /* set the one-shot bit to load the pair of LO values */
3238 tmpOneShot = tempLO2CQ[2] | 0xE0;
3239 status |=
3240 MT2063_WriteSub(pInfo->hUserData,
3241 pInfo->address,
3242 MT2063_REG_LO2CQ_3,
3243 &tmpOneShot, 1);
3244
3245 /* only restore the queue values if they were different from the actual. */
3246 if (restore) {
3247 /* put actual LO2 value into queue (0 in one-shot bits) */
3248 status |=
3249 MT2063_WriteSub(pInfo->hUserData,
3250 pInfo->address,
3251 MT2063_REG_LO2CQ_1,
3252 &(tempLO2CQ[0]), 3);
3253
3254 /* cache the bytes just written. */
3255 pInfo->reg[MT2063_REG_LO2CQ_1] =
3256 tempLO2CQ[0];
3257 pInfo->reg[MT2063_REG_LO2CQ_2] =
3258 tempLO2CQ[1];
3259 pInfo->reg[MT2063_REG_LO2CQ_3] =
3260 tempLO2CQ[2];
3261 }
3262
3263 MT2063_GetParam(pInfo->hUserData,
3264 MT2063_LO1_FREQ,
3265 &pInfo->AS_Data.f_LO1);
3266 }
3267 break;
3268
3269 /* LO1 minimum step size */
3270 case MT2063_LO1_STEPSIZE:
3271 pInfo->AS_Data.f_LO1_Step = nValue;
3272 break;
3273
3274 /* LO1 FracN keep-out region */
3275 case MT2063_LO1_FRACN_AVOID_PARAM:
3276 pInfo->AS_Data.f_LO1_FracN_Avoid = nValue;
3277 break;
3278
3279 /* Requested 1st IF */
3280 case MT2063_IF1_REQUEST:
3281 pInfo->AS_Data.f_if1_Request = nValue;
3282 break;
3283
3284 /* zero-IF bandwidth */
3285 case MT2063_ZIF_BW:
3286 pInfo->AS_Data.f_zif_bw = nValue;
3287 break;
3288
3289 /* LO2 frequency */
3290 case MT2063_LO2_FREQ:
3291 {
3292 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3293 /* Capture the Divider and Numerator portions of other LO */
3294 U8Data tempLO1CQ[2];
3295 U8Data tempLO1C[2];
3296 UData_t Div2;
3297 UData_t FracN2;
3298 U8Data tmpOneShot;
3299 U8Data restore = 0;
3300
3301 /* Buffer the queue for restoration later and get actual LO2 values. */
3302 status |=
3303 MT2063_ReadSub(pInfo->hUserData,
3304 pInfo->address,
3305 MT2063_REG_LO1CQ_1,
3306 &(tempLO1CQ[0]), 2);
3307 status |=
3308 MT2063_ReadSub(pInfo->hUserData,
3309 pInfo->address,
3310 MT2063_REG_LO1C_1,
3311 &(tempLO1C[0]), 2);
3312
3313 /* only write the queue values if they are different from the actual. */
3314 if ((tempLO1CQ[0] != tempLO1C[0])
3315 || (tempLO1CQ[1] != tempLO1C[1])) {
3316 /* put actual LO1 value into queue */
3317 status |=
3318 MT2063_WriteSub(pInfo->hUserData,
3319 pInfo->address,
3320 MT2063_REG_LO1CQ_1,
3321 &(tempLO1C[0]), 2);
3322
3323 /* cache the bytes just written. */
3324 pInfo->reg[MT2063_REG_LO1CQ_1] =
3325 tempLO1C[0];
3326 pInfo->reg[MT2063_REG_LO1CQ_2] =
3327 tempLO1C[1];
3328 restore = 1;
3329 }
3330
3331 /* Calculate the Divider and Numberator components of LO2 */
3332 status =
3333 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
3334 pInfo->AS_Data.f_ref /
3335 8191,
3336 pInfo->AS_Data.f_ref);
3337 pInfo->reg[MT2063_REG_LO2CQ_1] =
3338 (U8Data) ((Div2 << 1) |
3339 ((FracN2 >> 12) & 0x01)) & 0xFF;
3340 pInfo->reg[MT2063_REG_LO2CQ_2] =
3341 (U8Data) ((FracN2 >> 4) & 0xFF);
3342 pInfo->reg[MT2063_REG_LO2CQ_3] =
3343 (U8Data) ((FracN2 & 0x0F));
3344 status |=
3345 MT2063_WriteSub(pInfo->hUserData,
3346 pInfo->address,
3347 MT2063_REG_LO1CQ_1,
3348 &pInfo->
3349 reg[MT2063_REG_LO1CQ_1], 3);
3350
3351 /* set the one-shot bit to load the LO values */
3352 tmpOneShot =
3353 pInfo->reg[MT2063_REG_LO2CQ_3] | 0xE0;
3354 status |=
3355 MT2063_WriteSub(pInfo->hUserData,
3356 pInfo->address,
3357 MT2063_REG_LO2CQ_3,
3358 &tmpOneShot, 1);
3359
3360 /* only restore LO1 queue value if they were different from the actual. */
3361 if (restore) {
3362 /* put previous LO1 queue value back into queue */
3363 status |=
3364 MT2063_WriteSub(pInfo->hUserData,
3365 pInfo->address,
3366 MT2063_REG_LO1CQ_1,
3367 &(tempLO1CQ[0]), 2);
3368
3369 /* cache the bytes just written. */
3370 pInfo->reg[MT2063_REG_LO1CQ_1] =
3371 tempLO1CQ[0];
3372 pInfo->reg[MT2063_REG_LO1CQ_2] =
3373 tempLO1CQ[1];
3374 }
3375
3376 MT2063_GetParam(pInfo->hUserData,
3377 MT2063_LO2_FREQ,
3378 &pInfo->AS_Data.f_LO2);
3379 }
3380 break;
3381
3382 /* LO2 minimum step size */
3383 case MT2063_LO2_STEPSIZE:
3384 pInfo->AS_Data.f_LO2_Step = nValue;
3385 break;
3386
3387 /* LO2 FracN keep-out region */
3388 case MT2063_LO2_FRACN_AVOID:
3389 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue;
3390 break;
3391
3392 /* output center frequency */
3393 case MT2063_OUTPUT_FREQ:
3394 pInfo->AS_Data.f_out = nValue;
3395 break;
3396
3397 /* output bandwidth */
3398 case MT2063_OUTPUT_BW:
3399 pInfo->AS_Data.f_out_bw = nValue + 750000;
3400 break;
3401
3402 /* min inter-tuner LO separation */
3403 case MT2063_LO_SEPARATION:
3404 pInfo->AS_Data.f_min_LO_Separation = nValue;
3405 break;
3406
3407 /* max # of intra-tuner harmonics */
3408 case MT2063_MAX_HARM1:
3409 pInfo->AS_Data.maxH1 = nValue;
3410 break;
3411
3412 /* max # of inter-tuner harmonics */
3413 case MT2063_MAX_HARM2:
3414 pInfo->AS_Data.maxH2 = nValue;
3415 break;
3416
3417 case MT2063_RCVR_MODE:
3418 status |=
3419 MT2063_SetReceiverMode(pInfo,
3420 (enum MT2063_RCVR_MODES)
3421 nValue);
3422 break;
3423
3424 /* Set LNA Rin -- nValue is desired value */
3425 case MT2063_LNA_RIN:
3426 val =
3427 (pInfo->
3428 reg[MT2063_REG_CTRL_2C] & (U8Data) ~ 0x03) |
3429 (nValue & 0x03);
3430 if (pInfo->reg[MT2063_REG_CTRL_2C] != val) {
3431 status |=
3432 MT2063_SetReg(pInfo, MT2063_REG_CTRL_2C,
3433 val);
3434 }
3435 break;
3436
3437 /* Set target power level at LNA -- nValue is desired value */
3438 case MT2063_LNA_TGT:
3439 val =
3440 (pInfo->
3441 reg[MT2063_REG_LNA_TGT] & (U8Data) ~ 0x3F) |
3442 (nValue & 0x3F);
3443 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
3444 status |=
3445 MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT,
3446 val);
3447 }
3448 break;
3449
3450 /* Set target power level at PD1 -- nValue is desired value */
3451 case MT2063_PD1_TGT:
3452 val =
3453 (pInfo->
3454 reg[MT2063_REG_PD1_TGT] & (U8Data) ~ 0x3F) |
3455 (nValue & 0x3F);
3456 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
3457 status |=
3458 MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT,
3459 val);
3460 }
3461 break;
3462
3463 /* Set target power level at PD2 -- nValue is desired value */
3464 case MT2063_PD2_TGT:
3465 val =
3466 (pInfo->
3467 reg[MT2063_REG_PD2_TGT] & (U8Data) ~ 0x3F) |
3468 (nValue & 0x3F);
3469 if (pInfo->reg[MT2063_REG_PD2_TGT] != val) {
3470 status |=
3471 MT2063_SetReg(pInfo, MT2063_REG_PD2_TGT,
3472 val);
3473 }
3474 break;
3475
3476 /* Set LNA atten limit -- nValue is desired value */
3477 case MT2063_ACLNA_MAX:
3478 val =
3479 (pInfo->
3480 reg[MT2063_REG_LNA_OV] & (U8Data) ~ 0x1F) | (nValue
3481 &
3482 0x1F);
3483 if (pInfo->reg[MT2063_REG_LNA_OV] != val) {
3484 status |=
3485 MT2063_SetReg(pInfo, MT2063_REG_LNA_OV,
3486 val);
3487 }
3488 break;
3489
3490 /* Set RF atten limit -- nValue is desired value */
3491 case MT2063_ACRF_MAX:
3492 val =
3493 (pInfo->
3494 reg[MT2063_REG_RF_OV] & (U8Data) ~ 0x1F) | (nValue
3495 &
3496 0x1F);
3497 if (pInfo->reg[MT2063_REG_RF_OV] != val) {
3498 status |=
3499 MT2063_SetReg(pInfo, MT2063_REG_RF_OV, val);
3500 }
3501 break;
3502
3503 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
3504 case MT2063_ACFIF_MAX:
3505 if (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3
3506 && nValue > 5)
3507 nValue = 5;
3508 val =
3509 (pInfo->
3510 reg[MT2063_REG_FIF_OV] & (U8Data) ~ 0x1F) | (nValue
3511 &
3512 0x1F);
3513 if (pInfo->reg[MT2063_REG_FIF_OV] != val) {
3514 status |=
3515 MT2063_SetReg(pInfo, MT2063_REG_FIF_OV,
3516 val);
3517 }
3518 break;
3519
3520 case MT2063_DNC_OUTPUT_ENABLE:
3521 /* selects, which DNC output is used */
3522 switch ((enum MT2063_DNC_Output_Enable)nValue) {
3523 case MT2063_DNC_NONE:
3524 {
3525 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3526 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3527 val)
3528 status |=
3529 MT2063_SetReg(h,
3530 MT2063_REG_DNC_GAIN,
3531 val);
3532
3533 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3534 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3535 val)
3536 status |=
3537 MT2063_SetReg(h,
3538 MT2063_REG_VGA_GAIN,
3539 val);
3540
3541 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3542 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3543 val)
3544 status |=
3545 MT2063_SetReg(h,
3546 MT2063_REG_RSVD_20,
3547 val);
3548
3549 break;
3550 }
3551 case MT2063_DNC_1:
3552 {
3553 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3554 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3555 val)
3556 status |=
3557 MT2063_SetReg(h,
3558 MT2063_REG_DNC_GAIN,
3559 val);
3560
3561 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3562 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3563 val)
3564 status |=
3565 MT2063_SetReg(h,
3566 MT2063_REG_VGA_GAIN,
3567 val);
3568
3569 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3570 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3571 val)
3572 status |=
3573 MT2063_SetReg(h,
3574 MT2063_REG_RSVD_20,
3575 val);
3576
3577 break;
3578 }
3579 case MT2063_DNC_2:
3580 {
3581 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3582 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3583 val)
3584 status |=
3585 MT2063_SetReg(h,
3586 MT2063_REG_DNC_GAIN,
3587 val);
3588
3589 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3590 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3591 val)
3592 status |=
3593 MT2063_SetReg(h,
3594 MT2063_REG_VGA_GAIN,
3595 val);
3596
3597 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3598 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3599 val)
3600 status |=
3601 MT2063_SetReg(h,
3602 MT2063_REG_RSVD_20,
3603 val);
3604
3605 break;
3606 }
3607 case MT2063_DNC_BOTH:
3608 {
3609 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3610 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3611 val)
3612 status |=
3613 MT2063_SetReg(h,
3614 MT2063_REG_DNC_GAIN,
3615 val);
3616
3617 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3618 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3619 val)
3620 status |=
3621 MT2063_SetReg(h,
3622 MT2063_REG_VGA_GAIN,
3623 val);
3624
3625 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3626 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3627 val)
3628 status |=
3629 MT2063_SetReg(h,
3630 MT2063_REG_RSVD_20,
3631 val);
3632
3633 break;
3634 }
3635 default:
3636 break;
3637 }
3638 break;
3639
3640 case MT2063_VGAGC:
3641 /* Set VGA gain code */
3642 val =
3643 (pInfo->
3644 reg[MT2063_REG_VGA_GAIN] & (U8Data) ~ 0x0C) |
3645 ((nValue & 0x03) << 2);
3646 if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) {
3647 status |=
3648 MT2063_SetReg(pInfo, MT2063_REG_VGA_GAIN,
3649 val);
3650 }
3651 break;
3652
3653 case MT2063_VGAOI:
3654 /* Set VGA bias current */
3655 val =
3656 (pInfo->
3657 reg[MT2063_REG_RSVD_31] & (U8Data) ~ 0x07) |
3658 (nValue & 0x07);
3659 if (pInfo->reg[MT2063_REG_RSVD_31] != val) {
3660 status |=
3661 MT2063_SetReg(pInfo, MT2063_REG_RSVD_31,
3662 val);
3663 }
3664 break;
3665
3666 case MT2063_TAGC:
3667 /* Set TAGC */
3668 val =
3669 (pInfo->
3670 reg[MT2063_REG_RSVD_1E] & (U8Data) ~ 0x03) |
3671 (nValue & 0x03);
3672 if (pInfo->reg[MT2063_REG_RSVD_1E] != val) {
3673 status |=
3674 MT2063_SetReg(pInfo, MT2063_REG_RSVD_1E,
3675 val);
3676 }
3677 break;
3678
3679 case MT2063_AMPGC:
3680 /* Set Amp gain code */
3681 val =
3682 (pInfo->
3683 reg[MT2063_REG_TEMP_SEL] & (U8Data) ~ 0x03) |
3684 (nValue & 0x03);
3685 if (pInfo->reg[MT2063_REG_TEMP_SEL] != val) {
3686 status |=
3687 MT2063_SetReg(pInfo, MT2063_REG_TEMP_SEL,
3688 val);
3689 }
3690 break;
3691
3692 /* Avoid DECT Frequencies */
3693 case MT2063_AVOID_DECT:
3694 {
3695 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3696 (enum MT2063_DECT_Avoid_Type)nValue;
3697 if ((newAvoidSetting >=
3698 MT2063_NO_DECT_AVOIDANCE)
3699 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
3700 pInfo->AS_Data.avoidDECT =
3701 newAvoidSetting;
3702 }
3703 }
3704 break;
3705
3706 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3707 case MT2063_CTFILT_SW:
3708 pInfo->ctfilt_sw = (nValue & 0x01);
3709 break;
3710
3711 /* These parameters are read-only */
3712 case MT2063_IC_ADDR:
3713 case MT2063_MAX_OPEN:
3714 case MT2063_NUM_OPEN:
3715 case MT2063_INPUT_FREQ:
3716 case MT2063_IF1_ACTUAL:
3717 case MT2063_IF1_CENTER:
3718 case MT2063_IF1_BW:
3719 case MT2063_AS_ALG:
3720 case MT2063_EXCL_ZONES:
3721 case MT2063_SPUR_AVOIDED:
3722 case MT2063_NUM_SPURS:
3723 case MT2063_SPUR_PRESENT:
3724 case MT2063_ACLNA:
3725 case MT2063_ACRF:
3726 case MT2063_ACFIF:
3727 case MT2063_EOP:
3728 default:
3729 status |= MT2063_ARG_RANGE;
3730 }
3731 }
3732 return (status);
3733}
3734
3735/****************************************************************************
3736**
3737** Name: MT2063_SetPowerMaskBits
3738**
3739** Description: Sets the power-down mask bits for various sections of
3740** the MT2063
3741**
3742** Parameters: h - Tuner handle (returned by MT2063_Open)
3743** Bits - Mask bits to be set.
3744**
3745** See definition of MT2063_Mask_Bits type for description
3746** of each of the power bits.
3747**
3748** Returns: status:
3749** MT_OK - No errors
3750** MT_INV_HANDLE - Invalid tuner handle
3751** MT_COMM_ERR - Serial bus communications error
3752**
3753** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3754**
3755** Revision History:
3756**
3757** SCR Date Author Description
3758** -------------------------------------------------------------------------
3759** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3760**
3761****************************************************************************/
3762UData_t MT2063_SetPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits Bits)
3763{
3764 UData_t status = MT2063_OK; /* Status to be returned */
3765 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3766
3767 /* Verify that the handle passed points to a valid tuner */
3768 if (MT2063_IsValidHandle(pInfo) == 0)
3769 status = MT2063_INV_HANDLE;
3770 else {
3771 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3772 if ((Bits & 0xFF00) != 0) {
3773 pInfo->reg[MT2063_REG_PWR_2] |=
3774 (U8Data) ((Bits & 0xFF00) >> 8);
3775 status |=
3776 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3777 MT2063_REG_PWR_2,
3778 &pInfo->reg[MT2063_REG_PWR_2], 1);
3779 }
3780 if ((Bits & 0xFF) != 0) {
3781 pInfo->reg[MT2063_REG_PWR_1] |= ((U8Data) Bits & 0xFF);
3782 status |=
3783 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3784 MT2063_REG_PWR_1,
3785 &pInfo->reg[MT2063_REG_PWR_1], 1);
3786 }
3787 }
3788
3789 return (status);
3790}
3791
3792/****************************************************************************
3793**
3794** Name: MT2063_ClearPowerMaskBits
3795**
3796** Description: Clears the power-down mask bits for various sections of
3797** the MT2063
3798**
3799** Parameters: h - Tuner handle (returned by MT2063_Open)
3800** Bits - Mask bits to be cleared.
3801**
3802** See definition of MT2063_Mask_Bits type for description
3803** of each of the power bits.
3804**
3805** Returns: status:
3806** MT_OK - No errors
3807** MT_INV_HANDLE - Invalid tuner handle
3808** MT_COMM_ERR - Serial bus communications error
3809**
3810** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3811**
3812** Revision History:
3813**
3814** SCR Date Author Description
3815** -------------------------------------------------------------------------
3816** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3817**
3818****************************************************************************/
3819UData_t MT2063_ClearPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits Bits)
3820{
3821 UData_t status = MT2063_OK; /* Status to be returned */
3822 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3823
3824 /* Verify that the handle passed points to a valid tuner */
3825 if (MT2063_IsValidHandle(pInfo) == 0)
3826 status = MT2063_INV_HANDLE;
3827 else {
3828 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3829 if ((Bits & 0xFF00) != 0) {
3830 pInfo->reg[MT2063_REG_PWR_2] &= ~(U8Data) (Bits >> 8);
3831 status |=
3832 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3833 MT2063_REG_PWR_2,
3834 &pInfo->reg[MT2063_REG_PWR_2], 1);
3835 }
3836 if ((Bits & 0xFF) != 0) {
3837 pInfo->reg[MT2063_REG_PWR_1] &= ~(U8Data) (Bits & 0xFF);
3838 status |=
3839 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3840 MT2063_REG_PWR_1,
3841 &pInfo->reg[MT2063_REG_PWR_1], 1);
3842 }
3843 }
3844
3845 return (status);
3846}
3847
3848/****************************************************************************
3849**
3850** Name: MT2063_GetPowerMaskBits
3851**
3852** Description: Returns a mask of the enabled power shutdown bits
3853**
3854** Parameters: h - Tuner handle (returned by MT2063_Open)
3855** Bits - Mask bits to currently set.
3856**
3857** See definition of MT2063_Mask_Bits type for description
3858** of each of the power bits.
3859**
3860** Returns: status:
3861** MT_OK - No errors
3862** MT_INV_HANDLE - Invalid tuner handle
3863** MT_ARG_NULL - Output argument is NULL
3864** MT_COMM_ERR - Serial bus communications error
3865**
3866** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3867**
3868** Revision History:
3869**
3870** SCR Date Author Description
3871** -------------------------------------------------------------------------
3872** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3873**
3874****************************************************************************/
3875UData_t MT2063_GetPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits * Bits)
3876{
3877 UData_t status = MT2063_OK; /* Status to be returned */
3878 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3879
3880 /* Verify that the handle passed points to a valid tuner */
3881 if (MT2063_IsValidHandle(pInfo) == 0)
3882 status = MT2063_INV_HANDLE;
3883 else {
3884 if (Bits == NULL)
3885 status |= MT2063_ARG_NULL;
3886
3887 if (MT2063_NO_ERROR(status))
3888 status |=
3889 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
3890 MT2063_REG_PWR_1,
3891 &pInfo->reg[MT2063_REG_PWR_1], 2);
3892
3893 if (MT2063_NO_ERROR(status)) {
3894 *Bits =
3895 (enum
3896 MT2063_Mask_Bits)(((SData_t) pInfo->
3897 reg[MT2063_REG_PWR_2] << 8) +
3898 pInfo->reg[MT2063_REG_PWR_1]);
3899 *Bits = (enum MT2063_Mask_Bits)(*Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3900 }
3901 }
3902
3903 return (status);
3904}
3905
3906/****************************************************************************
3907**
3908** Name: MT2063_EnableExternalShutdown
3909**
3910** Description: Enables or disables the operation of the external
3911** shutdown pin
3912**
3913** Parameters: h - Tuner handle (returned by MT2063_Open)
3914** Enabled - 0 = disable the pin, otherwise enable it
3915**
3916** Returns: status:
3917** MT_OK - No errors
3918** MT_INV_HANDLE - Invalid tuner handle
3919** MT_COMM_ERR - Serial bus communications error
3920**
3921** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3922**
3923** Revision History:
3924**
3925** SCR Date Author Description
3926** -------------------------------------------------------------------------
3927** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3928**
3929****************************************************************************/
3930UData_t MT2063_EnableExternalShutdown(Handle_t h, U8Data Enabled)
3931{
3932 UData_t status = MT2063_OK; /* Status to be returned */
3933 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3934
3935 /* Verify that the handle passed points to a valid tuner */
3936 if (MT2063_IsValidHandle(pInfo) == 0)
3937 status = MT2063_INV_HANDLE;
3938 else {
3939 if (Enabled == 0)
3940 pInfo->reg[MT2063_REG_PWR_1] &= ~0x08; /* Turn off the bit */
3941 else
3942 pInfo->reg[MT2063_REG_PWR_1] |= 0x08; /* Turn the bit on */
3943
3944 status |=
3945 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3946 MT2063_REG_PWR_1,
3947 &pInfo->reg[MT2063_REG_PWR_1], 1);
3948 }
3949
3950 return (status);
3951}
3952
3953/****************************************************************************
3954**
3955** Name: MT2063_SoftwareShutdown
3956**
3957** Description: Enables or disables software shutdown function. When
3958** Shutdown==1, any section whose power mask is set will be
3959** shutdown.
3960**
3961** Parameters: h - Tuner handle (returned by MT2063_Open)
3962** Shutdown - 1 = shutdown the masked sections, otherwise
3963** power all sections on
3964**
3965** Returns: status:
3966** MT_OK - No errors
3967** MT_INV_HANDLE - Invalid tuner handle
3968** MT_COMM_ERR - Serial bus communications error
3969**
3970** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3971**
3972** Revision History:
3973**
3974** SCR Date Author Description
3975** -------------------------------------------------------------------------
3976** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3977** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3978** correct wakeup of the LNA
3979**
3980****************************************************************************/
3981UData_t MT2063_SoftwareShutdown(Handle_t h, U8Data Shutdown)
3982{
3983 UData_t status = MT2063_OK; /* Status to be returned */
3984 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3985
3986 /* Verify that the handle passed points to a valid tuner */
3987 if (MT2063_IsValidHandle(pInfo) == 0) {
3988 status = MT2063_INV_HANDLE;
3989 } else {
3990 if (Shutdown == 1)
3991 pInfo->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
3992 else
3993 pInfo->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
3994
3995 status |=
3996 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3997 MT2063_REG_PWR_1,
3998 &pInfo->reg[MT2063_REG_PWR_1], 1);
3999
4000 if (Shutdown != 1) {
4001 pInfo->reg[MT2063_REG_BYP_CTRL] =
4002 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
4003 status |=
4004 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
4005 MT2063_REG_BYP_CTRL,
4006 &pInfo->reg[MT2063_REG_BYP_CTRL],
4007 1);
4008 pInfo->reg[MT2063_REG_BYP_CTRL] =
4009 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F);
4010 status |=
4011 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
4012 MT2063_REG_BYP_CTRL,
4013 &pInfo->reg[MT2063_REG_BYP_CTRL],
4014 1);
4015 }
4016 }
4017
4018 return (status);
4019}
4020
4021/****************************************************************************
4022**
4023** Name: MT2063_SetExtSRO
4024**
4025** Description: Sets the external SRO driver.
4026**
4027** Parameters: h - Tuner handle (returned by MT2063_Open)
4028** Ext_SRO_Setting - external SRO drive setting
4029**
4030** (default) MT2063_EXT_SRO_OFF - ext driver off
4031** MT2063_EXT_SRO_BY_1 - ext driver = SRO frequency
4032** MT2063_EXT_SRO_BY_2 - ext driver = SRO/2 frequency
4033** MT2063_EXT_SRO_BY_4 - ext driver = SRO/4 frequency
4034**
4035** Returns: status:
4036** MT_OK - No errors
4037** MT_COMM_ERR - Serial bus communications error
4038** MT_INV_HANDLE - Invalid tuner handle
4039**
4040** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
4041**
4042** The Ext_SRO_Setting settings default to OFF
4043** Use this function if you need to override the default
4044**
4045** Revision History:
4046**
4047** SCR Date Author Description
4048** -------------------------------------------------------------------------
4049** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4050** 189 S 05-13-2008 RSK Ver 1.16: Correct location for ExtSRO control.
4051**
4052****************************************************************************/
4053UData_t MT2063_SetExtSRO(Handle_t h, enum MT2063_Ext_SRO Ext_SRO_Setting)
4054{
4055 UData_t status = MT2063_OK; /* Status to be returned */
4056 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4057
4058 /* Verify that the handle passed points to a valid tuner */
4059 if (MT2063_IsValidHandle(pInfo) == 0)
4060 status = MT2063_INV_HANDLE;
4061 else {
4062 pInfo->reg[MT2063_REG_CTRL_2C] =
4063 (pInfo->
4064 reg[MT2063_REG_CTRL_2C] & 0x3F) | ((U8Data) Ext_SRO_Setting
4065 << 6);
4066 status =
4067 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
4068 MT2063_REG_CTRL_2C,
4069 &pInfo->reg[MT2063_REG_CTRL_2C], 1);
4070 }
4071
4072 return (status);
4073}
4074
4075/****************************************************************************
4076**
4077** Name: MT2063_SetReg
4078**
4079** Description: Sets an MT2063 register.
4080**
4081** Parameters: h - Tuner handle (returned by MT2063_Open)
4082** reg - MT2063 register/subaddress location
4083** val - MT2063 register/subaddress value
4084**
4085** Returns: status:
4086** MT_OK - No errors
4087** MT_COMM_ERR - Serial bus communications error
4088** MT_INV_HANDLE - Invalid tuner handle
4089** MT_ARG_RANGE - Argument out of range
4090**
4091** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
4092**
4093** Use this function if you need to override a default
4094** register value
4095**
4096** Revision History:
4097**
4098** SCR Date Author Description
4099** -------------------------------------------------------------------------
4100** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4101**
4102****************************************************************************/
4103UData_t MT2063_SetReg(Handle_t h, U8Data reg, U8Data val)
4104{
4105 UData_t status = MT2063_OK; /* Status to be returned */
4106 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4107
4108 /* Verify that the handle passed points to a valid tuner */
4109 if (MT2063_IsValidHandle(pInfo) == 0)
4110 status |= MT2063_INV_HANDLE;
4111
4112 if (reg >= MT2063_REG_END_REGS)
4113 status |= MT2063_ARG_RANGE;
4114
4115 if (MT2063_NO_ERROR(status)) {
4116 status |=
4117 MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
4118 1);
4119 if (MT2063_NO_ERROR(status))
4120 pInfo->reg[reg] = val;
4121 }
4122
4123 return (status);
4124}
4125
4126static UData_t MT2063_Round_fLO(UData_t f_LO, UData_t f_LO_Step, UData_t f_ref)
4127{
4128 return f_ref * (f_LO / f_ref)
4129 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
4130}
4131
4132/****************************************************************************
4133**
4134** Name: fLO_FractionalTerm
4135**
4136** Description: Calculates the portion contributed by FracN / denom.
4137**
4138** This function preserves maximum precision without
4139** risk of overflow. It accurately calculates
4140** f_ref * num / denom to within 1 HZ with fixed math.
4141**
4142** Parameters: num - Fractional portion of the multiplier
4143** denom - denominator portion of the ratio
4144** This routine successfully handles denom values
4145** up to and including 2^18.
4146** f_Ref - SRO frequency. This calculation handles
4147** f_ref as two separate 14-bit fields.
4148** Therefore, a maximum value of 2^28-1
4149** may safely be used for f_ref. This is
4150** the genesis of the magic number "14" and the
4151** magic mask value of 0x03FFF.
4152**
4153** Returns: f_ref * num / denom
4154**
4155** Revision History:
4156**
4157** SCR Date Author Description
4158** -------------------------------------------------------------------------
4159** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4160**
4161****************************************************************************/
4162static UData_t MT2063_fLO_FractionalTerm(UData_t f_ref,
4163 UData_t num, UData_t denom)
4164{
4165 UData_t t1 = (f_ref >> 14) * num;
4166 UData_t term1 = t1 / denom;
4167 UData_t loss = t1 % denom;
4168 UData_t term2 =
4169 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
4170 return ((term1 << 14) + term2);
4171}
4172
4173/****************************************************************************
4174**
4175** Name: CalcLO1Mult
4176**
4177** Description: Calculates Integer divider value and the numerator
4178** value for a FracN PLL.
4179**
4180** This function assumes that the f_LO and f_Ref are
4181** evenly divisible by f_LO_Step.
4182**
4183** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4184** FracN - OUTPUT: Fractional portion of the multiplier
4185** f_LO - desired LO frequency.
4186** f_LO_Step - Minimum step size for the LO (in Hz).
4187** f_Ref - SRO frequency.
4188** f_Avoid - Range of PLL frequencies to avoid near
4189** integer multiples of f_Ref (in Hz).
4190**
4191** Returns: Recalculated LO frequency.
4192**
4193** Revision History:
4194**
4195** SCR Date Author Description
4196** -------------------------------------------------------------------------
4197** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4198**
4199****************************************************************************/
4200static UData_t MT2063_CalcLO1Mult(UData_t * Div,
4201 UData_t * FracN,
4202 UData_t f_LO,
4203 UData_t f_LO_Step, UData_t f_Ref)
4204{
4205 /* Calculate the whole number portion of the divider */
4206 *Div = f_LO / f_Ref;
4207
4208 /* Calculate the numerator value (round to nearest f_LO_Step) */
4209 *FracN =
4210 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4211 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4212
4213 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
4214}
4215
4216/****************************************************************************
4217**
4218** Name: CalcLO2Mult
4219**
4220** Description: Calculates Integer divider value and the numerator
4221** value for a FracN PLL.
4222**
4223** This function assumes that the f_LO and f_Ref are
4224** evenly divisible by f_LO_Step.
4225**
4226** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4227** FracN - OUTPUT: Fractional portion of the multiplier
4228** f_LO - desired LO frequency.
4229** f_LO_Step - Minimum step size for the LO (in Hz).
4230** f_Ref - SRO frequency.
4231** f_Avoid - Range of PLL frequencies to avoid near
4232** integer multiples of f_Ref (in Hz).
4233**
4234** Returns: Recalculated LO frequency.
4235**
4236** Revision History:
4237**
4238** SCR Date Author Description
4239** -------------------------------------------------------------------------
4240** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4241**
4242****************************************************************************/
4243static UData_t MT2063_CalcLO2Mult(UData_t * Div,
4244 UData_t * FracN,
4245 UData_t f_LO,
4246 UData_t f_LO_Step, UData_t f_Ref)
4247{
4248 /* Calculate the whole number portion of the divider */
4249 *Div = f_LO / f_Ref;
4250
4251 /* Calculate the numerator value (round to nearest f_LO_Step) */
4252 *FracN =
4253 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4254 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4255
4256 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
4257 8191);
4258}
4259
4260/****************************************************************************
4261**
4262** Name: FindClearTuneFilter
4263**
4264** Description: Calculate the corrrect ClearTune filter to be used for
4265** a given input frequency.
4266**
4267** Parameters: pInfo - ptr to tuner data structure
4268** f_in - RF input center frequency (in Hz).
4269**
4270** Returns: ClearTune filter number (0-31)
4271**
4272** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
4273**
4274** Revision History:
4275**
4276** SCR Date Author Description
4277** -------------------------------------------------------------------------
4278** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
4279** cross-over frequency values.
4280**
4281****************************************************************************/
4282static UData_t FindClearTuneFilter(struct MT2063_Info_t *pInfo, UData_t f_in)
4283{
4284 UData_t RFBand;
4285 UData_t idx; /* index loop */
4286
4287 /*
4288 ** Find RF Band setting
4289 */
4290 RFBand = 31; /* def when f_in > all */
4291 for (idx = 0; idx < 31; ++idx) {
4292 if (pInfo->CTFiltMax[idx] >= f_in) {
4293 RFBand = idx;
4294 break;
4295 }
4296 }
4297 return (RFBand);
4298}
4299
4300/****************************************************************************
4301**
4302** Name: MT2063_Tune
4303**
4304** Description: Change the tuner's tuned frequency to RFin.
4305**
4306** Parameters: h - Open handle to the tuner (from MT2063_Open).
4307** f_in - RF input center frequency (in Hz).
4308**
4309** Returns: status:
4310** MT_OK - No errors
4311** MT_INV_HANDLE - Invalid tuner handle
4312** MT_UPC_UNLOCK - Upconverter PLL unlocked
4313** MT_DNC_UNLOCK - Downconverter PLL unlocked
4314** MT_COMM_ERR - Serial bus communications error
4315** MT_SPUR_CNT_MASK - Count of avoided LO spurs
4316** MT_SPUR_PRESENT - LO spur possible in output
4317** MT_FIN_RANGE - Input freq out of range
4318** MT_FOUT_RANGE - Output freq out of range
4319** MT_UPC_RANGE - Upconverter freq out of range
4320** MT_DNC_RANGE - Downconverter freq out of range
4321**
4322** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
4323**
4324** MT_ReadSub - Read data from the two-wire serial bus
4325** MT_WriteSub - Write data to the two-wire serial bus
4326** MT_Sleep - Delay execution for x milliseconds
4327** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
4328**
4329** Revision History:
4330**
4331** SCR Date Author Description
4332** -------------------------------------------------------------------------
4333** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4334** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
4335** cross-over frequency values.
4336** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
4337** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
4338** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
4339**
4340****************************************************************************/
4341UData_t MT2063_Tune(Handle_t h, UData_t f_in)
4342{ /* RF input center frequency */
4343 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4344
4345 UData_t status = MT2063_OK; /* status of operation */
4346 UData_t LO1; /* 1st LO register value */
4347 UData_t Num1; /* Numerator for LO1 reg. value */
4348 UData_t f_IF1; /* 1st IF requested */
4349 UData_t LO2; /* 2nd LO register value */
4350 UData_t Num2; /* Numerator for LO2 reg. value */
4351 UData_t ofLO1, ofLO2; /* last time's LO frequencies */
4352 UData_t ofin, ofout; /* last time's I/O frequencies */
4353 U8Data fiffc = 0x80; /* FIFF center freq from tuner */
4354 UData_t fiffof; /* Offset from FIFF center freq */
4355 const U8Data LO1LK = 0x80; /* Mask for LO1 Lock bit */
4356 U8Data LO2LK = 0x08; /* Mask for LO2 Lock bit */
4357 U8Data val;
4358 UData_t RFBand;
4359
4360 /* Verify that the handle passed points to a valid tuner */
4361 if (MT2063_IsValidHandle(pInfo) == 0)
4362 return MT2063_INV_HANDLE;
4363
4364 /* Check the input and output frequency ranges */
4365 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
4366 status |= MT2063_FIN_RANGE;
4367
4368 if ((pInfo->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
4369 || (pInfo->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
4370 status |= MT2063_FOUT_RANGE;
4371
4372 /*
4373 ** Save original LO1 and LO2 register values
4374 */
4375 ofLO1 = pInfo->AS_Data.f_LO1;
4376 ofLO2 = pInfo->AS_Data.f_LO2;
4377 ofin = pInfo->AS_Data.f_in;
4378 ofout = pInfo->AS_Data.f_out;
4379
4380 /*
4381 ** Find and set RF Band setting
4382 */
4383 if (pInfo->ctfilt_sw == 1) {
4384 val = (pInfo->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
4385 if (pInfo->reg[MT2063_REG_CTUNE_CTRL] != val) {
4386 status |=
4387 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_CTRL, val);
4388 }
4389 val = pInfo->reg[MT2063_REG_CTUNE_OV];
4390 RFBand = FindClearTuneFilter(pInfo, f_in);
4391 pInfo->reg[MT2063_REG_CTUNE_OV] =
4392 (U8Data) ((pInfo->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
4393 | RFBand);
4394 if (pInfo->reg[MT2063_REG_CTUNE_OV] != val) {
4395 status |=
4396 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_OV, val);
4397 }
4398 }
4399
4400 /*
4401 ** Read the FIFF Center Frequency from the tuner
4402 */
4403 if (MT2063_NO_ERROR(status)) {
4404 status |=
4405 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
4406 MT2063_REG_FIFFC,
4407 &pInfo->reg[MT2063_REG_FIFFC], 1);
4408 fiffc = pInfo->reg[MT2063_REG_FIFFC];
4409 }
4410 /*
4411 ** Assign in the requested values
4412 */
4413 pInfo->AS_Data.f_in = f_in;
4414 /* Request a 1st IF such that LO1 is on a step size */
4415 pInfo->AS_Data.f_if1_Request =
4416 MT2063_Round_fLO(pInfo->AS_Data.f_if1_Request + f_in,
4417 pInfo->AS_Data.f_LO1_Step,
4418 pInfo->AS_Data.f_ref) - f_in;
4419
4420 /*
4421 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
4422 ** desired LO1 frequency
4423 */
4424 MT2063_ResetExclZones(&pInfo->AS_Data);
4425
4426 f_IF1 = MT2063_ChooseFirstIF(&pInfo->AS_Data);
4427
4428 pInfo->AS_Data.f_LO1 =
4429 MT2063_Round_fLO(f_IF1 + f_in, pInfo->AS_Data.f_LO1_Step,
4430 pInfo->AS_Data.f_ref);
4431
4432 pInfo->AS_Data.f_LO2 =
4433 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4434 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4435
4436 /*
4437 ** Check for any LO spurs in the output bandwidth and adjust
4438 ** the LO settings to avoid them if needed
4439 */
4440 status |= MT2063_AvoidSpurs(h, &pInfo->AS_Data);
4441 /*
4442 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
4443 ** Recalculate the LO frequencies and the values to be placed
4444 ** in the tuning registers.
4445 */
4446 pInfo->AS_Data.f_LO1 =
4447 MT2063_CalcLO1Mult(&LO1, &Num1, pInfo->AS_Data.f_LO1,
4448 pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref);
4449 pInfo->AS_Data.f_LO2 =
4450 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4451 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4452 pInfo->AS_Data.f_LO2 =
4453 MT2063_CalcLO2Mult(&LO2, &Num2, pInfo->AS_Data.f_LO2,
4454 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4455
4456 /*
4457 ** Check the upconverter and downconverter frequency ranges
4458 */
4459 if ((pInfo->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
4460 || (pInfo->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
4461 status |= MT2063_UPC_RANGE;
4462 if ((pInfo->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
4463 || (pInfo->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
4464 status |= MT2063_DNC_RANGE;
4465 /* LO2 Lock bit was in a different place for B0 version */
4466 if (pInfo->tuner_id == MT2063_B0)
4467 LO2LK = 0x40;
4468
4469 /*
4470 ** If we have the same LO frequencies and we're already locked,
4471 ** then skip re-programming the LO registers.
4472 */
4473 if ((ofLO1 != pInfo->AS_Data.f_LO1)
4474 || (ofLO2 != pInfo->AS_Data.f_LO2)
4475 || ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
4476 (LO1LK | LO2LK))) {
4477 /*
4478 ** Calculate the FIFFOF register value
4479 **
4480 ** IF1_Actual
4481 ** FIFFOF = ------------ - 8 * FIFFC - 4992
4482 ** f_ref/64
4483 */
4484 fiffof =
4485 (pInfo->AS_Data.f_LO1 -
4486 f_in) / (pInfo->AS_Data.f_ref / 64) - 8 * (UData_t) fiffc -
4487 4992;
4488 if (fiffof > 0xFF)
4489 fiffof = 0xFF;
4490
4491 /*
4492 ** Place all of the calculated values into the local tuner
4493 ** register fields.
4494 */
4495 if (MT2063_NO_ERROR(status)) {
4496 pInfo->reg[MT2063_REG_LO1CQ_1] = (U8Data) (LO1 & 0xFF); /* DIV1q */
4497 pInfo->reg[MT2063_REG_LO1CQ_2] = (U8Data) (Num1 & 0x3F); /* NUM1q */
4498 pInfo->reg[MT2063_REG_LO2CQ_1] = (U8Data) (((LO2 & 0x7F) << 1) /* DIV2q */
4499 |(Num2 >> 12)); /* NUM2q (hi) */
4500 pInfo->reg[MT2063_REG_LO2CQ_2] = (U8Data) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
4501 pInfo->reg[MT2063_REG_LO2CQ_3] = (U8Data) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
4502
4503 /*
4504 ** Now write out the computed register values
4505 ** IMPORTANT: There is a required order for writing
4506 ** (0x05 must follow all the others).
4507 */
4508 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
4509 if (pInfo->tuner_id == MT2063_B0) {
4510 /* Re-write the one-shot bits to trigger the tune operation */
4511 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &pInfo->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
4512 }
4513 /* Write out the FIFF offset only if it's changing */
4514 if (pInfo->reg[MT2063_REG_FIFF_OFFSET] !=
4515 (U8Data) fiffof) {
4516 pInfo->reg[MT2063_REG_FIFF_OFFSET] =
4517 (U8Data) fiffof;
4518 status |=
4519 MT2063_WriteSub(pInfo->hUserData,
4520 pInfo->address,
4521 MT2063_REG_FIFF_OFFSET,
4522 &pInfo->
4523 reg[MT2063_REG_FIFF_OFFSET],
4524 1);
4525 }
4526 }
4527
4528 /*
4529 ** Check for LO's locking
4530 */
4531
4532 if (MT2063_NO_ERROR(status)) {
4533 status |= MT2063_GetLocked(h);
4534 }
4535 /*
4536 ** If we locked OK, assign calculated data to MT2063_Info_t structure
4537 */
4538 if (MT2063_NO_ERROR(status)) {
4539 pInfo->f_IF1_actual = pInfo->AS_Data.f_LO1 - f_in;
4540 }
4541 }
4542
4543 return (status);
4544}
4545
4546UData_t MT_Tune_atv(Handle_t h, UData_t f_in, UData_t bw_in,
4547 enum MTTune_atv_standard tv_type)
4548{
4549
4550 UData_t status = MT2063_OK;
4551 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4552 struct dvb_frontend *fe = (struct dvb_frontend *)pInfo->hUserData;
4553 struct mt2063_state *state = fe->tuner_priv;
4554
4555 SData_t pict_car = 0;
4556 SData_t pict2chanb_vsb = 0;
4557 SData_t pict2chanb_snd = 0;
4558 SData_t pict2snd1 = 0;
4559 SData_t pict2snd2 = 0;
4560 SData_t ch_bw = 0;
4561
4562 SData_t if_mid = 0;
4563 SData_t rcvr_mode = 0;
4564 UData_t mode_get = 0;
4565
4566 switch (tv_type) {
4567 case MTTUNEA_PAL_B:{
4568 pict_car = 38900000;
4569 ch_bw = 8000000;
4570 pict2chanb_vsb = -1250000;
4571 pict2snd1 = 5500000;
4572 pict2snd2 = 5742000;
4573 rcvr_mode = 1;
4574 break;
4575 }
4576 case MTTUNEA_PAL_G:{
4577 pict_car = 38900000;
4578 ch_bw = 7000000;
4579 pict2chanb_vsb = -1250000;
4580 pict2snd1 = 5500000;
4581 pict2snd2 = 0;
4582 rcvr_mode = 1;
4583 break;
4584 }
4585 case MTTUNEA_PAL_I:{
4586 pict_car = 38900000;
4587 ch_bw = 8000000;
4588 pict2chanb_vsb = -1250000;
4589 pict2snd1 = 6000000;
4590 pict2snd2 = 0;
4591 rcvr_mode = 1;
4592 break;
4593 }
4594 case MTTUNEA_PAL_L:{
4595 pict_car = 38900000;
4596 ch_bw = 8000000;
4597 pict2chanb_vsb = -1250000;
4598 pict2snd1 = 6500000;
4599 pict2snd2 = 0;
4600 rcvr_mode = 1;
4601 break;
4602 }
4603 case MTTUNEA_PAL_MN:{
4604 pict_car = 38900000;
4605 ch_bw = 6000000;
4606 pict2chanb_vsb = -1250000;
4607 pict2snd1 = 4500000;
4608 pict2snd2 = 0;
4609 rcvr_mode = 1;
4610 break;
4611 }
4612 case MTTUNEA_PAL_DK:{
4613 pict_car = 38900000;
4614 ch_bw = 8000000;
4615 pict2chanb_vsb = -1250000;
4616 pict2snd1 = 6500000;
4617 pict2snd2 = 0;
4618 rcvr_mode = 1;
4619 break;
4620 }
4621 case MTTUNEA_DIGITAL:{
4622 pict_car = 36125000;
4623 ch_bw = 8000000;
4624 pict2chanb_vsb = -(ch_bw / 2);
4625 pict2snd1 = 0;
4626 pict2snd2 = 0;
4627 rcvr_mode = 2;
4628 break;
4629 }
4630 case MTTUNEA_FMRADIO:{
4631 pict_car = 38900000;
4632 ch_bw = 8000000;
4633 pict2chanb_vsb = -(ch_bw / 2);
4634 pict2snd1 = 0;
4635 pict2snd2 = 0;
4636 rcvr_mode = 4;
4637 //f_in -= 2900000;
4638 break;
4639 }
4640 case MTTUNEA_DVBC:{
4641 pict_car = 36125000;
4642 ch_bw = 8000000;
4643 pict2chanb_vsb = -(ch_bw / 2);
4644 pict2snd1 = 0;
4645 pict2snd2 = 0;
4646 rcvr_mode = MT2063_CABLE_QAM;
4647 break;
4648 }
4649 case MTTUNEA_DVBT:{
4650 pict_car = 36125000;
4651 ch_bw = bw_in; //8000000
4652 pict2chanb_vsb = -(ch_bw / 2);
4653 pict2snd1 = 0;
4654 pict2snd2 = 0;
4655 rcvr_mode = MT2063_OFFAIR_COFDM;
4656 break;
4657 }
4658 case MTTUNEA_UNKNOWN:
4659 break;
4660 default:
4661 break;
4662 }
4663
4664 pict2chanb_snd = pict2chanb_vsb - ch_bw;
4665 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
4666
4667 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
4668 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
4669 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
4670 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4671
4672 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
4673 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
4674 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4675
4676 return (UData_t) status;
4677}
4678
4679static int mt2063_init(struct dvb_frontend *fe)
4680{
4681 UData_t status = MT2063_ERROR;
4682 struct mt2063_state *state = fe->tuner_priv;
4683
4684 status = MT2063_Open(0xC0, &(state->MT2063_ht), fe);
4685 status |= MT2063_SoftwareShutdown(state->MT2063_ht, 1);
4686 status |= MT2063_ClearPowerMaskBits(state->MT2063_ht, MT2063_ALL_SD);
4687
4688 if (MT2063_OK != status) {
4689 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
4690 status);
4691 return -1;
4692 }
4693
4694 return 0;
4695}
4696
4697static int mt2063_sleep(struct dvb_frontend *fe)
4698{
4699 /* TODO: power down */
4700 return 0;
4701}
4702
4703static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
4704{
4705 int rc = 0;
4706
4707 //get tuner lock status
4708
4709 return rc;
4710}
4711
4712static int mt2063_get_state(struct dvb_frontend *fe,
4713 enum tuner_param param, struct tuner_state *state)
4714{
4715 struct mt2063_state *mt2063State = fe->tuner_priv;
4716
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004717 switch (param) {
4718 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004719 //get frequency
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004720 break;
4721 case DVBFE_TUNER_TUNERSTEP:
4722 break;
4723 case DVBFE_TUNER_IFFREQ:
4724 break;
4725 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004726 //get bandwidth
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004727 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004728 case DVBFE_TUNER_REFCLOCK:
4729 state->refclock =
4730 (u32_t)
4731 MT2063_GetLocked((Handle_t) (mt2063State->MT2063_ht));
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004732 break;
4733 default:
4734 break;
4735 }
4736
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004737 return (int)state->refclock;
4738}
4739
4740static int mt2063_set_state(struct dvb_frontend *fe,
4741 enum tuner_param param, struct tuner_state *state)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004742{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004743 struct mt2063_state *mt2063State = fe->tuner_priv;
4744 UData_t status = MT2063_OK;
4745
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004746 switch (param) {
4747 case DVBFE_TUNER_FREQUENCY:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004748 //set frequency
4749
4750 status =
4751 MT_Tune_atv((Handle_t) (mt2063State->MT2063_ht),
4752 state->frequency, state->bandwidth,
4753 mt2063State->tv_type);
4754
4755 mt2063State->frequency = state->frequency;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004756 break;
4757 case DVBFE_TUNER_TUNERSTEP:
4758 break;
4759 case DVBFE_TUNER_IFFREQ:
4760 break;
4761 case DVBFE_TUNER_BANDWIDTH:
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004762 //set bandwidth
4763 mt2063State->bandwidth = state->bandwidth;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004764 break;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004765 case DVBFE_TUNER_REFCLOCK:
4766
4767 break;
4768 case DVBFE_TUNER_OPEN:
4769 status = MT2063_Open(MT2063_I2C, &(mt2063State->MT2063_ht), fe);
4770 break;
4771 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
4772 status = MT2063_SoftwareShutdown(mt2063State->MT2063_ht, 1);
4773 break;
4774 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
4775 status =
4776 MT2063_ClearPowerMaskBits(mt2063State->MT2063_ht,
4777 MT2063_ALL_SD);
4778 break;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004779 default:
4780 break;
4781 }
4782
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004783 return (int)status;
4784}
4785
4786static int mt2063_release(struct dvb_frontend *fe)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004787{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004788 struct mt2063_state *state = fe->tuner_priv;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004789
4790 fe->tuner_priv = NULL;
4791 kfree(state);
4792
4793 return 0;
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004794}
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004795
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004796static struct dvb_tuner_ops mt2063_ops = {
4797 .info = {
4798 .name = "MT2063 Silicon Tuner",
4799 .frequency_min = 45000000,
4800 .frequency_max = 850000000,
4801 .frequency_step = 0,
4802 },
4803
4804 .init = mt2063_init,
4805 .sleep = mt2063_sleep,
4806 .get_status = mt2063_get_status,
4807 .get_state = mt2063_get_state,
4808 .set_state = mt2063_set_state,
4809 .release = mt2063_release
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004810};
4811
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004812struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4813 struct mt2063_config *config,
4814 struct i2c_adapter *i2c)
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004815{
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004816 struct mt2063_state *state = NULL;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004817
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004818 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004819 if (state == NULL)
4820 goto error;
4821
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004822 state->config = config;
4823 state->i2c = i2c;
4824 state->frontend = fe;
4825 state->reference = config->refclock / 1000; /* kHz */
4826 state->MT2063_init = FALSE;
4827 fe->tuner_priv = state;
4828 fe->ops.tuner_ops = mt2063_ops;
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004829
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004830 printk("%s: Attaching MT2063 \n", __func__);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004831 return fe;
4832
4833error:
4834 kfree(state);
4835 return NULL;
4836}
4837
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004838EXPORT_SYMBOL(mt2063_attach);
Mauro Carvalho Chehab223c7b02011-07-20 19:48:59 -03004839MODULE_PARM_DESC(verbose, "Set Verbosity level");
4840
Mauro Carvalho Chehab0e301442011-07-20 19:52:49 -03004841MODULE_AUTHOR("Henry");
4842MODULE_DESCRIPTION("MT2063 Silicon tuner");
4843MODULE_LICENSE("GPL");