2 #include <linux/init.h>
3 #include <linux/kernel.h>
4 #include <linux/module.h>
5 #include <linux/string.h>
9 /* Version of this module */
10 #define MT2063_VERSION 10018 /* Version 01.18 */
12 static unsigned int verbose;
13 module_param(verbose, int, 0644);
17 /* From drivers/media/common/tuners/mt2063_cfg.h */
19 static unsigned int mt2063_setTune(struct dvb_frontend *fe, u32 f_in,
21 enum MTTune_atv_standard tv_type)
23 //return (int)MT_Tune_atv(h, f_in, bw_in, tv_type);
25 struct dvb_frontend_ops *frontend_ops = NULL;
26 struct dvb_tuner_ops *tuner_ops = NULL;
27 struct tuner_state t_state;
28 struct mt2063_state *mt2063State = fe->tuner_priv;
31 t_state.frequency = f_in;
32 t_state.bandwidth = bw_in;
33 mt2063State->tv_type = tv_type;
35 frontend_ops = &fe->ops;
36 if (&frontend_ops->tuner_ops)
37 tuner_ops = &frontend_ops->tuner_ops;
38 if (tuner_ops->set_state) {
40 tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY,
42 printk("%s: Invalid parameter\n", __func__);
50 static unsigned int mt2063_lockStatus(struct dvb_frontend *fe)
52 struct dvb_frontend_ops *frontend_ops = &fe->ops;
53 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
54 struct tuner_state t_state;
58 frontend_ops = &fe->ops;
59 if (&frontend_ops->tuner_ops)
60 tuner_ops = &frontend_ops->tuner_ops;
61 if (tuner_ops->get_state) {
63 tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK,
65 printk("%s: Invalid parameter\n", __func__);
72 static unsigned int tuner_MT2063_Open(struct dvb_frontend *fe)
74 struct dvb_frontend_ops *frontend_ops = &fe->ops;
75 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
76 struct tuner_state t_state;
80 frontend_ops = &fe->ops;
81 if (&frontend_ops->tuner_ops)
82 tuner_ops = &frontend_ops->tuner_ops;
83 if (tuner_ops->set_state) {
85 tuner_ops->set_state(fe, DVBFE_TUNER_OPEN,
87 printk("%s: Invalid parameter\n", __func__);
95 static unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
97 struct dvb_frontend_ops *frontend_ops = &fe->ops;
98 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
99 struct tuner_state t_state;
103 frontend_ops = &fe->ops;
104 if (&frontend_ops->tuner_ops)
105 tuner_ops = &frontend_ops->tuner_ops;
106 if (tuner_ops->set_state) {
108 tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN,
110 printk("%s: Invalid parameter\n", __func__);
118 static unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
120 struct dvb_frontend_ops *frontend_ops = &fe->ops;
121 struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops;
122 struct tuner_state t_state;
126 frontend_ops = &fe->ops;
127 if (&frontend_ops->tuner_ops)
128 tuner_ops = &frontend_ops->tuner_ops;
129 if (tuner_ops->set_state) {
131 tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS,
133 printk("%s: Invalid parameter\n", __func__);
145 static int mt2063_writeregs(struct mt2063_state *state, u8 reg1,
149 u8 buf[60]; /* = { reg1, data }; */
151 struct i2c_msg msg = {
152 .addr = state->config->tuner_address,
159 memcpy(msg.buf + 1, data, len);
161 //printk("mt2063_writeregs state->i2c=%p\n", state->i2c);
162 ret = i2c_transfer(state->i2c, &msg, 1);
165 printk("mt2063_writeregs error ret=%d\n", ret);
170 static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 * b, u8 len)
174 struct i2c_msg msg[] = {
176 .addr = state->config->tuner_address,
180 .addr = state->config->tuner_address,
186 //printk("mt2063_read_regs state->i2c=%p\n", state->i2c);
187 ret = i2c_transfer(state->i2c, msg, 2);
189 printk("mt2063_readregs error ret=%d\n", ret);
194 //context of mt2063_userdef.c <Henry> ======================================
195 //#################################################################
196 //=================================================================
197 /*****************************************************************************
201 ** Description: Write values to device using a two-wire serial bus.
203 ** Parameters: hUserData - User-specific I/O parameter that was
204 ** passed to tuner's Open function.
205 ** addr - device serial bus address (value passed
206 ** as parameter to MTxxxx_Open)
207 ** subAddress - serial bus sub-address (Register Address)
208 ** pData - pointer to the Data to be written to the
210 ** cnt - number of bytes/registers to be written
214 ** MT_COMM_ERR - Serial bus communications error
217 ** Notes: This is a callback function that is called from the
218 ** the tuning algorithm. You MUST provide code for this
219 ** function to write data using the tuner's 2-wire serial
222 ** The hUserData parameter is a user-specific argument.
223 ** If additional arguments are needed for the user's
224 ** serial bus read/write functions, this argument can be
225 ** used to supply the necessary information.
226 ** The hUserData parameter is initialized in the tuner's Open
231 ** SCR Date Author Description
232 ** -------------------------------------------------------------------------
233 ** N/A 03-25-2004 DAD Original
235 *****************************************************************************/
236 u32 MT2063_WriteSub(void *hUserData,
238 u8 subAddress, u8 * pData, u32 cnt)
240 u32 status = MT2063_OK; /* Status to be returned */
241 struct dvb_frontend *fe = hUserData;
242 struct mt2063_state *state = fe->tuner_priv;
244 ** ToDo: Add code here to implement a serial-bus write
245 ** operation to the MTxxxx tuner. If successful,
250 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
252 if (mt2063_writeregs(state, subAddress, pData, cnt) < 0) {
253 status = MT2063_ERROR;
255 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
260 /*****************************************************************************
264 ** Description: Read values from device using a two-wire serial bus.
266 ** Parameters: hUserData - User-specific I/O parameter that was
267 ** passed to tuner's Open function.
268 ** addr - device serial bus address (value passed
269 ** as parameter to MTxxxx_Open)
270 ** subAddress - serial bus sub-address (Register Address)
271 ** pData - pointer to the Data to be written to the
273 ** cnt - number of bytes/registers to be written
277 ** MT_COMM_ERR - Serial bus communications error
280 ** Notes: This is a callback function that is called from the
281 ** the tuning algorithm. You MUST provide code for this
282 ** function to read data using the tuner's 2-wire serial
285 ** The hUserData parameter is a user-specific argument.
286 ** If additional arguments are needed for the user's
287 ** serial bus read/write functions, this argument can be
288 ** used to supply the necessary information.
289 ** The hUserData parameter is initialized in the tuner's Open
294 ** SCR Date Author Description
295 ** -------------------------------------------------------------------------
296 ** N/A 03-25-2004 DAD Original
298 *****************************************************************************/
299 u32 MT2063_ReadSub(void *hUserData,
301 u8 subAddress, u8 * pData, u32 cnt)
304 ** ToDo: Add code here to implement a serial-bus read
305 ** operation to the MTxxxx tuner. If successful,
309 u32 status = MT2063_OK; /* Status to be returned */
310 struct dvb_frontend *fe = hUserData;
311 struct mt2063_state *state = fe->tuner_priv;
313 fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge
315 for (i = 0; i < cnt; i++) {
316 if (mt2063_read_regs(state, subAddress + i, pData + i, 1) < 0) {
317 status = MT2063_ERROR;
322 fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge
327 /*****************************************************************************
331 ** Description: Delay execution for "nMinDelayTime" milliseconds
333 ** Parameters: hUserData - User-specific I/O parameter that was
334 ** passed to tuner's Open function.
335 ** nMinDelayTime - Delay time in milliseconds
339 ** Notes: This is a callback function that is called from the
340 ** the tuning algorithm. You MUST provide code that
341 ** blocks execution for the specified period of time.
345 ** SCR Date Author Description
346 ** -------------------------------------------------------------------------
347 ** N/A 03-25-2004 DAD Original
349 *****************************************************************************/
350 void MT2063_Sleep(void *hUserData, u32 nMinDelayTime)
353 ** ToDo: Add code here to implement a OS blocking
354 ** for a period of "nMinDelayTime" milliseconds.
356 msleep(nMinDelayTime);
359 /*****************************************************************************
361 ** Name: MT_TunerGain (MT2060 only)
363 ** Description: Measure the relative tuner gain using the demodulator
365 ** Parameters: hUserData - User-specific I/O parameter that was
366 ** passed to tuner's Open function.
367 ** pMeas - Tuner gain (1/100 of dB scale).
368 ** ie. 1234 = 12.34 (dB)
372 ** user-defined errors could be set
374 ** Notes: This is a callback function that is called from the
375 ** the 1st IF location routine. You MUST provide
376 ** code that measures the relative tuner gain in a dB
377 ** (not linear) scale. The return value is an integer
378 ** value scaled to 1/100 of a dB.
382 ** SCR Date Author Description
383 ** -------------------------------------------------------------------------
384 ** N/A 06-16-2004 DAD Original
385 ** N/A 11-30-2004 DAD Renamed from MT_DemodInputPower. This name
386 ** better describes what this function does.
388 *****************************************************************************/
389 u32 MT2060_TunerGain(void *hUserData, s32 * pMeas)
391 u32 status = MT2063_OK; /* Status to be returned */
394 ** ToDo: Add code here to return the gain / power level measured
395 ** at the input to the demodulator.
400 //end of mt2063_userdef.c
401 //=================================================================
402 //#################################################################
403 //=================================================================
405 //context of mt2063_spuravoid.c <Henry> ======================================
406 //#################################################################
407 //=================================================================
409 /*****************************************************************************
411 ** Name: mt_spuravoid.c
413 ** Description: Microtune spur avoidance software module.
414 ** Supports Microtune tuner drivers.
416 ** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $
417 ** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $
421 ** SCR Date Author Description
422 ** -------------------------------------------------------------------------
423 ** 082 03-25-2005 JWS Original multi-tuner support - requires
424 ** MTxxxx_CNT declarations
425 ** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
426 ** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid
427 ** of compiler warnings
428 ** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur
429 ** avoidance into a single module.
430 ** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
431 ** (f_min, f_max) < 0, ignore the entry.
432 ** 115 03-23-2007 DAD Fix declaration of spur due to truncation
434 ** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
436 ** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
437 ** multi-tuners that have
438 ** (delta IF1) > (f_out-f_outbw/2).
439 ** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
440 ** Added logic to force f_Center within 1/2 f_Step.
441 ** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
442 ** Type casts added to preserve correct sign.
443 ** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
444 ** frequencies into MT_ResetExclZones().
445 ** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking.
447 *****************************************************************************/
449 /* Version of this module */
450 #define MT2063_SPUR_VERSION 10201 /* Version 01.21 */
452 /* Implement ceiling, floor functions. */
453 #define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
454 #define uceil(n, d) ((n)/(d) + ((n)%(d) != 0))
455 #define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
456 #define ufloor(n, d) ((n)/(d))
458 struct MT2063_FIFZone_t {
463 #if MT2063_TUNER_CNT > 1
464 static struct MT2063_AvoidSpursData_t *TunerList[MT2063_TUNER_CNT];
465 static u32 TunerCount = 0;
468 u32 MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
470 #if MT2063_TUNER_CNT == 1
471 pAS_Info->nAS_Algorithm = 1;
476 pAS_Info->nAS_Algorithm = 2;
479 ** Check to see if tuner is already registered
481 for (index = 0; index < TunerCount; index++) {
482 if (TunerList[index] == pAS_Info) {
483 return MT2063_OK; /* Already here - no problem */
488 ** Add tuner to list - if there is room.
490 if (TunerCount < MT2063_TUNER_CNT) {
491 TunerList[TunerCount] = pAS_Info;
495 return MT2063_TUNER_CNT_ERR;
499 void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t *pAS_Info)
501 #if MT2063_TUNER_CNT == 1
507 for (index = 0; index < TunerCount; index++) {
508 if (TunerList[index] == pAS_Info) {
509 TunerList[index] = TunerList[--TunerCount];
516 ** Reset all exclusion zones.
517 ** Add zones to protect the PLL FracN regions near zero
519 ** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT
520 ** frequencies into MT_ResetExclZones().
522 void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
525 #if MT2063_TUNER_CNT > 1
527 struct MT2063_AvoidSpursData_t *adj;
530 pAS_Info->nZones = 0; /* this clears the used list */
531 pAS_Info->usedZones = NULL; /* reset ptr */
532 pAS_Info->freeZones = NULL; /* reset ptr */
536 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
537 pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
539 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
540 pAS_Info->f_LO1_FracN_Avoid) {
541 /* Exclude LO1 FracN */
542 MT2063_AddExclZone(pAS_Info,
543 center - pAS_Info->f_LO1_FracN_Avoid,
545 MT2063_AddExclZone(pAS_Info, center + 1,
546 center + pAS_Info->f_LO1_FracN_Avoid);
547 center += pAS_Info->f_ref;
552 ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
553 pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
555 pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
556 pAS_Info->f_LO2_FracN_Avoid) {
557 /* Exclude LO2 FracN */
558 MT2063_AddExclZone(pAS_Info,
559 center - pAS_Info->f_LO2_FracN_Avoid,
561 MT2063_AddExclZone(pAS_Info, center + 1,
562 center + pAS_Info->f_LO2_FracN_Avoid);
563 center += pAS_Info->f_ref;
566 if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
567 /* Exclude LO1 values that conflict with DECT channels */
568 MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */
569 MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */
570 MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */
571 MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */
572 MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */
575 if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
576 MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */
577 MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */
578 MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */
579 MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */
580 MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */
581 MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */
582 MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */
583 MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */
584 MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */
585 MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */
587 #if MT2063_TUNER_CNT > 1
589 ** Iterate through all adjacent tuners and exclude frequencies related to them
591 for (index = 0; index < TunerCount; ++index) {
592 adj = TunerList[index];
593 if (pAS_Info == adj) /* skip over our own data, don't process it */
597 ** Add 1st IF exclusion zone covering adjacent tuner's LO2
598 ** at "adjfLO2 + f_out" +/- m_MinLOSpacing
601 MT2063_AddExclZone(pAS_Info,
602 (adj->f_LO2 + pAS_Info->f_out) -
603 pAS_Info->f_min_LO_Separation,
604 (adj->f_LO2 + pAS_Info->f_out) +
605 pAS_Info->f_min_LO_Separation);
608 ** Add 1st IF exclusion zone covering adjacent tuner's LO1
609 ** at "adjfLO1 - f_in" +/- m_MinLOSpacing
612 MT2063_AddExclZone(pAS_Info,
613 (adj->f_LO1 - pAS_Info->f_in) -
614 pAS_Info->f_min_LO_Separation,
615 (adj->f_LO1 - pAS_Info->f_in) +
616 pAS_Info->f_min_LO_Separation);
621 static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
623 struct MT2063_ExclZone_t *pPrevNode)
625 struct MT2063_ExclZone_t *pNode;
626 /* Check for a node in the free list */
627 if (pAS_Info->freeZones != NULL) {
628 /* Use one from the free list */
629 pNode = pAS_Info->freeZones;
630 pAS_Info->freeZones = pNode->next_;
632 /* Grab a node from the array */
633 pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
636 if (pPrevNode != NULL) {
637 pNode->next_ = pPrevNode->next_;
638 pPrevNode->next_ = pNode;
639 } else { /* insert at the beginning of the list */
641 pNode->next_ = pAS_Info->usedZones;
642 pAS_Info->usedZones = pNode;
649 static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
651 struct MT2063_ExclZone_t *pPrevNode,
652 struct MT2063_ExclZone_t
655 struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
657 /* Make previous node point to the subsequent node */
658 if (pPrevNode != NULL)
659 pPrevNode->next_ = pNext;
661 /* Add pNodeToRemove to the beginning of the freeZones */
662 pNodeToRemove->next_ = pAS_Info->freeZones;
663 pAS_Info->freeZones = pNodeToRemove;
665 /* Decrement node count */
671 /*****************************************************************************
673 ** Name: MT_AddExclZone
675 ** Description: Add (and merge) an exclusion zone into the list.
676 ** If the range (f_min, f_max) is totally outside the
677 ** 1st IF BW, ignore the entry.
678 ** If the range (f_min, f_max) is negative, ignore the entry.
682 ** SCR Date Author Description
683 ** -------------------------------------------------------------------------
684 ** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range
685 ** (f_min, f_max) < 0, ignore the entry.
687 *****************************************************************************/
688 void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
689 u32 f_min, u32 f_max)
691 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
692 struct MT2063_ExclZone_t *pPrev = NULL;
693 struct MT2063_ExclZone_t *pNext = NULL;
695 /* Check to see if this overlaps the 1st IF filter */
696 if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
697 && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
698 && (f_min < f_max)) {
702 ** New entry: |---| |--| |--| |-| |---| |--|
704 ** Existing: |--| |--| |--| |---| |-| |--|
707 /* Check for our place in the list */
708 while ((pNode != NULL) && (pNode->max_ < f_min)) {
710 pNode = pNode->next_;
713 if ((pNode != NULL) && (pNode->min_ < f_max)) {
714 /* Combine me with pNode */
715 if (f_min < pNode->min_)
717 if (f_max > pNode->max_)
720 pNode = InsertNode(pAS_Info, pPrev);
725 /* Look for merging possibilities */
726 pNext = pNode->next_;
727 while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
728 if (pNext->max_ > pNode->max_)
729 pNode->max_ = pNext->max_;
730 pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */
735 /*****************************************************************************
737 ** Name: MT_ChooseFirstIF
739 ** Description: Choose the best available 1st IF
740 ** If f_Desired is not excluded, choose that first.
741 ** Otherwise, return the value closest to f_Center that is
746 ** SCR Date Author Description
747 ** -------------------------------------------------------------------------
748 ** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from
750 ** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)
751 ** Added logic to force f_Center within 1/2 f_Step.
753 *****************************************************************************/
754 u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
757 ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step".
758 ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum
759 ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
760 ** However, the sum must be.
762 const u32 f_Desired =
763 pAS_Info->f_LO1_Step *
764 ((pAS_Info->f_if1_Request + pAS_Info->f_in +
765 pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
768 (pAS_Info->f_LO1_Step >
769 pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
775 u32 bDesiredExcluded = 0;
776 u32 bZeroExcluded = 0;
779 struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
780 struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
782 if (pAS_Info->nZones == 0)
785 /* f_Center needs to be an integer multiple of f_Step away from f_Desired */
786 if (pAS_Info->f_if1_Center > f_Desired)
790 ((pAS_Info->f_if1_Center - f_Desired +
791 f_Step / 2) / f_Step);
796 ((f_Desired - pAS_Info->f_if1_Center +
797 f_Step / 2) / f_Step);
800 //if (!abs((s32) f_Center - (s32) pAS_Info->f_if1_Center) <= (s32) (f_Step/2))
803 /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */
804 while (pNode != NULL) {
807 floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
811 ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
813 if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
814 bDesiredExcluded = 1;
816 if ((tmpMin < 0) && (tmpMax > 0))
819 /* See if this zone overlaps the previous */
820 if ((j > 0) && (tmpMin < zones[j - 1].max_))
821 zones[j - 1].max_ = tmpMax;
824 //assert(j<MT2063_MAX_ZONES);
825 //if (j>=MT2063_MAX_ZONES)
828 zones[j].min_ = tmpMin;
829 zones[j].max_ = tmpMax;
832 pNode = pNode->next_;
836 ** If the desired is okay, return with it
838 if (bDesiredExcluded == 0)
842 ** If the desired is excluded and the center is okay, return with it
844 if (bZeroExcluded == 0)
847 /* Find the value closest to 0 (f_Center) */
848 bestDiff = zones[0].min_;
849 for (i = 0; i < j; i++) {
850 if (abs(zones[i].min_) < abs(bestDiff))
851 bestDiff = zones[i].min_;
852 if (abs(zones[i].max_) < abs(bestDiff))
853 bestDiff = zones[i].max_;
857 return f_Center - ((u32) (-bestDiff) * f_Step);
859 return f_Center + (bestDiff * f_Step);
862 /****************************************************************************
866 ** Description: Uses Euclid's algorithm
868 ** Parameters: u, v - unsigned values whose GCD is desired.
872 ** Returns: greatest common divisor of u and v, if either value
873 ** is 0, the other value is returned as the result.
875 ** Dependencies: None.
879 ** SCR Date Author Description
880 ** -------------------------------------------------------------------------
881 ** N/A 06-01-2004 JWS Original
882 ** N/A 08-03-2004 DAD Changed to Euclid's since it can handle
885 ****************************************************************************/
886 static u32 MT2063_gcd(u32 u, u32 v)
899 /****************************************************************************
903 ** Description: Implements a simple maximum function for unsigned numbers.
904 ** Implemented as a function rather than a macro to avoid
905 ** multiple evaluation of the calling parameters.
907 ** Parameters: a, b - Values to be compared
911 ** Returns: larger of the input values.
913 ** Dependencies: None.
917 ** SCR Date Author Description
918 ** -------------------------------------------------------------------------
919 ** N/A 06-02-2004 JWS Original
921 ****************************************************************************/
922 static u32 MT2063_umax(u32 a, u32 b)
924 return (a >= b) ? a : b;
927 #if MT2063_TUNER_CNT > 1
928 static s32 RoundAwayFromZero(s32 n, s32 d)
930 return (n < 0) ? floor(n, d) : ceil(n, d);
933 /****************************************************************************
935 ** Name: IsSpurInAdjTunerBand
937 ** Description: Checks to see if a spur will be present within the IF's
938 ** bandwidth or near the zero IF.
939 ** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2)
944 ** <--+-+-+-----------------+-+-+-----------------+-+-+-->
946 ** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
947 ** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
949 ** Note that some equations are doubled to prevent round-off
950 ** problems when calculating fIFBW/2
952 ** The spur frequencies are computed as:
954 ** fSpur = n * f1 - m * f2 - fOffset
956 ** Parameters: f1 - The 1st local oscillator (LO) frequency
957 ** of the tuner whose output we are examining
958 ** f2 - The 1st local oscillator (LO) frequency
959 ** of the adjacent tuner
960 ** fOffset - The 2nd local oscillator of the tuner whose
961 ** output we are examining
962 ** fIFOut - Output IF center frequency
963 ** fIFBW - Output IF Bandwidth
964 ** nMaxH - max # of LO harmonics to search
965 ** fp - If spur, positive distance to spur-free band edge (returned)
966 ** fm - If spur, negative distance to spur-free band edge (returned)
968 ** Returns: 1 if an LO spur would be present, otherwise 0.
970 ** Dependencies: None.
974 ** SCR Date Author Description
975 ** -------------------------------------------------------------------------
976 ** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion.
977 ** 115 03-23-2007 DAD Fix declaration of spur due to truncation
979 ** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for
980 ** multi-tuners that have
981 ** (delta IF1) > (f_out-f_outbw/2).
982 ** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2
983 ** Type casts added to preserve correct sign.
985 ****************************************************************************/
986 static u32 IsSpurInAdjTunerBand(u32 bIsMyOutput,
993 u32 nMaxH, u32 * fp, u32 * fm)
997 const u32 fHalf_IFBW = fIFBW / 2;
998 const u32 fHalf_ZIFBW = fZIFBW / 2;
1000 /* Calculate a scale factor for all frequencies, so that our
1001 calculations all stay within 31 bits */
1005 fHalf_IFBW) / nMaxH) / (MAX_UDATA / 2 / nMaxH)) + 1;
1008 ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into
1009 ** signed data types (smaller than MAX_UDATA/2)
1011 const s32 _f1 = (s32) (f1 / f_Scale);
1012 const s32 _f2 = (s32) (f2 / f_Scale);
1013 const s32 _f3 = (s32) (fOffset / f_Scale);
1015 const s32 c = (s32) (fIFOut - fHalf_IFBW) / (s32) f_Scale;
1016 const s32 d = (s32) ((fIFOut + fHalf_IFBW) / f_Scale);
1017 const s32 f = (s32) (fHalf_ZIFBW / f_Scale);
1019 s32 ma, mb, mc, md, me, mf;
1026 ** If the other tuner does not have an LO frequency defined,
1027 ** assume that we cannot interfere with it
1032 /* Check out all multiples of f1 from -nMaxH to +nMaxH */
1033 for (n = -(s32) nMaxH; n <= (s32) nMaxH; ++n) {
1034 const s32 nf1 = n * _f1;
1035 md = (_f3 + d - nf1) / _f2;
1037 /* If # f2 harmonics > nMaxH, then no spurs present */
1038 if (md <= -(s32) nMaxH)
1041 ma = (_f3 - d - nf1) / _f2;
1042 if ((ma == md) || (ma >= (s32) (nMaxH)))
1045 mc = (_f3 + c - nf1) / _f2;
1047 const s32 m = (n < 0) ? md : mc;
1048 const s32 fspur = (nf1 + m * _f2 - _f3);
1049 const s32 den = (bIsMyOutput ? n - 1 : n);
1051 fp_ = (d - fspur) * f_Scale;
1052 fm_ = (fspur - c) * f_Scale;
1055 (s32) RoundAwayFromZero((d - fspur) *
1058 (s32) RoundAwayFromZero((fspur - c) *
1061 if (((u32) abs(fm_) >= f_Scale)
1062 && ((u32) abs(fp_) >= f_Scale)) {
1068 /* Location of Zero-IF-spur to be checked */
1069 mf = (_f3 + f - nf1) / _f2;
1070 me = (_f3 - f - nf1) / _f2;
1072 const s32 m = (n < 0) ? mf : me;
1073 const s32 fspur = (nf1 + m * _f2 - _f3);
1074 const s32 den = (bIsMyOutput ? n - 1 : n);
1076 fp_ = (d - fspur) * f_Scale;
1077 fm_ = (fspur - c) * f_Scale;
1080 (s32) RoundAwayFromZero((f - fspur) *
1083 (s32) RoundAwayFromZero((fspur + f) *
1086 if (((u32) abs(fm_) >= f_Scale)
1087 && ((u32) abs(fp_) >= f_Scale)) {
1093 mb = (_f3 - c - nf1) / _f2;
1095 const s32 m = (n < 0) ? mb : ma;
1096 const s32 fspur = (nf1 + m * _f2 - _f3);
1097 const s32 den = (bIsMyOutput ? n - 1 : n);
1099 fp_ = (d - fspur) * f_Scale;
1100 fm_ = (fspur - c) * f_Scale;
1103 (s32) RoundAwayFromZero((-c - fspur) *
1106 (s32) RoundAwayFromZero((fspur + d) *
1109 if (((u32) abs(fm_) >= f_Scale)
1110 && ((u32) abs(fp_) >= f_Scale)) {
1118 ** Verify that fm & fp are both positive
1119 ** Add one to ensure next 1st IF choice is not right on the edge
1124 } else if (fp_ > 0) {
1136 /****************************************************************************
1138 ** Name: IsSpurInBand
1140 ** Description: Checks to see if a spur will be present within the IF's
1141 ** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
1144 ** <--+-+-+-------------------+-------------------+-+-+-->
1146 ** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^
1147 ** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2
1149 ** Note that some equations are doubled to prevent round-off
1150 ** problems when calculating fIFBW/2
1152 ** Parameters: pAS_Info - Avoid Spurs information block
1153 ** fm - If spur, amount f_IF1 has to move negative
1154 ** fp - If spur, amount f_IF1 has to move positive
1158 ** Returns: 1 if an LO spur would be present, otherwise 0.
1160 ** Dependencies: None.
1162 ** Revision History:
1164 ** SCR Date Author Description
1165 ** -------------------------------------------------------------------------
1166 ** N/A 11-28-2002 DAD Implemented algorithm from applied patent
1168 ****************************************************************************/
1169 static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
1173 ** Calculate LO frequency settings.
1176 const u32 f_LO1 = pAS_Info->f_LO1;
1177 const u32 f_LO2 = pAS_Info->f_LO2;
1178 const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
1179 const u32 c = d - pAS_Info->f_out_bw;
1180 const u32 f = pAS_Info->f_zif_bw / 2;
1181 const u32 f_Scale = (f_LO1 / (MAX_UDATA / 2 / pAS_Info->maxH1)) + 1;
1182 s32 f_nsLO1, f_nsLO2;
1184 u32 ma, mb, mc, md, me, mf;
1185 u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
1186 #if MT2063_TUNER_CNT > 1
1189 struct MT2063_AvoidSpursData_t *adj;
1194 ** For each edge (d, c & f), calculate a scale, based on the gcd
1195 ** of f_LO1, f_LO2 and the edge value. Use the larger of this
1196 ** gcd-based scale factor or f_Scale.
1198 lo_gcd = MT2063_gcd(f_LO1, f_LO2);
1199 gd_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, d), f_Scale);
1200 hgds = gd_Scale / 2;
1201 gc_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, c), f_Scale);
1202 hgcs = gc_Scale / 2;
1203 gf_Scale = MT2063_umax((u32) MT2063_gcd(lo_gcd, f), f_Scale);
1204 hgfs = gf_Scale / 2;
1206 n0 = uceil(f_LO2 - d, f_LO1 - f_LO2);
1208 /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */
1209 for (n = n0; n <= pAS_Info->maxH1; ++n) {
1210 md = (n * ((f_LO1 + hgds) / gd_Scale) -
1211 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1213 /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */
1214 if (md >= pAS_Info->maxH1)
1217 ma = (n * ((f_LO1 + hgds) / gd_Scale) +
1218 ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
1220 /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */
1224 mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
1225 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1227 f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
1228 f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
1230 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1231 n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
1233 *fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
1234 *fm = (((s32) d - f_Spur) / (mc - n)) + 1;
1238 /* Location of Zero-IF-spur to be checked */
1239 me = (n * ((f_LO1 + hgfs) / gf_Scale) +
1240 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1241 mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
1242 ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
1244 f_nsLO1 = n * (f_LO1 / gf_Scale);
1245 f_nsLO2 = me * (f_LO2 / gf_Scale);
1247 (gf_Scale * (f_nsLO1 - f_nsLO2)) +
1248 n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
1250 *fp = ((f_Spur + (s32) f) / (me - n)) + 1;
1251 *fm = (((s32) f - f_Spur) / (me - n)) + 1;
1255 mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
1256 ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
1258 f_nsLO1 = n * (f_LO1 / gc_Scale);
1259 f_nsLO2 = ma * (f_LO2 / gc_Scale);
1261 (gc_Scale * (f_nsLO1 - f_nsLO2)) +
1262 n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
1264 *fp = (((s32) d + f_Spur) / (ma - n)) + 1;
1265 *fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
1270 #if MT2063_TUNER_CNT > 1
1271 /* If no spur found, see if there are more tuners on the same board */
1272 for (index = 0; index < TunerCount; ++index) {
1273 adj = TunerList[index];
1274 if (pAS_Info == adj) /* skip over our own data, don't process it */
1277 /* Look for LO-related spurs from the adjacent tuner generated into my IF output */
1278 if (IsSpurInAdjTunerBand(1, /* check my IF output */
1279 pAS_Info->f_LO1, /* my fLO1 */
1280 adj->f_LO1, /* the other tuner's fLO1 */
1281 pAS_Info->f_LO2, /* my fLO2 */
1282 pAS_Info->f_out, /* my fOut */
1283 pAS_Info->f_out_bw, /* my output IF bandwidth */
1284 pAS_Info->f_zif_bw, /* my Zero-IF bandwidth */
1285 pAS_Info->maxH2, fp, /* minimum amount to move LO's positive */
1286 fm)) /* miminum amount to move LO's negative */
1288 /* Look for LO-related spurs from my tuner generated into the adjacent tuner's IF output */
1289 if (IsSpurInAdjTunerBand(0, /* check his IF output */
1290 pAS_Info->f_LO1, /* my fLO1 */
1291 adj->f_LO1, /* the other tuner's fLO1 */
1292 adj->f_LO2, /* the other tuner's fLO2 */
1293 adj->f_out, /* the other tuner's fOut */
1294 adj->f_out_bw, /* the other tuner's output IF bandwidth */
1295 pAS_Info->f_zif_bw, /* the other tuner's Zero-IF bandwidth */
1296 adj->maxH2, fp, /* minimum amount to move LO's positive */
1297 fm)) /* miminum amount to move LO's negative */
1301 /* No spurs found */
1305 /*****************************************************************************
1307 ** Name: MT_AvoidSpurs
1309 ** Description: Main entry point to avoid spurs.
1310 ** Checks for existing spurs in present LO1, LO2 freqs
1311 ** and if present, chooses spur-free LO1, LO2 combination
1312 ** that tunes the same input/output frequencies.
1314 ** Revision History:
1316 ** SCR Date Author Description
1317 ** -------------------------------------------------------------------------
1318 ** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0.
1320 *****************************************************************************/
1321 u32 MT2063_AvoidSpurs(void *h, struct MT2063_AvoidSpursData_t * pAS_Info)
1323 u32 status = MT2063_OK;
1324 u32 fm, fp; /* restricted range on LO's */
1325 pAS_Info->bSpurAvoided = 0;
1326 pAS_Info->nSpursFound = 0;
1328 if (pAS_Info->maxH1 == 0)
1332 ** Avoid LO Generated Spurs
1334 ** Make sure that have no LO-related spurs within the IF output
1337 ** If there is an LO spur in this band, start at the current IF1 frequency
1338 ** and work out until we find a spur-free frequency or run up against the
1339 ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they
1340 ** will be unchanged if a spur-free setting is not found.
1342 pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
1343 if (pAS_Info->bSpurPresent) {
1344 u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */
1345 u32 zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */
1346 u32 zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */
1351 ** Spur was found, attempt to find a spur-free 1st IF
1354 pAS_Info->nSpursFound++;
1356 /* Raise f_IF1_upper, if needed */
1357 MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
1359 /* Choose next IF1 that is closest to f_IF1_CENTER */
1360 new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
1362 if (new_IF1 > zfIF1) {
1363 pAS_Info->f_LO1 += (new_IF1 - zfIF1);
1364 pAS_Info->f_LO2 += (new_IF1 - zfIF1);
1366 pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
1367 pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
1371 if (zfIF1 > pAS_Info->f_if1_Center)
1372 delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
1374 delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
1377 ** Continue while the new 1st IF is still within the 1st IF bandwidth
1378 ** and there is a spur in the band (again)
1380 while ((2 * delta_IF1 + pAS_Info->f_out_bw <=
1382 && (pAS_Info->bSpurPresent =
1383 IsSpurInBand(pAS_Info, &fm, &fp)));
1386 ** Use the LO-spur free values found. If the search went all the way to
1387 ** the 1st IF band edge and always found spurs, just leave the original
1388 ** choice. It's as "good" as any other.
1390 if (pAS_Info->bSpurPresent == 1) {
1391 status |= MT2063_SPUR_PRESENT_ERR;
1392 pAS_Info->f_LO1 = zfLO1;
1393 pAS_Info->f_LO2 = zfLO2;
1395 pAS_Info->bSpurAvoided = 1;
1400 nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
1405 u32 MT2063_AvoidSpursVersion(void)
1407 return (MT2063_SPUR_VERSION);
1410 //end of mt2063_spuravoid.c
1411 //=================================================================
1412 //#################################################################
1413 //=================================================================
1416 ** The expected version of MT_AvoidSpursData_t
1417 ** If the version is different, an updated file is needed from Microtune
1419 /* Expecting version 1.21 of the Spur Avoidance API */
1425 } MT2063_ATTEN_CNTL_MODE;
1427 //#define TUNER_MT2063_OPTIMIZATION
1429 ** Constants used by the tuning algorithm
1431 #define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */
1432 #define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */
1433 #define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */
1434 #define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */
1435 #define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */
1436 #define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */
1437 #define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */
1438 #define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */
1439 #define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */
1440 #define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */
1441 #define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */
1442 #define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */
1443 #define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */
1444 #define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */
1445 #define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */
1446 #define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */
1447 #define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */
1448 #define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */
1451 ** Define the supported Part/Rev codes for the MT2063
1453 #define MT2063_B0 (0x9B)
1454 #define MT2063_B1 (0x9C)
1455 #define MT2063_B2 (0x9D)
1456 #define MT2063_B3 (0x9E)
1459 ** The number of Tuner Registers
1461 static const u32 MT2063_Num_Registers = MT2063_REG_END_REGS;
1463 #define USE_GLOBAL_TUNER 0
1465 static u32 nMT2063MaxTuners = 1;
1466 static struct MT2063_Info_t MT2063_Info[1];
1467 static struct MT2063_Info_t *MT2063_Avail[1];
1468 static u32 nMT2063OpenTuners = 0;
1471 ** Constants for setting receiver modes.
1472 ** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES)
1473 ** (DNC1GC & DNC2GC are the values, which are used, when the specific
1474 ** DNC Output is selected, the other is always off)
1476 ** If PAL-L or L' is received, set:
1477 ** MT2063_SetParam(hMT2063,MT2063_TAGC,1);
1479 ** --------------+----------------------------------------------
1480 ** Mode 0 : | MT2063_CABLE_QAM
1481 ** Mode 1 : | MT2063_CABLE_ANALOG
1482 ** Mode 2 : | MT2063_OFFAIR_COFDM
1483 ** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
1484 ** Mode 4 : | MT2063_OFFAIR_ANALOG
1485 ** Mode 5 : | MT2063_OFFAIR_8VSB
1486 ** --------------+----+----+----+----+-----+-----+--------------
1487 ** Mode | 0 | 1 | 2 | 3 | 4 | 5 |
1488 ** --------------+----+----+----+----+-----+-----+
1492 static const u8 RFAGCEN[] = { 0, 0, 0, 0, 0, 0 };
1493 static const u8 LNARIN[] = { 0, 0, 3, 3, 3, 3 };
1494 static const u8 FIFFQEN[] = { 1, 1, 1, 1, 1, 1 };
1495 static const u8 FIFFQ[] = { 0, 0, 0, 0, 0, 0 };
1496 static const u8 DNC1GC[] = { 0, 0, 0, 0, 0, 0 };
1497 static const u8 DNC2GC[] = { 0, 0, 0, 0, 0, 0 };
1498 static const u8 ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 };
1499 static const u8 LNATGT[] = { 44, 43, 43, 43, 43, 43 };
1500 static const u8 RFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1501 static const u8 ACRFMAX[] = { 31, 31, 31, 31, 31, 31 };
1502 static const u8 PD1TGT[] = { 36, 36, 38, 38, 36, 38 };
1503 static const u8 FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 };
1504 static const u8 ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 };
1505 static const u8 PD2TGT[] = { 40, 33, 38, 42, 30, 38 };
1508 ** Local Function Prototypes - not available for external access.
1511 /* Forward declaration(s): */
1512 static u32 MT2063_CalcLO1Mult(u32 * Div, u32 * FracN, u32 f_LO,
1513 u32 f_LO_Step, u32 f_Ref);
1514 static u32 MT2063_CalcLO2Mult(u32 * Div, u32 * FracN, u32 f_LO,
1515 u32 f_LO_Step, u32 f_Ref);
1516 static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num,
1519 /******************************************************************************
1521 ** Name: MT2063_Open
1523 ** Description: Initialize the tuner's register values.
1525 ** Parameters: MT2063_Addr - Serial bus address of the tuner.
1526 ** hMT2063 - Tuner handle passed back.
1527 ** hUserData - User-defined data, if needed for the
1528 ** MT_ReadSub() & MT_WriteSub functions.
1531 ** MT_OK - No errors
1532 ** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
1533 ** MT_TUNER_INIT_ERR - Tuner initialization failed
1534 ** MT_COMM_ERR - Serial bus communications error
1535 ** MT_ARG_NULL - Null pointer argument passed
1536 ** MT_TUNER_CNT_ERR - Too many tuners open
1538 ** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
1539 ** MT_WriteSub - Write byte(s) of data to the two-wire bus
1541 ** Revision History:
1543 ** SCR Date Author Description
1544 ** -------------------------------------------------------------------------
1545 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1547 ******************************************************************************/
1548 u32 MT2063_Open(u32 MT2063_Addr, void ** hMT2063, void *hUserData)
1550 u32 status = MT2063_OK; /* Status to be returned. */
1552 struct MT2063_Info_t *pInfo = NULL;
1553 struct dvb_frontend *fe = (struct dvb_frontend *)hUserData;
1554 struct mt2063_state *state = fe->tuner_priv;
1556 /* Check the argument before using */
1557 if (hMT2063 == NULL) {
1558 return MT2063_ARG_NULL;
1561 /* Default tuner handle to NULL. If successful, it will be reassigned */
1563 if (state->MT2063_init == false) {
1564 pInfo = kzalloc(sizeof(struct MT2063_Info_t), GFP_KERNEL);
1565 if (pInfo == NULL) {
1566 return MT2063_TUNER_OPEN_ERR;
1568 pInfo->handle = NULL;
1569 pInfo->address = MAX_UDATA;
1570 pInfo->rcvr_mode = MT2063_CABLE_QAM;
1571 pInfo->hUserData = NULL;
1576 if (MT2063_NO_ERROR(status)) {
1577 status |= MT2063_RegisterTuner(&pInfo->AS_Data);
1580 if (MT2063_NO_ERROR(status)) {
1581 pInfo->handle = (void *) pInfo;
1583 pInfo->hUserData = hUserData;
1584 pInfo->address = MT2063_Addr;
1585 pInfo->rcvr_mode = MT2063_CABLE_QAM;
1586 status |= MT2063_ReInit((void *) pInfo);
1589 if (MT2063_IS_ERROR(status))
1590 /* MT2063_Close handles the un-registration of the tuner */
1591 MT2063_Close((void *) pInfo);
1593 state->MT2063_init = true;
1594 *hMT2063 = pInfo->handle;
1601 static u32 MT2063_IsValidHandle(struct MT2063_Info_t *handle)
1603 return ((handle != NULL) && (handle->handle == handle)) ? 1 : 0;
1606 /******************************************************************************
1608 ** Name: MT2063_Close
1610 ** Description: Release the handle to the tuner.
1612 ** Parameters: hMT2063 - Handle to the MT2063 tuner
1615 ** MT_OK - No errors
1616 ** MT_INV_HANDLE - Invalid tuner handle
1618 ** Dependencies: mt_errordef.h - definition of error codes
1620 ** Revision History:
1622 ** SCR Date Author Description
1623 ** -------------------------------------------------------------------------
1624 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1626 ******************************************************************************/
1627 u32 MT2063_Close(void *hMT2063)
1629 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)hMT2063;
1631 if (!MT2063_IsValidHandle(pInfo))
1632 return MT2063_INV_HANDLE;
1634 /* Unregister tuner with SpurAvoidance routines (if needed) */
1635 MT2063_UnRegisterTuner(&pInfo->AS_Data);
1636 /* Now remove the tuner from our own list of tuners */
1637 pInfo->handle = NULL;
1638 pInfo->address = MAX_UDATA;
1639 pInfo->hUserData = NULL;
1646 /******************************************************************************
1648 ** Name: MT2063_GetGPIO
1650 ** Description: Get the current MT2063 GPIO value.
1652 ** Parameters: h - Open handle to the tuner (from MT2063_Open).
1653 ** gpio_id - Selects GPIO0, GPIO1 or GPIO2
1654 ** attr - Selects input readback, I/O direction or
1656 ** *value - current setting of GPIO pin
1658 ** Usage: status = MT2063_GetGPIO(hMT2063, MT2063_GPIO_OUT, &value);
1661 ** MT_OK - No errors
1662 ** MT_COMM_ERR - Serial bus communications error
1663 ** MT_INV_HANDLE - Invalid tuner handle
1664 ** MT_ARG_NULL - Null pointer argument passed
1666 ** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1668 ** Revision History:
1670 ** SCR Date Author Description
1671 ** -------------------------------------------------------------------------
1672 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1674 ******************************************************************************/
1675 u32 MT2063_GetGPIO(void *h, enum MT2063_GPIO_ID gpio_id,
1676 enum MT2063_GPIO_Attr attr, u32 * value)
1678 u32 status = MT2063_OK; /* Status to be returned */
1681 static u8 GPIOreg[3] =
1682 { MT2063_REG_RF_STATUS, MT2063_REG_FIF_OV, MT2063_REG_RF_OV };
1683 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1685 if (MT2063_IsValidHandle(pInfo) == 0)
1686 return MT2063_INV_HANDLE;
1689 return MT2063_ARG_NULL;
1691 regno = GPIOreg[attr];
1693 /* We'll read the register just in case the write didn't work last time */
1695 MT2063_ReadSub(pInfo->hUserData, pInfo->address, regno,
1696 &pInfo->reg[regno], 1);
1698 shift = (gpio_id - MT2063_GPIO0 + 5);
1699 *value = (pInfo->reg[regno] >> shift) & 1;
1704 /****************************************************************************
1706 ** Name: MT2063_GetLocked
1708 ** Description: Checks to see if LO1 and LO2 are locked.
1710 ** Parameters: h - Open handle to the tuner (from MT2063_Open).
1713 ** MT_OK - No errors
1714 ** MT_UPC_UNLOCK - Upconverter PLL unlocked
1715 ** MT_DNC_UNLOCK - Downconverter PLL unlocked
1716 ** MT_COMM_ERR - Serial bus communications error
1717 ** MT_INV_HANDLE - Invalid tuner handle
1719 ** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus
1720 ** MT_Sleep - Delay execution for x milliseconds
1722 ** Revision History:
1724 ** SCR Date Author Description
1725 ** -------------------------------------------------------------------------
1726 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1728 ****************************************************************************/
1729 u32 MT2063_GetLocked(void *h)
1731 const u32 nMaxWait = 100; /* wait a maximum of 100 msec */
1732 const u32 nPollRate = 2; /* poll status bits every 2 ms */
1733 const u32 nMaxLoops = nMaxWait / nPollRate;
1734 const u8 LO1LK = 0x80;
1736 u32 status = MT2063_OK; /* Status to be returned */
1738 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1740 if (MT2063_IsValidHandle(pInfo) == 0)
1741 return MT2063_INV_HANDLE;
1743 /* LO2 Lock bit was in a different place for B0 version */
1744 if (pInfo->tuner_id == MT2063_B0)
1749 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
1750 MT2063_REG_LO_STATUS,
1751 &pInfo->reg[MT2063_REG_LO_STATUS], 1);
1753 if (MT2063_IS_ERROR(status))
1756 if ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
1760 MT2063_Sleep(pInfo->hUserData, nPollRate); /* Wait between retries */
1762 while (++nDelays < nMaxLoops);
1764 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00)
1765 status |= MT2063_UPC_UNLOCK;
1766 if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00)
1767 status |= MT2063_DNC_UNLOCK;
1772 /****************************************************************************
1774 ** Name: MT2063_GetParam
1776 ** Description: Gets a tuning algorithm parameter.
1778 ** This function provides access to the internals of the
1779 ** tuning algorithm - mostly for testing purposes.
1781 ** Parameters: h - Tuner handle (returned by MT2063_Open)
1782 ** param - Tuning algorithm parameter
1783 ** (see enum MT2063_Param)
1784 ** pValue - ptr to returned value
1786 ** param Description
1787 ** ---------------------- --------------------------------
1788 ** MT2063_IC_ADDR Serial Bus address of this tuner
1789 ** MT2063_MAX_OPEN Max # of MT2063's allowed open
1790 ** MT2063_NUM_OPEN # of MT2063's open
1791 ** MT2063_SRO_FREQ crystal frequency
1792 ** MT2063_STEPSIZE minimum tuning step size
1793 ** MT2063_INPUT_FREQ input center frequency
1794 ** MT2063_LO1_FREQ LO1 Frequency
1795 ** MT2063_LO1_STEPSIZE LO1 minimum step size
1796 ** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
1797 ** MT2063_IF1_ACTUAL Current 1st IF in use
1798 ** MT2063_IF1_REQUEST Requested 1st IF
1799 ** MT2063_IF1_CENTER Center of 1st IF SAW filter
1800 ** MT2063_IF1_BW Bandwidth of 1st IF SAW filter
1801 ** MT2063_ZIF_BW zero-IF bandwidth
1802 ** MT2063_LO2_FREQ LO2 Frequency
1803 ** MT2063_LO2_STEPSIZE LO2 minimum step size
1804 ** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
1805 ** MT2063_OUTPUT_FREQ output center frequency
1806 ** MT2063_OUTPUT_BW output bandwidth
1807 ** MT2063_LO_SEPARATION min inter-tuner LO separation
1808 ** MT2063_AS_ALG ID of avoid-spurs algorithm in use
1809 ** MT2063_MAX_HARM1 max # of intra-tuner harmonics
1810 ** MT2063_MAX_HARM2 max # of inter-tuner harmonics
1811 ** MT2063_EXCL_ZONES # of 1st IF exclusion zones
1812 ** MT2063_NUM_SPURS # of spurs found/avoided
1813 ** MT2063_SPUR_AVOIDED >0 spurs avoided
1814 ** MT2063_SPUR_PRESENT >0 spurs in output (mathematically)
1815 ** MT2063_RCVR_MODE Predefined modes.
1816 ** MT2063_ACLNA LNA attenuator gain code
1817 ** MT2063_ACRF RF attenuator gain code
1818 ** MT2063_ACFIF FIF attenuator gain code
1819 ** MT2063_ACLNA_MAX LNA attenuator limit
1820 ** MT2063_ACRF_MAX RF attenuator limit
1821 ** MT2063_ACFIF_MAX FIF attenuator limit
1822 ** MT2063_PD1 Actual value of PD1
1823 ** MT2063_PD2 Actual value of PD2
1824 ** MT2063_DNC_OUTPUT_ENABLE DNC output selection
1825 ** MT2063_VGAGC VGA gain code
1826 ** MT2063_VGAOI VGA output current
1827 ** MT2063_TAGC TAGC setting
1828 ** MT2063_AMPGC AMP gain code
1829 ** MT2063_AVOID_DECT Avoid DECT Frequencies
1830 ** MT2063_CTFILT_SW Cleartune filter selection
1832 ** Usage: status |= MT2063_GetParam(hMT2063,
1833 ** MT2063_IF1_ACTUAL,
1837 ** MT_OK - No errors
1838 ** MT_INV_HANDLE - Invalid tuner handle
1839 ** MT_ARG_NULL - Null pointer argument passed
1840 ** MT_ARG_RANGE - Invalid parameter requested
1842 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
1844 ** See Also: MT2063_SetParam, MT2063_Open
1846 ** Revision History:
1848 ** SCR Date Author Description
1849 ** -------------------------------------------------------------------------
1850 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
1851 ** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
1852 ** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
1853 ** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW
1855 ** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
1856 ** Split SetParam up to ACLNA / ACLNA_MAX
1857 ** removed ACLNA_INRC/DECR (+RF & FIF)
1858 ** removed GCUAUTO / BYPATNDN/UP
1859 ** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
1860 ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
1861 ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
1863 ****************************************************************************/
1864 u32 MT2063_GetParam(void *h, enum MT2063_Param param, u32 * pValue)
1866 u32 status = MT2063_OK; /* Status to be returned */
1867 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
1872 status |= MT2063_ARG_NULL;
1874 /* Verify that the handle passed points to a valid tuner */
1875 if (MT2063_IsValidHandle(pInfo) == 0)
1876 status |= MT2063_INV_HANDLE;
1878 if (MT2063_NO_ERROR(status)) {
1880 /* Serial Bus address of this tuner */
1881 case MT2063_IC_ADDR:
1882 *pValue = pInfo->address;
1885 /* Max # of MT2063's allowed to be open */
1886 case MT2063_MAX_OPEN:
1887 *pValue = nMT2063MaxTuners;
1890 /* # of MT2063's open */
1891 case MT2063_NUM_OPEN:
1892 *pValue = nMT2063OpenTuners;
1895 /* crystal frequency */
1896 case MT2063_SRO_FREQ:
1897 *pValue = pInfo->AS_Data.f_ref;
1900 /* minimum tuning step size */
1901 case MT2063_STEPSIZE:
1902 *pValue = pInfo->AS_Data.f_LO2_Step;
1905 /* input center frequency */
1906 case MT2063_INPUT_FREQ:
1907 *pValue = pInfo->AS_Data.f_in;
1911 case MT2063_LO1_FREQ:
1913 /* read the actual tuner register values for LO1C_1 and LO1C_2 */
1915 MT2063_ReadSub(pInfo->hUserData,
1919 reg[MT2063_REG_LO1C_1], 2);
1920 Div = pInfo->reg[MT2063_REG_LO1C_1];
1921 Num = pInfo->reg[MT2063_REG_LO1C_2] & 0x3F;
1922 pInfo->AS_Data.f_LO1 =
1923 (pInfo->AS_Data.f_ref * Div) +
1924 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
1927 *pValue = pInfo->AS_Data.f_LO1;
1930 /* LO1 minimum step size */
1931 case MT2063_LO1_STEPSIZE:
1932 *pValue = pInfo->AS_Data.f_LO1_Step;
1935 /* LO1 FracN keep-out region */
1936 case MT2063_LO1_FRACN_AVOID_PARAM:
1937 *pValue = pInfo->AS_Data.f_LO1_FracN_Avoid;
1940 /* Current 1st IF in use */
1941 case MT2063_IF1_ACTUAL:
1942 *pValue = pInfo->f_IF1_actual;
1945 /* Requested 1st IF */
1946 case MT2063_IF1_REQUEST:
1947 *pValue = pInfo->AS_Data.f_if1_Request;
1950 /* Center of 1st IF SAW filter */
1951 case MT2063_IF1_CENTER:
1952 *pValue = pInfo->AS_Data.f_if1_Center;
1955 /* Bandwidth of 1st IF SAW filter */
1957 *pValue = pInfo->AS_Data.f_if1_bw;
1960 /* zero-IF bandwidth */
1962 *pValue = pInfo->AS_Data.f_zif_bw;
1966 case MT2063_LO2_FREQ:
1968 /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */
1970 MT2063_ReadSub(pInfo->hUserData,
1974 reg[MT2063_REG_LO2C_1], 3);
1976 (pInfo->reg[MT2063_REG_LO2C_1] & 0xFE) >> 1;
1979 reg[MT2063_REG_LO2C_1] & 0x01) << 12) |
1981 reg[MT2063_REG_LO2C_2] << 4) | (pInfo->
1985 pInfo->AS_Data.f_LO2 =
1986 (pInfo->AS_Data.f_ref * Div) +
1987 MT2063_fLO_FractionalTerm(pInfo->AS_Data.
1990 *pValue = pInfo->AS_Data.f_LO2;
1993 /* LO2 minimum step size */
1994 case MT2063_LO2_STEPSIZE:
1995 *pValue = pInfo->AS_Data.f_LO2_Step;
1998 /* LO2 FracN keep-out region */
1999 case MT2063_LO2_FRACN_AVOID:
2000 *pValue = pInfo->AS_Data.f_LO2_FracN_Avoid;
2003 /* output center frequency */
2004 case MT2063_OUTPUT_FREQ:
2005 *pValue = pInfo->AS_Data.f_out;
2008 /* output bandwidth */
2009 case MT2063_OUTPUT_BW:
2010 *pValue = pInfo->AS_Data.f_out_bw - 750000;
2013 /* min inter-tuner LO separation */
2014 case MT2063_LO_SEPARATION:
2015 *pValue = pInfo->AS_Data.f_min_LO_Separation;
2018 /* ID of avoid-spurs algorithm in use */
2020 *pValue = pInfo->AS_Data.nAS_Algorithm;
2023 /* max # of intra-tuner harmonics */
2024 case MT2063_MAX_HARM1:
2025 *pValue = pInfo->AS_Data.maxH1;
2028 /* max # of inter-tuner harmonics */
2029 case MT2063_MAX_HARM2:
2030 *pValue = pInfo->AS_Data.maxH2;
2033 /* # of 1st IF exclusion zones */
2034 case MT2063_EXCL_ZONES:
2035 *pValue = pInfo->AS_Data.nZones;
2038 /* # of spurs found/avoided */
2039 case MT2063_NUM_SPURS:
2040 *pValue = pInfo->AS_Data.nSpursFound;
2043 /* >0 spurs avoided */
2044 case MT2063_SPUR_AVOIDED:
2045 *pValue = pInfo->AS_Data.bSpurAvoided;
2048 /* >0 spurs in output (mathematically) */
2049 case MT2063_SPUR_PRESENT:
2050 *pValue = pInfo->AS_Data.bSpurPresent;
2053 /* Predefined receiver setup combination */
2054 case MT2063_RCVR_MODE:
2055 *pValue = pInfo->rcvr_mode;
2061 u8 mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */
2062 u8 orig = (pInfo->reg[MT2063_REG_BYP_CTRL]);
2063 u8 reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */
2068 /* Initiate ADC output to reg 0x0A */
2071 MT2063_WriteSub(pInfo->hUserData,
2073 MT2063_REG_BYP_CTRL,
2076 if (MT2063_IS_ERROR(status))
2079 for (i = 0; i < 8; i++) {
2081 MT2063_ReadSub(pInfo->hUserData,
2086 [MT2063_REG_ADC_OUT],
2089 if (MT2063_NO_ERROR(status))
2092 reg[MT2063_REG_ADC_OUT];
2099 *pValue /= 8; /* divide by number of reads */
2100 *pValue >>= 2; /* only want 6 MSB's out of 8 */
2102 /* Restore value of Register BYP_CTRL */
2105 MT2063_WriteSub(pInfo->hUserData,
2107 MT2063_REG_BYP_CTRL,
2112 /* Get LNA attenuator code */
2117 MT2063_GetReg(pInfo, MT2063_REG_XO_STATUS,
2119 *pValue = val & 0x1f;
2123 /* Get RF attenuator code */
2128 MT2063_GetReg(pInfo, MT2063_REG_RF_STATUS,
2130 *pValue = val & 0x1f;
2134 /* Get FIF attenuator code */
2139 MT2063_GetReg(pInfo, MT2063_REG_FIF_STATUS,
2141 *pValue = val & 0x1f;
2145 /* Get LNA attenuator limit */
2146 case MT2063_ACLNA_MAX:
2150 MT2063_GetReg(pInfo, MT2063_REG_LNA_OV,
2152 *pValue = val & 0x1f;
2156 /* Get RF attenuator limit */
2157 case MT2063_ACRF_MAX:
2161 MT2063_GetReg(pInfo, MT2063_REG_RF_OV,
2163 *pValue = val & 0x1f;
2167 /* Get FIF attenuator limit */
2168 case MT2063_ACFIF_MAX:
2172 MT2063_GetReg(pInfo, MT2063_REG_FIF_OV,
2174 *pValue = val & 0x1f;
2178 /* Get current used DNC output */
2179 case MT2063_DNC_OUTPUT_ENABLE:
2181 if ((pInfo->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) { /* if DNC1 is off */
2182 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2184 (u32) MT2063_DNC_NONE;
2188 } else { /* DNC1 is on */
2190 if ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */
2195 (u32) MT2063_DNC_BOTH;
2200 /* Get VGA Gain Code */
2203 ((pInfo->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2);
2206 /* Get VGA bias current */
2208 *pValue = (pInfo->reg[MT2063_REG_RSVD_31] & 0x07);
2211 /* Get TAGC setting */
2213 *pValue = (pInfo->reg[MT2063_REG_RSVD_1E] & 0x03);
2216 /* Get AMP Gain Code */
2218 *pValue = (pInfo->reg[MT2063_REG_TEMP_SEL] & 0x03);
2221 /* Avoid DECT Frequencies */
2222 case MT2063_AVOID_DECT:
2223 *pValue = pInfo->AS_Data.avoidDECT;
2226 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
2227 case MT2063_CTFILT_SW:
2228 *pValue = pInfo->ctfilt_sw;
2233 status |= MT2063_ARG_RANGE;
2239 /****************************************************************************
2241 ** Name: MT2063_GetReg
2243 ** Description: Gets an MT2063 register.
2245 ** Parameters: h - Tuner handle (returned by MT2063_Open)
2246 ** reg - MT2063 register/subaddress location
2247 ** *val - MT2063 register/subaddress value
2250 ** MT_OK - No errors
2251 ** MT_COMM_ERR - Serial bus communications error
2252 ** MT_INV_HANDLE - Invalid tuner handle
2253 ** MT_ARG_NULL - Null pointer argument passed
2254 ** MT_ARG_RANGE - Argument out of range
2256 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2258 ** Use this function if you need to read a register from
2261 ** Revision History:
2263 ** SCR Date Author Description
2264 ** -------------------------------------------------------------------------
2265 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2267 ****************************************************************************/
2268 u32 MT2063_GetReg(void *h, u8 reg, u8 * val)
2270 u32 status = MT2063_OK; /* Status to be returned */
2271 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2273 /* Verify that the handle passed points to a valid tuner */
2274 if (MT2063_IsValidHandle(pInfo) == 0)
2275 status |= MT2063_INV_HANDLE;
2278 status |= MT2063_ARG_NULL;
2280 if (reg >= MT2063_REG_END_REGS)
2281 status |= MT2063_ARG_RANGE;
2283 if (MT2063_NO_ERROR(status)) {
2285 MT2063_ReadSub(pInfo->hUserData, pInfo->address, reg,
2286 &pInfo->reg[reg], 1);
2287 if (MT2063_NO_ERROR(status))
2288 *val = pInfo->reg[reg];
2294 /******************************************************************************
2296 ** Name: MT2063_GetTemp
2298 ** Description: Get the MT2063 Temperature register.
2300 ** Parameters: h - Open handle to the tuner (from MT2063_Open).
2301 ** *value - value read from the register
2304 ** Value Returned Value Approx Temp
2305 ** ---------------------------------------------
2306 ** MT2063_T_0C 0000 0C
2307 ** MT2063_T_10C 0001 10C
2308 ** MT2063_T_20C 0010 20C
2309 ** MT2063_T_30C 0011 30C
2310 ** MT2063_T_40C 0100 40C
2311 ** MT2063_T_50C 0101 50C
2312 ** MT2063_T_60C 0110 60C
2313 ** MT2063_T_70C 0111 70C
2314 ** MT2063_T_80C 1000 80C
2315 ** MT2063_T_90C 1001 90C
2316 ** MT2063_T_100C 1010 100C
2317 ** MT2063_T_110C 1011 110C
2318 ** MT2063_T_120C 1100 120C
2319 ** MT2063_T_130C 1101 130C
2320 ** MT2063_T_140C 1110 140C
2321 ** MT2063_T_150C 1111 150C
2324 ** MT_OK - No errors
2325 ** MT_COMM_ERR - Serial bus communications error
2326 ** MT_INV_HANDLE - Invalid tuner handle
2327 ** MT_ARG_NULL - Null pointer argument passed
2328 ** MT_ARG_RANGE - Argument out of range
2330 ** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2331 ** MT_WriteSub - Write byte(s) of data to the two-wire bus
2333 ** Revision History:
2335 ** SCR Date Author Description
2336 ** -------------------------------------------------------------------------
2337 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2339 ******************************************************************************/
2340 u32 MT2063_GetTemp(void *h, enum MT2063_Temperature * value)
2342 u32 status = MT2063_OK; /* Status to be returned */
2343 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2345 if (MT2063_IsValidHandle(pInfo) == 0)
2346 return MT2063_INV_HANDLE;
2349 return MT2063_ARG_NULL;
2351 if ((MT2063_NO_ERROR(status))
2352 && ((pInfo->reg[MT2063_REG_TEMP_SEL] & 0xE0) != 0x00)) {
2353 pInfo->reg[MT2063_REG_TEMP_SEL] &= (0x1F);
2354 status |= MT2063_WriteSub(pInfo->hUserData,
2356 MT2063_REG_TEMP_SEL,
2357 &pInfo->reg[MT2063_REG_TEMP_SEL], 1);
2360 if (MT2063_NO_ERROR(status))
2361 status |= MT2063_ReadSub(pInfo->hUserData,
2363 MT2063_REG_TEMP_STATUS,
2364 &pInfo->reg[MT2063_REG_TEMP_STATUS],
2367 if (MT2063_NO_ERROR(status))
2369 (enum MT2063_Temperature)(pInfo->
2370 reg[MT2063_REG_TEMP_STATUS] >> 4);
2375 /****************************************************************************
2377 ** Name: MT2063_GetUserData
2379 ** Description: Gets the user-defined data item.
2381 ** Parameters: h - Tuner handle (returned by MT2063_Open)
2384 ** MT_OK - No errors
2385 ** MT_INV_HANDLE - Invalid tuner handle
2386 ** MT_ARG_NULL - Null pointer argument passed
2388 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
2390 ** The hUserData parameter is a user-specific argument
2391 ** that is stored internally with the other tuner-
2392 ** specific information.
2394 ** For example, if additional arguments are needed
2395 ** for the user to identify the device communicating
2396 ** with the tuner, this argument can be used to supply
2397 ** the necessary information.
2399 ** The hUserData parameter is initialized in the tuner's
2400 ** Open function to NULL.
2402 ** See Also: MT2063_Open
2404 ** Revision History:
2406 ** SCR Date Author Description
2407 ** -------------------------------------------------------------------------
2408 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2410 ****************************************************************************/
2411 u32 MT2063_GetUserData(void *h, void ** hUserData)
2413 u32 status = MT2063_OK; /* Status to be returned */
2414 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2416 /* Verify that the handle passed points to a valid tuner */
2417 if (MT2063_IsValidHandle(pInfo) == 0)
2418 status = MT2063_INV_HANDLE;
2420 if (hUserData == NULL)
2421 status |= MT2063_ARG_NULL;
2423 if (MT2063_NO_ERROR(status))
2424 *hUserData = pInfo->hUserData;
2429 /******************************************************************************
2431 ** Name: MT2063_SetReceiverMode
2433 ** Description: Set the MT2063 receiver mode
2435 ** --------------+----------------------------------------------
2436 ** Mode 0 : | MT2063_CABLE_QAM
2437 ** Mode 1 : | MT2063_CABLE_ANALOG
2438 ** Mode 2 : | MT2063_OFFAIR_COFDM
2439 ** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS
2440 ** Mode 4 : | MT2063_OFFAIR_ANALOG
2441 ** Mode 5 : | MT2063_OFFAIR_8VSB
2442 ** --------------+----+----+----+----+-----+--------------------
2443 ** (DNC1GC & DNC2GC are the values, which are used, when the specific
2444 ** DNC Output is selected, the other is always off)
2446 ** |<---------- Mode -------------->|
2447 ** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 |
2448 ** ------------+-----+-----+-----+-----+-----+-----+
2449 ** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF
2450 ** LNARin | 0 | 0 | 3 | 3 | 3 | 3
2451 ** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1
2452 ** FIFFq | 0 | 0 | 0 | 0 | 0 | 0
2453 ** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0
2454 ** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0
2455 ** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1
2456 ** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31
2457 ** LNA Target | 44 | 43 | 43 | 43 | 43 | 43
2458 ** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2459 ** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31
2460 ** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38
2461 ** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0
2462 ** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5
2463 ** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42
2466 ** Parameters: pInfo - ptr to MT2063_Info_t structure
2467 ** Mode - desired reciever mode
2469 ** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode);
2472 ** MT_OK - No errors
2473 ** MT_COMM_ERR - Serial bus communications error
2475 ** Dependencies: MT2063_SetReg - Write a byte of data to a HW register.
2476 ** Assumes that the tuner cache is valid.
2478 ** Revision History:
2480 ** SCR Date Author Description
2481 ** -------------------------------------------------------------------------
2482 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2483 ** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered
2484 ** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive
2486 ** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2487 ** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have
2488 ** the same settings as with MT Launcher
2489 ** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI
2490 ** Add SetParam DNC_OUTPUT_ENABLE
2491 ** Removed VGAGC from receiver mode,
2493 ** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode
2494 ** Add SetParam AMPGC, removed from rcvr-mode
2495 ** Corrected names of GCU values
2496 ** reorganized receiver modes, removed,
2497 ** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE)
2498 ** Actualized Receiver-Mode values
2499 ** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values
2500 ** N/A 11-27-2007 PINZ Improved buffered writing
2501 ** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for
2502 ** correct wakeup of the LNA after shutdown
2503 ** Set AFCsd = 1 as default
2504 ** Changed CAP1sel default
2505 ** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2506 ** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
2507 ** Split SetParam up to ACLNA / ACLNA_MAX
2508 ** removed ACLNA_INRC/DECR (+RF & FIF)
2509 ** removed GCUAUTO / BYPATNDN/UP
2511 ******************************************************************************/
2512 static u32 MT2063_SetReceiverMode(struct MT2063_Info_t *pInfo,
2513 enum MT2063_RCVR_MODES Mode)
2515 u32 status = MT2063_OK; /* Status to be returned */
2519 if (Mode >= MT2063_NUM_RCVR_MODES)
2520 status = MT2063_ARG_RANGE;
2523 if (MT2063_NO_ERROR(status)) {
2526 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x40) | (RFAGCEN[Mode]
2529 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2530 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2535 if (MT2063_NO_ERROR(status)) {
2536 status |= MT2063_SetParam(pInfo, MT2063_LNA_RIN, LNARIN[Mode]);
2539 /* FIFFQEN and FIFFQ */
2540 if (MT2063_NO_ERROR(status)) {
2543 reg[MT2063_REG_FIFF_CTRL2] & (u8) ~ 0xF0) |
2544 (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
2545 if (pInfo->reg[MT2063_REG_FIFF_CTRL2] != val) {
2547 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL2, val);
2548 /* trigger FIFF calibration, needed after changing FIFFQ */
2550 (pInfo->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
2552 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2555 reg[MT2063_REG_FIFF_CTRL] & (u8) ~ 0x01);
2557 MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val);
2561 /* DNC1GC & DNC2GC */
2562 status |= MT2063_GetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, &longval);
2563 status |= MT2063_SetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, longval);
2566 if (MT2063_NO_ERROR(status)) {
2568 MT2063_SetParam(pInfo, MT2063_ACLNA_MAX, ACLNAMAX[Mode]);
2572 if (MT2063_NO_ERROR(status)) {
2573 status |= MT2063_SetParam(pInfo, MT2063_LNA_TGT, LNATGT[Mode]);
2577 if (MT2063_NO_ERROR(status)) {
2579 MT2063_SetParam(pInfo, MT2063_ACRF_MAX, ACRFMAX[Mode]);
2583 if (MT2063_NO_ERROR(status)) {
2584 status |= MT2063_SetParam(pInfo, MT2063_PD1_TGT, PD1TGT[Mode]);
2588 if (MT2063_NO_ERROR(status)) {
2590 MT2063_SetParam(pInfo, MT2063_ACFIF_MAX, ACFIFMAX[Mode]);
2594 if (MT2063_NO_ERROR(status)) {
2595 status |= MT2063_SetParam(pInfo, MT2063_PD2_TGT, PD2TGT[Mode]);
2598 /* Ignore ATN Overload */
2599 if (MT2063_NO_ERROR(status)) {
2602 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x80) | (RFOVDIS[Mode]
2605 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
2606 status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val);
2610 /* Ignore FIF Overload */
2611 if (MT2063_NO_ERROR(status)) {
2614 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x80) |
2615 (FIFOVDIS[Mode] ? 0x80 : 0x00);
2616 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
2617 status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val);
2621 if (MT2063_NO_ERROR(status))
2622 pInfo->rcvr_mode = Mode;
2627 /******************************************************************************
2629 ** Name: MT2063_ReInit
2631 ** Description: Initialize the tuner's register values.
2633 ** Parameters: h - Tuner handle (returned by MT2063_Open)
2636 ** MT_OK - No errors
2637 ** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch
2638 ** MT_INV_HANDLE - Invalid tuner handle
2639 ** MT_COMM_ERR - Serial bus communications error
2641 ** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus
2642 ** MT_WriteSub - Write byte(s) of data to the two-wire bus
2644 ** Revision History:
2646 ** SCR Date Author Description
2647 ** -------------------------------------------------------------------------
2648 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2649 ** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference
2650 ** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements
2651 ** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0
2652 ** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0
2653 ** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults
2654 ** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default
2655 ** 01-14-2008 PINZ Ver 1.11: Updated gain settings
2656 ** 03-18-2008 PINZ Ver 1.13: Added Support for B3
2657 ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
2658 ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
2660 ******************************************************************************/
2661 u32 MT2063_ReInit(void *h)
2663 u8 all_resets = 0xF0; /* reset/load bits */
2664 u32 status = MT2063_OK; /* Status to be returned */
2665 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2668 u8 MT2063B0_defaults[] = { /* Reg, Value */
2681 0x2C, 0x27, /* bit at 0x20 is cleared below */
2683 0x2C, 0x07, /* bit at 0x20 is cleared here */
2686 0x28, 0xE1, /* Set the FIFCrst bit here */
2687 0x28, 0xE0, /* Clear the FIFCrst bit here */
2691 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2692 u8 MT2063B1_defaults[] = { /* Reg, Value */
2694 0x11, 0x10, /* New Enable AFCsd */
2703 0x22, 0x21, /* New - ver 1.03 */
2704 0x23, 0x3C, /* New - ver 1.10 */
2705 0x24, 0x20, /* New - ver 1.03 */
2706 0x2C, 0x24, /* bit at 0x20 is cleared below */
2707 0x2D, 0x87, /* FIFFQ=0 */
2709 0x30, 0x0C, /* New - ver 1.11 */
2710 0x31, 0x1B, /* New - ver 1.11 */
2711 0x2C, 0x04, /* bit at 0x20 is cleared here */
2712 0x28, 0xE1, /* Set the FIFCrst bit here */
2713 0x28, 0xE0, /* Clear the FIFCrst bit here */
2717 /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
2718 u8 MT2063B3_defaults[] = { /* Reg, Value */
2721 0x2C, 0x24, /* bit at 0x20 is cleared below */
2722 0x2C, 0x04, /* bit at 0x20 is cleared here */
2723 0x28, 0xE1, /* Set the FIFCrst bit here */
2724 0x28, 0xE0, /* Clear the FIFCrst bit here */
2728 /* Verify that the handle passed points to a valid tuner */
2729 if (MT2063_IsValidHandle(pInfo) == 0)
2730 status |= MT2063_INV_HANDLE;
2732 /* Read the Part/Rev code from the tuner */
2733 if (MT2063_NO_ERROR(status)) {
2735 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2736 MT2063_REG_PART_REV, pInfo->reg, 1);
2739 if (MT2063_NO_ERROR(status) /* Check the part/rev code */
2740 &&((pInfo->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */
2741 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */
2742 &&(pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */
2743 status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */
2745 /* Read the Part/Rev code (2nd byte) from the tuner */
2746 if (MT2063_NO_ERROR(status))
2748 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2750 &pInfo->reg[MT2063_REG_RSVD_3B], 1);
2752 if (MT2063_NO_ERROR(status) /* Check the 2nd part/rev code */
2753 &&((pInfo->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */
2754 status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */
2756 /* Reset the tuner */
2757 if (MT2063_NO_ERROR(status))
2758 status |= MT2063_WriteSub(pInfo->hUserData,
2760 MT2063_REG_LO2CQ_3, &all_resets, 1);
2762 /* change all of the default values that vary from the HW reset values */
2763 /* def = (pInfo->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
2764 switch (pInfo->reg[MT2063_REG_PART_REV]) {
2766 def = MT2063B3_defaults;
2770 def = MT2063B1_defaults;
2774 def = MT2063B0_defaults;
2778 status |= MT2063_TUNER_ID_ERR;
2782 while (MT2063_NO_ERROR(status) && *def) {
2786 MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
2790 /* Wait for FIFF location to complete. */
2791 if (MT2063_NO_ERROR(status)) {
2794 while (MT2063_NO_ERROR(status) && (FCRUN != 0)
2795 && (maxReads-- > 0)) {
2796 MT2063_Sleep(pInfo->hUserData, 2);
2797 status |= MT2063_ReadSub(pInfo->hUserData,
2799 MT2063_REG_XO_STATUS,
2801 reg[MT2063_REG_XO_STATUS], 1);
2802 FCRUN = (pInfo->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
2806 status |= MT2063_TUNER_INIT_ERR | MT2063_TUNER_TIMEOUT;
2808 if (MT2063_NO_ERROR(status)) /* Re-read FIFFC value */
2810 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2812 &pInfo->reg[MT2063_REG_FIFFC], 1);
2815 /* Read back all the registers from the tuner */
2816 if (MT2063_NO_ERROR(status))
2817 status |= MT2063_ReadSub(pInfo->hUserData,
2819 MT2063_REG_PART_REV,
2820 pInfo->reg, MT2063_REG_END_REGS);
2822 if (MT2063_NO_ERROR(status)) {
2823 /* Initialize the tuner state. */
2824 pInfo->version = MT2063_VERSION;
2825 pInfo->tuner_id = pInfo->reg[MT2063_REG_PART_REV];
2826 pInfo->AS_Data.f_ref = MT2063_REF_FREQ;
2827 pInfo->AS_Data.f_if1_Center =
2828 (pInfo->AS_Data.f_ref / 8) *
2829 ((u32) pInfo->reg[MT2063_REG_FIFFC] + 640);
2830 pInfo->AS_Data.f_if1_bw = MT2063_IF1_BW;
2831 pInfo->AS_Data.f_out = 43750000UL;
2832 pInfo->AS_Data.f_out_bw = 6750000UL;
2833 pInfo->AS_Data.f_zif_bw = MT2063_ZIF_BW;
2834 pInfo->AS_Data.f_LO1_Step = pInfo->AS_Data.f_ref / 64;
2835 pInfo->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
2836 pInfo->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
2837 pInfo->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
2838 pInfo->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
2839 pInfo->AS_Data.f_if1_Request = pInfo->AS_Data.f_if1_Center;
2840 pInfo->AS_Data.f_LO1 = 2181000000UL;
2841 pInfo->AS_Data.f_LO2 = 1486249786UL;
2842 pInfo->f_IF1_actual = pInfo->AS_Data.f_if1_Center;
2843 pInfo->AS_Data.f_in =
2844 pInfo->AS_Data.f_LO1 - pInfo->f_IF1_actual;
2845 pInfo->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
2846 pInfo->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
2847 pInfo->num_regs = MT2063_REG_END_REGS;
2848 pInfo->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
2849 pInfo->ctfilt_sw = 0;
2852 if (MT2063_NO_ERROR(status)) {
2853 pInfo->CTFiltMax[0] = 69230000;
2854 pInfo->CTFiltMax[1] = 105770000;
2855 pInfo->CTFiltMax[2] = 140350000;
2856 pInfo->CTFiltMax[3] = 177110000;
2857 pInfo->CTFiltMax[4] = 212860000;
2858 pInfo->CTFiltMax[5] = 241130000;
2859 pInfo->CTFiltMax[6] = 274370000;
2860 pInfo->CTFiltMax[7] = 309820000;
2861 pInfo->CTFiltMax[8] = 342450000;
2862 pInfo->CTFiltMax[9] = 378870000;
2863 pInfo->CTFiltMax[10] = 416210000;
2864 pInfo->CTFiltMax[11] = 456500000;
2865 pInfo->CTFiltMax[12] = 495790000;
2866 pInfo->CTFiltMax[13] = 534530000;
2867 pInfo->CTFiltMax[14] = 572610000;
2868 pInfo->CTFiltMax[15] = 598970000;
2869 pInfo->CTFiltMax[16] = 635910000;
2870 pInfo->CTFiltMax[17] = 672130000;
2871 pInfo->CTFiltMax[18] = 714840000;
2872 pInfo->CTFiltMax[19] = 739660000;
2873 pInfo->CTFiltMax[20] = 770410000;
2874 pInfo->CTFiltMax[21] = 814660000;
2875 pInfo->CTFiltMax[22] = 846950000;
2876 pInfo->CTFiltMax[23] = 867820000;
2877 pInfo->CTFiltMax[24] = 915980000;
2878 pInfo->CTFiltMax[25] = 947450000;
2879 pInfo->CTFiltMax[26] = 983110000;
2880 pInfo->CTFiltMax[27] = 1021630000;
2881 pInfo->CTFiltMax[28] = 1061870000;
2882 pInfo->CTFiltMax[29] = 1098330000;
2883 pInfo->CTFiltMax[30] = 1138990000;
2887 ** Fetch the FCU osc value and use it and the fRef value to
2888 ** scale all of the Band Max values
2890 if (MT2063_NO_ERROR(status)) {
2894 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
2896 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
2897 MT2063_REG_CTUNE_CTRL,
2898 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2899 /* Read the ClearTune filter calibration value */
2901 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
2903 &pInfo->reg[MT2063_REG_FIFFC], 1);
2904 fcu_osc = pInfo->reg[MT2063_REG_FIFFC];
2906 pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
2908 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
2909 MT2063_REG_CTUNE_CTRL,
2910 &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1);
2912 /* Adjust each of the values in the ClearTune filter cross-over table */
2913 for (i = 0; i < 31; i++) {
2914 pInfo->CTFiltMax[i] =
2915 (pInfo->CTFiltMax[i] / 768) * (fcu_osc + 640);
2922 /******************************************************************************
2924 ** Name: MT2063_SetGPIO
2926 ** Description: Modify the MT2063 GPIO value.
2928 ** Parameters: h - Open handle to the tuner (from MT2063_Open).
2929 ** gpio_id - Selects GPIO0, GPIO1 or GPIO2
2930 ** attr - Selects input readback, I/O direction or
2932 ** value - value to set GPIO pin 15, 14 or 19
2934 ** Usage: status = MT2063_SetGPIO(hMT2063, MT2063_GPIO1, MT2063_GPIO_OUT, 1);
2937 ** MT_OK - No errors
2938 ** MT_COMM_ERR - Serial bus communications error
2939 ** MT_INV_HANDLE - Invalid tuner handle
2941 ** Dependencies: MT_WriteSub - Write byte(s) of data to the two-wire-bus
2943 ** Revision History:
2945 ** SCR Date Author Description
2946 ** -------------------------------------------------------------------------
2947 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
2949 ******************************************************************************/
2950 u32 MT2063_SetGPIO(void *h, enum MT2063_GPIO_ID gpio_id,
2951 enum MT2063_GPIO_Attr attr, u32 value)
2953 u32 status = MT2063_OK; /* Status to be returned */
2956 static u8 GPIOreg[3] = { 0x15, 0x19, 0x18 };
2957 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
2959 if (MT2063_IsValidHandle(pInfo) == 0)
2960 return MT2063_INV_HANDLE;
2962 regno = GPIOreg[attr];
2964 shift = (gpio_id - MT2063_GPIO0 + 5);
2967 pInfo->reg[regno] |= (0x01 << shift);
2969 pInfo->reg[regno] &= ~(0x01 << shift);
2971 MT2063_WriteSub(pInfo->hUserData, pInfo->address, regno,
2972 &pInfo->reg[regno], 1);
2977 /****************************************************************************
2979 ** Name: MT2063_SetParam
2981 ** Description: Sets a tuning algorithm parameter.
2983 ** This function provides access to the internals of the
2984 ** tuning algorithm. You can override many of the tuning
2985 ** algorithm defaults using this function.
2987 ** Parameters: h - Tuner handle (returned by MT2063_Open)
2988 ** param - Tuning algorithm parameter
2989 ** (see enum MT2063_Param)
2990 ** nValue - value to be set
2992 ** param Description
2993 ** ---------------------- --------------------------------
2994 ** MT2063_SRO_FREQ crystal frequency
2995 ** MT2063_STEPSIZE minimum tuning step size
2996 ** MT2063_LO1_FREQ LO1 frequency
2997 ** MT2063_LO1_STEPSIZE LO1 minimum step size
2998 ** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region
2999 ** MT2063_IF1_REQUEST Requested 1st IF
3000 ** MT2063_ZIF_BW zero-IF bandwidth
3001 ** MT2063_LO2_FREQ LO2 frequency
3002 ** MT2063_LO2_STEPSIZE LO2 minimum step size
3003 ** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region
3004 ** MT2063_OUTPUT_FREQ output center frequency
3005 ** MT2063_OUTPUT_BW output bandwidth
3006 ** MT2063_LO_SEPARATION min inter-tuner LO separation
3007 ** MT2063_MAX_HARM1 max # of intra-tuner harmonics
3008 ** MT2063_MAX_HARM2 max # of inter-tuner harmonics
3009 ** MT2063_RCVR_MODE Predefined modes
3010 ** MT2063_LNA_RIN Set LNA Rin (*)
3011 ** MT2063_LNA_TGT Set target power level at LNA (*)
3012 ** MT2063_PD1_TGT Set target power level at PD1 (*)
3013 ** MT2063_PD2_TGT Set target power level at PD2 (*)
3014 ** MT2063_ACLNA_MAX LNA attenuator limit (*)
3015 ** MT2063_ACRF_MAX RF attenuator limit (*)
3016 ** MT2063_ACFIF_MAX FIF attenuator limit (*)
3017 ** MT2063_DNC_OUTPUT_ENABLE DNC output selection
3018 ** MT2063_VGAGC VGA gain code
3019 ** MT2063_VGAOI VGA output current
3020 ** MT2063_TAGC TAGC setting
3021 ** MT2063_AMPGC AMP gain code
3022 ** MT2063_AVOID_DECT Avoid DECT Frequencies
3023 ** MT2063_CTFILT_SW Cleartune filter selection
3025 ** (*) This parameter is set by MT2063_RCVR_MODE, do not call
3028 ** Usage: status |= MT2063_SetParam(hMT2063,
3033 ** MT_OK - No errors
3034 ** MT_INV_HANDLE - Invalid tuner handle
3035 ** MT_ARG_NULL - Null pointer argument passed
3036 ** MT_ARG_RANGE - Invalid parameter requested
3037 ** or set value out of range
3038 ** or non-writable parameter
3040 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3042 ** See Also: MT2063_GetParam, MT2063_Open
3044 ** Revision History:
3046 ** SCR Date Author Description
3047 ** -------------------------------------------------------------------------
3048 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3049 ** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ
3050 ** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC
3051 ** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT
3052 ** Split SetParam up to ACLNA / ACLNA_MAX
3053 ** removed ACLNA_INRC/DECR (+RF & FIF)
3054 ** removed GCUAUTO / BYPATNDN/UP
3055 ** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
3056 ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
3057 ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
3059 ****************************************************************************/
3060 u32 MT2063_SetParam(void *h, enum MT2063_Param param, u32 nValue)
3062 u32 status = MT2063_OK; /* Status to be returned */
3064 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3066 /* Verify that the handle passed points to a valid tuner */
3067 if (MT2063_IsValidHandle(pInfo) == 0)
3068 status |= MT2063_INV_HANDLE;
3070 if (MT2063_NO_ERROR(status)) {
3072 /* crystal frequency */
3073 case MT2063_SRO_FREQ:
3074 pInfo->AS_Data.f_ref = nValue;
3075 pInfo->AS_Data.f_LO1_FracN_Avoid = 0;
3076 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1;
3077 pInfo->AS_Data.f_LO1_Step = nValue / 64;
3078 pInfo->AS_Data.f_if1_Center =
3079 (pInfo->AS_Data.f_ref / 8) *
3080 (pInfo->reg[MT2063_REG_FIFFC] + 640);
3083 /* minimum tuning step size */
3084 case MT2063_STEPSIZE:
3085 pInfo->AS_Data.f_LO2_Step = nValue;
3089 case MT2063_LO1_FREQ:
3091 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3092 /* Capture the Divider and Numerator portions of other LO */
3099 /* Buffer the queue for restoration later and get actual LO2 values. */
3101 MT2063_ReadSub(pInfo->hUserData,
3104 &(tempLO2CQ[0]), 3);
3106 MT2063_ReadSub(pInfo->hUserData,
3111 /* clear the one-shot bits */
3112 tempLO2CQ[2] = tempLO2CQ[2] & 0x0F;
3113 tempLO2C[2] = tempLO2C[2] & 0x0F;
3115 /* only write the queue values if they are different from the actual. */
3116 if ((tempLO2CQ[0] != tempLO2C[0]) ||
3117 (tempLO2CQ[1] != tempLO2C[1]) ||
3118 (tempLO2CQ[2] != tempLO2C[2])) {
3119 /* put actual LO2 value into queue (with 0 in one-shot bits) */
3121 MT2063_WriteSub(pInfo->hUserData,
3126 if (status == MT2063_OK) {
3127 /* cache the bytes just written. */
3128 pInfo->reg[MT2063_REG_LO2CQ_1] =
3130 pInfo->reg[MT2063_REG_LO2CQ_2] =
3132 pInfo->reg[MT2063_REG_LO2CQ_3] =
3138 /* Calculate the Divider and Numberator components of LO1 */
3140 MT2063_CalcLO1Mult(&Div, &FracN, nValue,
3141 pInfo->AS_Data.f_ref /
3143 pInfo->AS_Data.f_ref);
3144 pInfo->reg[MT2063_REG_LO1CQ_1] =
3145 (u8) (Div & 0x00FF);
3146 pInfo->reg[MT2063_REG_LO1CQ_2] =
3149 MT2063_WriteSub(pInfo->hUserData,
3153 reg[MT2063_REG_LO1CQ_1], 2);
3155 /* set the one-shot bit to load the pair of LO values */
3156 tmpOneShot = tempLO2CQ[2] | 0xE0;
3158 MT2063_WriteSub(pInfo->hUserData,
3163 /* only restore the queue values if they were different from the actual. */
3165 /* put actual LO2 value into queue (0 in one-shot bits) */
3167 MT2063_WriteSub(pInfo->hUserData,
3170 &(tempLO2CQ[0]), 3);
3172 /* cache the bytes just written. */
3173 pInfo->reg[MT2063_REG_LO2CQ_1] =
3175 pInfo->reg[MT2063_REG_LO2CQ_2] =
3177 pInfo->reg[MT2063_REG_LO2CQ_3] =
3181 MT2063_GetParam(pInfo->hUserData,
3183 &pInfo->AS_Data.f_LO1);
3187 /* LO1 minimum step size */
3188 case MT2063_LO1_STEPSIZE:
3189 pInfo->AS_Data.f_LO1_Step = nValue;
3192 /* LO1 FracN keep-out region */
3193 case MT2063_LO1_FRACN_AVOID_PARAM:
3194 pInfo->AS_Data.f_LO1_FracN_Avoid = nValue;
3197 /* Requested 1st IF */
3198 case MT2063_IF1_REQUEST:
3199 pInfo->AS_Data.f_if1_Request = nValue;
3202 /* zero-IF bandwidth */
3204 pInfo->AS_Data.f_zif_bw = nValue;
3208 case MT2063_LO2_FREQ:
3210 /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */
3211 /* Capture the Divider and Numerator portions of other LO */
3219 /* Buffer the queue for restoration later and get actual LO2 values. */
3221 MT2063_ReadSub(pInfo->hUserData,
3224 &(tempLO1CQ[0]), 2);
3226 MT2063_ReadSub(pInfo->hUserData,
3231 /* only write the queue values if they are different from the actual. */
3232 if ((tempLO1CQ[0] != tempLO1C[0])
3233 || (tempLO1CQ[1] != tempLO1C[1])) {
3234 /* put actual LO1 value into queue */
3236 MT2063_WriteSub(pInfo->hUserData,
3241 /* cache the bytes just written. */
3242 pInfo->reg[MT2063_REG_LO1CQ_1] =
3244 pInfo->reg[MT2063_REG_LO1CQ_2] =
3249 /* Calculate the Divider and Numberator components of LO2 */
3251 MT2063_CalcLO2Mult(&Div2, &FracN2, nValue,
3252 pInfo->AS_Data.f_ref /
3254 pInfo->AS_Data.f_ref);
3255 pInfo->reg[MT2063_REG_LO2CQ_1] =
3257 ((FracN2 >> 12) & 0x01)) & 0xFF;
3258 pInfo->reg[MT2063_REG_LO2CQ_2] =
3259 (u8) ((FracN2 >> 4) & 0xFF);
3260 pInfo->reg[MT2063_REG_LO2CQ_3] =
3261 (u8) ((FracN2 & 0x0F));
3263 MT2063_WriteSub(pInfo->hUserData,
3267 reg[MT2063_REG_LO1CQ_1], 3);
3269 /* set the one-shot bit to load the LO values */
3271 pInfo->reg[MT2063_REG_LO2CQ_3] | 0xE0;
3273 MT2063_WriteSub(pInfo->hUserData,
3278 /* only restore LO1 queue value if they were different from the actual. */
3280 /* put previous LO1 queue value back into queue */
3282 MT2063_WriteSub(pInfo->hUserData,
3285 &(tempLO1CQ[0]), 2);
3287 /* cache the bytes just written. */
3288 pInfo->reg[MT2063_REG_LO1CQ_1] =
3290 pInfo->reg[MT2063_REG_LO1CQ_2] =
3294 MT2063_GetParam(pInfo->hUserData,
3296 &pInfo->AS_Data.f_LO2);
3300 /* LO2 minimum step size */
3301 case MT2063_LO2_STEPSIZE:
3302 pInfo->AS_Data.f_LO2_Step = nValue;
3305 /* LO2 FracN keep-out region */
3306 case MT2063_LO2_FRACN_AVOID:
3307 pInfo->AS_Data.f_LO2_FracN_Avoid = nValue;
3310 /* output center frequency */
3311 case MT2063_OUTPUT_FREQ:
3312 pInfo->AS_Data.f_out = nValue;
3315 /* output bandwidth */
3316 case MT2063_OUTPUT_BW:
3317 pInfo->AS_Data.f_out_bw = nValue + 750000;
3320 /* min inter-tuner LO separation */
3321 case MT2063_LO_SEPARATION:
3322 pInfo->AS_Data.f_min_LO_Separation = nValue;
3325 /* max # of intra-tuner harmonics */
3326 case MT2063_MAX_HARM1:
3327 pInfo->AS_Data.maxH1 = nValue;
3330 /* max # of inter-tuner harmonics */
3331 case MT2063_MAX_HARM2:
3332 pInfo->AS_Data.maxH2 = nValue;
3335 case MT2063_RCVR_MODE:
3337 MT2063_SetReceiverMode(pInfo,
3338 (enum MT2063_RCVR_MODES)
3342 /* Set LNA Rin -- nValue is desired value */
3343 case MT2063_LNA_RIN:
3346 reg[MT2063_REG_CTRL_2C] & (u8) ~ 0x03) |
3348 if (pInfo->reg[MT2063_REG_CTRL_2C] != val) {
3350 MT2063_SetReg(pInfo, MT2063_REG_CTRL_2C,
3355 /* Set target power level at LNA -- nValue is desired value */
3356 case MT2063_LNA_TGT:
3359 reg[MT2063_REG_LNA_TGT] & (u8) ~ 0x3F) |
3361 if (pInfo->reg[MT2063_REG_LNA_TGT] != val) {
3363 MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT,
3368 /* Set target power level at PD1 -- nValue is desired value */
3369 case MT2063_PD1_TGT:
3372 reg[MT2063_REG_PD1_TGT] & (u8) ~ 0x3F) |
3374 if (pInfo->reg[MT2063_REG_PD1_TGT] != val) {
3376 MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT,
3381 /* Set target power level at PD2 -- nValue is desired value */
3382 case MT2063_PD2_TGT:
3385 reg[MT2063_REG_PD2_TGT] & (u8) ~ 0x3F) |
3387 if (pInfo->reg[MT2063_REG_PD2_TGT] != val) {
3389 MT2063_SetReg(pInfo, MT2063_REG_PD2_TGT,
3394 /* Set LNA atten limit -- nValue is desired value */
3395 case MT2063_ACLNA_MAX:
3398 reg[MT2063_REG_LNA_OV] & (u8) ~ 0x1F) | (nValue
3401 if (pInfo->reg[MT2063_REG_LNA_OV] != val) {
3403 MT2063_SetReg(pInfo, MT2063_REG_LNA_OV,
3408 /* Set RF atten limit -- nValue is desired value */
3409 case MT2063_ACRF_MAX:
3412 reg[MT2063_REG_RF_OV] & (u8) ~ 0x1F) | (nValue
3415 if (pInfo->reg[MT2063_REG_RF_OV] != val) {
3417 MT2063_SetReg(pInfo, MT2063_REG_RF_OV, val);
3421 /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */
3422 case MT2063_ACFIF_MAX:
3423 if (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3
3428 reg[MT2063_REG_FIF_OV] & (u8) ~ 0x1F) | (nValue
3431 if (pInfo->reg[MT2063_REG_FIF_OV] != val) {
3433 MT2063_SetReg(pInfo, MT2063_REG_FIF_OV,
3438 case MT2063_DNC_OUTPUT_ENABLE:
3439 /* selects, which DNC output is used */
3440 switch ((enum MT2063_DNC_Output_Enable)nValue) {
3441 case MT2063_DNC_NONE:
3443 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3444 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3448 MT2063_REG_DNC_GAIN,
3451 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3452 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3456 MT2063_REG_VGA_GAIN,
3459 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3460 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3471 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3472 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3476 MT2063_REG_DNC_GAIN,
3479 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03; /* Set DNC2GC=3 */
3480 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3484 MT2063_REG_VGA_GAIN,
3487 val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */
3488 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3499 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03; /* Set DNC1GC=3 */
3500 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3504 MT2063_REG_DNC_GAIN,
3507 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3508 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3512 MT2063_REG_VGA_GAIN,
3515 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3516 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3525 case MT2063_DNC_BOTH:
3527 val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */
3528 if (pInfo->reg[MT2063_REG_DNC_GAIN] !=
3532 MT2063_REG_DNC_GAIN,
3535 val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */
3536 if (pInfo->reg[MT2063_REG_VGA_GAIN] !=
3540 MT2063_REG_VGA_GAIN,
3543 val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */
3544 if (pInfo->reg[MT2063_REG_RSVD_20] !=
3559 /* Set VGA gain code */
3562 reg[MT2063_REG_VGA_GAIN] & (u8) ~ 0x0C) |
3563 ((nValue & 0x03) << 2);
3564 if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) {
3566 MT2063_SetReg(pInfo, MT2063_REG_VGA_GAIN,
3572 /* Set VGA bias current */
3575 reg[MT2063_REG_RSVD_31] & (u8) ~ 0x07) |
3577 if (pInfo->reg[MT2063_REG_RSVD_31] != val) {
3579 MT2063_SetReg(pInfo, MT2063_REG_RSVD_31,
3588 reg[MT2063_REG_RSVD_1E] & (u8) ~ 0x03) |
3590 if (pInfo->reg[MT2063_REG_RSVD_1E] != val) {
3592 MT2063_SetReg(pInfo, MT2063_REG_RSVD_1E,
3598 /* Set Amp gain code */
3601 reg[MT2063_REG_TEMP_SEL] & (u8) ~ 0x03) |
3603 if (pInfo->reg[MT2063_REG_TEMP_SEL] != val) {
3605 MT2063_SetReg(pInfo, MT2063_REG_TEMP_SEL,
3610 /* Avoid DECT Frequencies */
3611 case MT2063_AVOID_DECT:
3613 enum MT2063_DECT_Avoid_Type newAvoidSetting =
3614 (enum MT2063_DECT_Avoid_Type)nValue;
3615 if ((newAvoidSetting >=
3616 MT2063_NO_DECT_AVOIDANCE)
3617 && (newAvoidSetting <= MT2063_AVOID_BOTH)) {
3618 pInfo->AS_Data.avoidDECT =
3624 /* Cleartune filter selection: 0 - by IC (default), 1 - by software */
3625 case MT2063_CTFILT_SW:
3626 pInfo->ctfilt_sw = (nValue & 0x01);
3629 /* These parameters are read-only */
3630 case MT2063_IC_ADDR:
3631 case MT2063_MAX_OPEN:
3632 case MT2063_NUM_OPEN:
3633 case MT2063_INPUT_FREQ:
3634 case MT2063_IF1_ACTUAL:
3635 case MT2063_IF1_CENTER:
3638 case MT2063_EXCL_ZONES:
3639 case MT2063_SPUR_AVOIDED:
3640 case MT2063_NUM_SPURS:
3641 case MT2063_SPUR_PRESENT:
3647 status |= MT2063_ARG_RANGE;
3653 /****************************************************************************
3655 ** Name: MT2063_SetPowerMaskBits
3657 ** Description: Sets the power-down mask bits for various sections of
3660 ** Parameters: h - Tuner handle (returned by MT2063_Open)
3661 ** Bits - Mask bits to be set.
3663 ** See definition of MT2063_Mask_Bits type for description
3664 ** of each of the power bits.
3667 ** MT_OK - No errors
3668 ** MT_INV_HANDLE - Invalid tuner handle
3669 ** MT_COMM_ERR - Serial bus communications error
3671 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3673 ** Revision History:
3675 ** SCR Date Author Description
3676 ** -------------------------------------------------------------------------
3677 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3679 ****************************************************************************/
3680 u32 MT2063_SetPowerMaskBits(void *h, enum MT2063_Mask_Bits Bits)
3682 u32 status = MT2063_OK; /* Status to be returned */
3683 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3685 /* Verify that the handle passed points to a valid tuner */
3686 if (MT2063_IsValidHandle(pInfo) == 0)
3687 status = MT2063_INV_HANDLE;
3689 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3690 if ((Bits & 0xFF00) != 0) {
3691 pInfo->reg[MT2063_REG_PWR_2] |=
3692 (u8) ((Bits & 0xFF00) >> 8);
3694 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3696 &pInfo->reg[MT2063_REG_PWR_2], 1);
3698 if ((Bits & 0xFF) != 0) {
3699 pInfo->reg[MT2063_REG_PWR_1] |= ((u8) Bits & 0xFF);
3701 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3703 &pInfo->reg[MT2063_REG_PWR_1], 1);
3710 /****************************************************************************
3712 ** Name: MT2063_ClearPowerMaskBits
3714 ** Description: Clears the power-down mask bits for various sections of
3717 ** Parameters: h - Tuner handle (returned by MT2063_Open)
3718 ** Bits - Mask bits to be cleared.
3720 ** See definition of MT2063_Mask_Bits type for description
3721 ** of each of the power bits.
3724 ** MT_OK - No errors
3725 ** MT_INV_HANDLE - Invalid tuner handle
3726 ** MT_COMM_ERR - Serial bus communications error
3728 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3730 ** Revision History:
3732 ** SCR Date Author Description
3733 ** -------------------------------------------------------------------------
3734 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3736 ****************************************************************************/
3737 u32 MT2063_ClearPowerMaskBits(void *h, enum MT2063_Mask_Bits Bits)
3739 u32 status = MT2063_OK; /* Status to be returned */
3740 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3742 /* Verify that the handle passed points to a valid tuner */
3743 if (MT2063_IsValidHandle(pInfo) == 0)
3744 status = MT2063_INV_HANDLE;
3746 Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3747 if ((Bits & 0xFF00) != 0) {
3748 pInfo->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
3750 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3752 &pInfo->reg[MT2063_REG_PWR_2], 1);
3754 if ((Bits & 0xFF) != 0) {
3755 pInfo->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
3757 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3759 &pInfo->reg[MT2063_REG_PWR_1], 1);
3766 /****************************************************************************
3768 ** Name: MT2063_GetPowerMaskBits
3770 ** Description: Returns a mask of the enabled power shutdown bits
3772 ** Parameters: h - Tuner handle (returned by MT2063_Open)
3773 ** Bits - Mask bits to currently set.
3775 ** See definition of MT2063_Mask_Bits type for description
3776 ** of each of the power bits.
3779 ** MT_OK - No errors
3780 ** MT_INV_HANDLE - Invalid tuner handle
3781 ** MT_ARG_NULL - Output argument is NULL
3782 ** MT_COMM_ERR - Serial bus communications error
3784 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3786 ** Revision History:
3788 ** SCR Date Author Description
3789 ** -------------------------------------------------------------------------
3790 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3792 ****************************************************************************/
3793 u32 MT2063_GetPowerMaskBits(void *h, enum MT2063_Mask_Bits * Bits)
3795 u32 status = MT2063_OK; /* Status to be returned */
3796 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3798 /* Verify that the handle passed points to a valid tuner */
3799 if (MT2063_IsValidHandle(pInfo) == 0)
3800 status = MT2063_INV_HANDLE;
3803 status |= MT2063_ARG_NULL;
3805 if (MT2063_NO_ERROR(status))
3807 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
3809 &pInfo->reg[MT2063_REG_PWR_1], 2);
3811 if (MT2063_NO_ERROR(status)) {
3814 MT2063_Mask_Bits)(((s32) pInfo->
3815 reg[MT2063_REG_PWR_2] << 8) +
3816 pInfo->reg[MT2063_REG_PWR_1]);
3817 *Bits = (enum MT2063_Mask_Bits)(*Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */
3824 /****************************************************************************
3826 ** Name: MT2063_EnableExternalShutdown
3828 ** Description: Enables or disables the operation of the external
3831 ** Parameters: h - Tuner handle (returned by MT2063_Open)
3832 ** Enabled - 0 = disable the pin, otherwise enable it
3835 ** MT_OK - No errors
3836 ** MT_INV_HANDLE - Invalid tuner handle
3837 ** MT_COMM_ERR - Serial bus communications error
3839 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3841 ** Revision History:
3843 ** SCR Date Author Description
3844 ** -------------------------------------------------------------------------
3845 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3847 ****************************************************************************/
3848 u32 MT2063_EnableExternalShutdown(void *h, u8 Enabled)
3850 u32 status = MT2063_OK; /* Status to be returned */
3851 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3853 /* Verify that the handle passed points to a valid tuner */
3854 if (MT2063_IsValidHandle(pInfo) == 0)
3855 status = MT2063_INV_HANDLE;
3858 pInfo->reg[MT2063_REG_PWR_1] &= ~0x08; /* Turn off the bit */
3860 pInfo->reg[MT2063_REG_PWR_1] |= 0x08; /* Turn the bit on */
3863 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3865 &pInfo->reg[MT2063_REG_PWR_1], 1);
3871 /****************************************************************************
3873 ** Name: MT2063_SoftwareShutdown
3875 ** Description: Enables or disables software shutdown function. When
3876 ** Shutdown==1, any section whose power mask is set will be
3879 ** Parameters: h - Tuner handle (returned by MT2063_Open)
3880 ** Shutdown - 1 = shutdown the masked sections, otherwise
3881 ** power all sections on
3884 ** MT_OK - No errors
3885 ** MT_INV_HANDLE - Invalid tuner handle
3886 ** MT_COMM_ERR - Serial bus communications error
3888 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3890 ** Revision History:
3892 ** SCR Date Author Description
3893 ** -------------------------------------------------------------------------
3894 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3895 ** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for
3896 ** correct wakeup of the LNA
3898 ****************************************************************************/
3899 u32 MT2063_SoftwareShutdown(void *h, u8 Shutdown)
3901 u32 status = MT2063_OK; /* Status to be returned */
3902 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3904 /* Verify that the handle passed points to a valid tuner */
3905 if (MT2063_IsValidHandle(pInfo) == 0) {
3906 status = MT2063_INV_HANDLE;
3909 pInfo->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */
3911 pInfo->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */
3914 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3916 &pInfo->reg[MT2063_REG_PWR_1], 1);
3918 if (Shutdown != 1) {
3919 pInfo->reg[MT2063_REG_BYP_CTRL] =
3920 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
3922 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3923 MT2063_REG_BYP_CTRL,
3924 &pInfo->reg[MT2063_REG_BYP_CTRL],
3926 pInfo->reg[MT2063_REG_BYP_CTRL] =
3927 (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F);
3929 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3930 MT2063_REG_BYP_CTRL,
3931 &pInfo->reg[MT2063_REG_BYP_CTRL],
3939 /****************************************************************************
3941 ** Name: MT2063_SetExtSRO
3943 ** Description: Sets the external SRO driver.
3945 ** Parameters: h - Tuner handle (returned by MT2063_Open)
3946 ** Ext_SRO_Setting - external SRO drive setting
3948 ** (default) MT2063_EXT_SRO_OFF - ext driver off
3949 ** MT2063_EXT_SRO_BY_1 - ext driver = SRO frequency
3950 ** MT2063_EXT_SRO_BY_2 - ext driver = SRO/2 frequency
3951 ** MT2063_EXT_SRO_BY_4 - ext driver = SRO/4 frequency
3954 ** MT_OK - No errors
3955 ** MT_COMM_ERR - Serial bus communications error
3956 ** MT_INV_HANDLE - Invalid tuner handle
3958 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
3960 ** The Ext_SRO_Setting settings default to OFF
3961 ** Use this function if you need to override the default
3963 ** Revision History:
3965 ** SCR Date Author Description
3966 ** -------------------------------------------------------------------------
3967 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
3968 ** 189 S 05-13-2008 RSK Ver 1.16: Correct location for ExtSRO control.
3970 ****************************************************************************/
3971 u32 MT2063_SetExtSRO(void *h, enum MT2063_Ext_SRO Ext_SRO_Setting)
3973 u32 status = MT2063_OK; /* Status to be returned */
3974 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
3976 /* Verify that the handle passed points to a valid tuner */
3977 if (MT2063_IsValidHandle(pInfo) == 0)
3978 status = MT2063_INV_HANDLE;
3980 pInfo->reg[MT2063_REG_CTRL_2C] =
3982 reg[MT2063_REG_CTRL_2C] & 0x3F) | ((u8) Ext_SRO_Setting
3985 MT2063_WriteSub(pInfo->hUserData, pInfo->address,
3987 &pInfo->reg[MT2063_REG_CTRL_2C], 1);
3993 /****************************************************************************
3995 ** Name: MT2063_SetReg
3997 ** Description: Sets an MT2063 register.
3999 ** Parameters: h - Tuner handle (returned by MT2063_Open)
4000 ** reg - MT2063 register/subaddress location
4001 ** val - MT2063 register/subaddress value
4004 ** MT_OK - No errors
4005 ** MT_COMM_ERR - Serial bus communications error
4006 ** MT_INV_HANDLE - Invalid tuner handle
4007 ** MT_ARG_RANGE - Argument out of range
4009 ** Dependencies: USERS MUST CALL MT2063_Open() FIRST!
4011 ** Use this function if you need to override a default
4014 ** Revision History:
4016 ** SCR Date Author Description
4017 ** -------------------------------------------------------------------------
4018 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4020 ****************************************************************************/
4021 u32 MT2063_SetReg(void *h, u8 reg, u8 val)
4023 u32 status = MT2063_OK; /* Status to be returned */
4024 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4026 /* Verify that the handle passed points to a valid tuner */
4027 if (MT2063_IsValidHandle(pInfo) == 0)
4028 status |= MT2063_INV_HANDLE;
4030 if (reg >= MT2063_REG_END_REGS)
4031 status |= MT2063_ARG_RANGE;
4033 if (MT2063_NO_ERROR(status)) {
4035 MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val,
4037 if (MT2063_NO_ERROR(status))
4038 pInfo->reg[reg] = val;
4044 static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
4046 return f_ref * (f_LO / f_ref)
4047 + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
4050 /****************************************************************************
4052 ** Name: fLO_FractionalTerm
4054 ** Description: Calculates the portion contributed by FracN / denom.
4056 ** This function preserves maximum precision without
4057 ** risk of overflow. It accurately calculates
4058 ** f_ref * num / denom to within 1 HZ with fixed math.
4060 ** Parameters: num - Fractional portion of the multiplier
4061 ** denom - denominator portion of the ratio
4062 ** This routine successfully handles denom values
4063 ** up to and including 2^18.
4064 ** f_Ref - SRO frequency. This calculation handles
4065 ** f_ref as two separate 14-bit fields.
4066 ** Therefore, a maximum value of 2^28-1
4067 ** may safely be used for f_ref. This is
4068 ** the genesis of the magic number "14" and the
4069 ** magic mask value of 0x03FFF.
4071 ** Returns: f_ref * num / denom
4073 ** Revision History:
4075 ** SCR Date Author Description
4076 ** -------------------------------------------------------------------------
4077 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4079 ****************************************************************************/
4080 static u32 MT2063_fLO_FractionalTerm(u32 f_ref,
4083 u32 t1 = (f_ref >> 14) * num;
4084 u32 term1 = t1 / denom;
4085 u32 loss = t1 % denom;
4087 (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
4088 return ((term1 << 14) + term2);
4091 /****************************************************************************
4093 ** Name: CalcLO1Mult
4095 ** Description: Calculates Integer divider value and the numerator
4096 ** value for a FracN PLL.
4098 ** This function assumes that the f_LO and f_Ref are
4099 ** evenly divisible by f_LO_Step.
4101 ** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4102 ** FracN - OUTPUT: Fractional portion of the multiplier
4103 ** f_LO - desired LO frequency.
4104 ** f_LO_Step - Minimum step size for the LO (in Hz).
4105 ** f_Ref - SRO frequency.
4106 ** f_Avoid - Range of PLL frequencies to avoid near
4107 ** integer multiples of f_Ref (in Hz).
4109 ** Returns: Recalculated LO frequency.
4111 ** Revision History:
4113 ** SCR Date Author Description
4114 ** -------------------------------------------------------------------------
4115 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4117 ****************************************************************************/
4118 static u32 MT2063_CalcLO1Mult(u32 * Div,
4121 u32 f_LO_Step, u32 f_Ref)
4123 /* Calculate the whole number portion of the divider */
4124 *Div = f_LO / f_Ref;
4126 /* Calculate the numerator value (round to nearest f_LO_Step) */
4128 (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4129 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4131 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
4134 /****************************************************************************
4136 ** Name: CalcLO2Mult
4138 ** Description: Calculates Integer divider value and the numerator
4139 ** value for a FracN PLL.
4141 ** This function assumes that the f_LO and f_Ref are
4142 ** evenly divisible by f_LO_Step.
4144 ** Parameters: Div - OUTPUT: Whole number portion of the multiplier
4145 ** FracN - OUTPUT: Fractional portion of the multiplier
4146 ** f_LO - desired LO frequency.
4147 ** f_LO_Step - Minimum step size for the LO (in Hz).
4148 ** f_Ref - SRO frequency.
4149 ** f_Avoid - Range of PLL frequencies to avoid near
4150 ** integer multiples of f_Ref (in Hz).
4152 ** Returns: Recalculated LO frequency.
4154 ** Revision History:
4156 ** SCR Date Author Description
4157 ** -------------------------------------------------------------------------
4158 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4160 ****************************************************************************/
4161 static u32 MT2063_CalcLO2Mult(u32 * Div,
4164 u32 f_LO_Step, u32 f_Ref)
4166 /* Calculate the whole number portion of the divider */
4167 *Div = f_LO / f_Ref;
4169 /* Calculate the numerator value (round to nearest f_LO_Step) */
4171 (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
4172 (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
4174 return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
4178 /****************************************************************************
4180 ** Name: FindClearTuneFilter
4182 ** Description: Calculate the corrrect ClearTune filter to be used for
4183 ** a given input frequency.
4185 ** Parameters: pInfo - ptr to tuner data structure
4186 ** f_in - RF input center frequency (in Hz).
4188 ** Returns: ClearTune filter number (0-31)
4190 ** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter!
4192 ** Revision History:
4194 ** SCR Date Author Description
4195 ** -------------------------------------------------------------------------
4196 ** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune
4197 ** cross-over frequency values.
4199 ****************************************************************************/
4200 static u32 FindClearTuneFilter(struct MT2063_Info_t *pInfo, u32 f_in)
4203 u32 idx; /* index loop */
4206 ** Find RF Band setting
4208 RFBand = 31; /* def when f_in > all */
4209 for (idx = 0; idx < 31; ++idx) {
4210 if (pInfo->CTFiltMax[idx] >= f_in) {
4218 /****************************************************************************
4220 ** Name: MT2063_Tune
4222 ** Description: Change the tuner's tuned frequency to RFin.
4224 ** Parameters: h - Open handle to the tuner (from MT2063_Open).
4225 ** f_in - RF input center frequency (in Hz).
4228 ** MT_OK - No errors
4229 ** MT_INV_HANDLE - Invalid tuner handle
4230 ** MT_UPC_UNLOCK - Upconverter PLL unlocked
4231 ** MT_DNC_UNLOCK - Downconverter PLL unlocked
4232 ** MT_COMM_ERR - Serial bus communications error
4233 ** MT_SPUR_CNT_MASK - Count of avoided LO spurs
4234 ** MT_SPUR_PRESENT - LO spur possible in output
4235 ** MT_FIN_RANGE - Input freq out of range
4236 ** MT_FOUT_RANGE - Output freq out of range
4237 ** MT_UPC_RANGE - Upconverter freq out of range
4238 ** MT_DNC_RANGE - Downconverter freq out of range
4240 ** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune!
4242 ** MT_ReadSub - Read data from the two-wire serial bus
4243 ** MT_WriteSub - Write data to the two-wire serial bus
4244 ** MT_Sleep - Delay execution for x milliseconds
4245 ** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked
4247 ** Revision History:
4249 ** SCR Date Author Description
4250 ** -------------------------------------------------------------------------
4251 ** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b.
4252 ** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune
4253 ** cross-over frequency values.
4254 ** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs.
4255 ** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid.
4256 ** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW
4258 ****************************************************************************/
4259 u32 MT2063_Tune(void *h, u32 f_in)
4260 { /* RF input center frequency */
4261 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4263 u32 status = MT2063_OK; /* status of operation */
4264 u32 LO1; /* 1st LO register value */
4265 u32 Num1; /* Numerator for LO1 reg. value */
4266 u32 f_IF1; /* 1st IF requested */
4267 u32 LO2; /* 2nd LO register value */
4268 u32 Num2; /* Numerator for LO2 reg. value */
4269 u32 ofLO1, ofLO2; /* last time's LO frequencies */
4270 u32 ofin, ofout; /* last time's I/O frequencies */
4271 u8 fiffc = 0x80; /* FIFF center freq from tuner */
4272 u32 fiffof; /* Offset from FIFF center freq */
4273 const u8 LO1LK = 0x80; /* Mask for LO1 Lock bit */
4274 u8 LO2LK = 0x08; /* Mask for LO2 Lock bit */
4278 /* Verify that the handle passed points to a valid tuner */
4279 if (MT2063_IsValidHandle(pInfo) == 0)
4280 return MT2063_INV_HANDLE;
4282 /* Check the input and output frequency ranges */
4283 if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
4284 status |= MT2063_FIN_RANGE;
4286 if ((pInfo->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
4287 || (pInfo->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
4288 status |= MT2063_FOUT_RANGE;
4291 ** Save original LO1 and LO2 register values
4293 ofLO1 = pInfo->AS_Data.f_LO1;
4294 ofLO2 = pInfo->AS_Data.f_LO2;
4295 ofin = pInfo->AS_Data.f_in;
4296 ofout = pInfo->AS_Data.f_out;
4299 ** Find and set RF Band setting
4301 if (pInfo->ctfilt_sw == 1) {
4302 val = (pInfo->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
4303 if (pInfo->reg[MT2063_REG_CTUNE_CTRL] != val) {
4305 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_CTRL, val);
4307 val = pInfo->reg[MT2063_REG_CTUNE_OV];
4308 RFBand = FindClearTuneFilter(pInfo, f_in);
4309 pInfo->reg[MT2063_REG_CTUNE_OV] =
4310 (u8) ((pInfo->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
4312 if (pInfo->reg[MT2063_REG_CTUNE_OV] != val) {
4314 MT2063_SetReg(pInfo, MT2063_REG_CTUNE_OV, val);
4319 ** Read the FIFF Center Frequency from the tuner
4321 if (MT2063_NO_ERROR(status)) {
4323 MT2063_ReadSub(pInfo->hUserData, pInfo->address,
4325 &pInfo->reg[MT2063_REG_FIFFC], 1);
4326 fiffc = pInfo->reg[MT2063_REG_FIFFC];
4329 ** Assign in the requested values
4331 pInfo->AS_Data.f_in = f_in;
4332 /* Request a 1st IF such that LO1 is on a step size */
4333 pInfo->AS_Data.f_if1_Request =
4334 MT2063_Round_fLO(pInfo->AS_Data.f_if1_Request + f_in,
4335 pInfo->AS_Data.f_LO1_Step,
4336 pInfo->AS_Data.f_ref) - f_in;
4339 ** Calculate frequency settings. f_IF1_FREQ + f_in is the
4340 ** desired LO1 frequency
4342 MT2063_ResetExclZones(&pInfo->AS_Data);
4344 f_IF1 = MT2063_ChooseFirstIF(&pInfo->AS_Data);
4346 pInfo->AS_Data.f_LO1 =
4347 MT2063_Round_fLO(f_IF1 + f_in, pInfo->AS_Data.f_LO1_Step,
4348 pInfo->AS_Data.f_ref);
4350 pInfo->AS_Data.f_LO2 =
4351 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4352 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4355 ** Check for any LO spurs in the output bandwidth and adjust
4356 ** the LO settings to avoid them if needed
4358 status |= MT2063_AvoidSpurs(h, &pInfo->AS_Data);
4360 ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
4361 ** Recalculate the LO frequencies and the values to be placed
4362 ** in the tuning registers.
4364 pInfo->AS_Data.f_LO1 =
4365 MT2063_CalcLO1Mult(&LO1, &Num1, pInfo->AS_Data.f_LO1,
4366 pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref);
4367 pInfo->AS_Data.f_LO2 =
4368 MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in,
4369 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4370 pInfo->AS_Data.f_LO2 =
4371 MT2063_CalcLO2Mult(&LO2, &Num2, pInfo->AS_Data.f_LO2,
4372 pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref);
4375 ** Check the upconverter and downconverter frequency ranges
4377 if ((pInfo->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
4378 || (pInfo->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
4379 status |= MT2063_UPC_RANGE;
4380 if ((pInfo->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
4381 || (pInfo->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
4382 status |= MT2063_DNC_RANGE;
4383 /* LO2 Lock bit was in a different place for B0 version */
4384 if (pInfo->tuner_id == MT2063_B0)
4388 ** If we have the same LO frequencies and we're already locked,
4389 ** then skip re-programming the LO registers.
4391 if ((ofLO1 != pInfo->AS_Data.f_LO1)
4392 || (ofLO2 != pInfo->AS_Data.f_LO2)
4393 || ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
4396 ** Calculate the FIFFOF register value
4399 ** FIFFOF = ------------ - 8 * FIFFC - 4992
4403 (pInfo->AS_Data.f_LO1 -
4404 f_in) / (pInfo->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
4410 ** Place all of the calculated values into the local tuner
4413 if (MT2063_NO_ERROR(status)) {
4414 pInfo->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF); /* DIV1q */
4415 pInfo->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F); /* NUM1q */
4416 pInfo->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1) /* DIV2q */
4417 |(Num2 >> 12)); /* NUM2q (hi) */
4418 pInfo->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */
4419 pInfo->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */
4422 ** Now write out the computed register values
4423 ** IMPORTANT: There is a required order for writing
4424 ** (0x05 must follow all the others).
4426 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */
4427 if (pInfo->tuner_id == MT2063_B0) {
4428 /* Re-write the one-shot bits to trigger the tune operation */
4429 status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &pInfo->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */
4431 /* Write out the FIFF offset only if it's changing */
4432 if (pInfo->reg[MT2063_REG_FIFF_OFFSET] !=
4434 pInfo->reg[MT2063_REG_FIFF_OFFSET] =
4437 MT2063_WriteSub(pInfo->hUserData,
4439 MT2063_REG_FIFF_OFFSET,
4441 reg[MT2063_REG_FIFF_OFFSET],
4447 ** Check for LO's locking
4450 if (MT2063_NO_ERROR(status)) {
4451 status |= MT2063_GetLocked(h);
4454 ** If we locked OK, assign calculated data to MT2063_Info_t structure
4456 if (MT2063_NO_ERROR(status)) {
4457 pInfo->f_IF1_actual = pInfo->AS_Data.f_LO1 - f_in;
4464 u32 MT_Tune_atv(void *h, u32 f_in, u32 bw_in,
4465 enum MTTune_atv_standard tv_type)
4468 u32 status = MT2063_OK;
4469 struct MT2063_Info_t *pInfo = (struct MT2063_Info_t *)h;
4470 struct dvb_frontend *fe = (struct dvb_frontend *)pInfo->hUserData;
4471 struct mt2063_state *state = fe->tuner_priv;
4474 s32 pict2chanb_vsb = 0;
4475 s32 pict2chanb_snd = 0;
4485 case MTTUNEA_PAL_B:{
4486 pict_car = 38900000;
4488 pict2chanb_vsb = -1250000;
4489 pict2snd1 = 5500000;
4490 pict2snd2 = 5742000;
4494 case MTTUNEA_PAL_G:{
4495 pict_car = 38900000;
4497 pict2chanb_vsb = -1250000;
4498 pict2snd1 = 5500000;
4503 case MTTUNEA_PAL_I:{
4504 pict_car = 38900000;
4506 pict2chanb_vsb = -1250000;
4507 pict2snd1 = 6000000;
4512 case MTTUNEA_PAL_L:{
4513 pict_car = 38900000;
4515 pict2chanb_vsb = -1250000;
4516 pict2snd1 = 6500000;
4521 case MTTUNEA_PAL_MN:{
4522 pict_car = 38900000;
4524 pict2chanb_vsb = -1250000;
4525 pict2snd1 = 4500000;
4530 case MTTUNEA_PAL_DK:{
4531 pict_car = 38900000;
4533 pict2chanb_vsb = -1250000;
4534 pict2snd1 = 6500000;
4539 case MTTUNEA_DIGITAL:{
4540 pict_car = 36125000;
4542 pict2chanb_vsb = -(ch_bw / 2);
4548 case MTTUNEA_FMRADIO:{
4549 pict_car = 38900000;
4551 pict2chanb_vsb = -(ch_bw / 2);
4559 pict_car = 36125000;
4561 pict2chanb_vsb = -(ch_bw / 2);
4564 rcvr_mode = MT2063_CABLE_QAM;
4568 pict_car = 36125000;
4569 ch_bw = bw_in; //8000000
4570 pict2chanb_vsb = -(ch_bw / 2);
4573 rcvr_mode = MT2063_OFFAIR_COFDM;
4576 case MTTUNEA_UNKNOWN:
4582 pict2chanb_snd = pict2chanb_vsb - ch_bw;
4583 if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
4585 status |= MT2063_SetParam(h, MT2063_STEPSIZE, 125000);
4586 status |= MT2063_SetParam(h, MT2063_OUTPUT_FREQ, if_mid);
4587 status |= MT2063_SetParam(h, MT2063_OUTPUT_BW, ch_bw);
4588 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4590 status |= MT2063_SetParam(h, MT2063_RCVR_MODE, rcvr_mode);
4591 status |= MT2063_Tune(h, (f_in + (pict2chanb_vsb + (ch_bw / 2))));
4592 status |= MT2063_GetParam(h, MT2063_RCVR_MODE, &mode_get);
4594 return (u32) status;
4597 static int mt2063_init(struct dvb_frontend *fe)
4599 u32 status = MT2063_ERROR;
4600 struct mt2063_state *state = fe->tuner_priv;
4602 status = MT2063_Open(0xC0, &(state->MT2063_ht), fe);
4603 status |= MT2063_SoftwareShutdown(state->MT2063_ht, 1);
4604 status |= MT2063_ClearPowerMaskBits(state->MT2063_ht, MT2063_ALL_SD);
4606 if (MT2063_OK != status) {
4607 printk("%s %d error status = 0x%x!!\n", __func__, __LINE__,
4615 static int mt2063_sleep(struct dvb_frontend *fe)
4617 /* TODO: power down */
4621 static int mt2063_get_status(struct dvb_frontend *fe, u32 * status)
4625 //get tuner lock status
4630 static int mt2063_get_state(struct dvb_frontend *fe,
4631 enum tuner_param param, struct tuner_state *state)
4633 struct mt2063_state *mt2063State = fe->tuner_priv;
4636 case DVBFE_TUNER_FREQUENCY:
4639 case DVBFE_TUNER_TUNERSTEP:
4641 case DVBFE_TUNER_IFFREQ:
4643 case DVBFE_TUNER_BANDWIDTH:
4646 case DVBFE_TUNER_REFCLOCK:
4649 MT2063_GetLocked((void *) (mt2063State->MT2063_ht));
4655 return (int)state->refclock;
4658 static int mt2063_set_state(struct dvb_frontend *fe,
4659 enum tuner_param param, struct tuner_state *state)
4661 struct mt2063_state *mt2063State = fe->tuner_priv;
4662 u32 status = MT2063_OK;
4665 case DVBFE_TUNER_FREQUENCY:
4669 MT_Tune_atv((void *) (mt2063State->MT2063_ht),
4670 state->frequency, state->bandwidth,
4671 mt2063State->tv_type);
4673 mt2063State->frequency = state->frequency;
4675 case DVBFE_TUNER_TUNERSTEP:
4677 case DVBFE_TUNER_IFFREQ:
4679 case DVBFE_TUNER_BANDWIDTH:
4681 mt2063State->bandwidth = state->bandwidth;
4683 case DVBFE_TUNER_REFCLOCK:
4686 case DVBFE_TUNER_OPEN:
4687 status = MT2063_Open(MT2063_I2C, &(mt2063State->MT2063_ht), fe);
4689 case DVBFE_TUNER_SOFTWARE_SHUTDOWN:
4690 status = MT2063_SoftwareShutdown(mt2063State->MT2063_ht, 1);
4692 case DVBFE_TUNER_CLEAR_POWER_MASKBITS:
4694 MT2063_ClearPowerMaskBits(mt2063State->MT2063_ht,
4704 static int mt2063_release(struct dvb_frontend *fe)
4706 struct mt2063_state *state = fe->tuner_priv;
4708 fe->tuner_priv = NULL;
4714 static struct dvb_tuner_ops mt2063_ops = {
4716 .name = "MT2063 Silicon Tuner",
4717 .frequency_min = 45000000,
4718 .frequency_max = 850000000,
4719 .frequency_step = 0,
4722 .init = mt2063_init,
4723 .sleep = mt2063_sleep,
4724 .get_status = mt2063_get_status,
4725 .get_state = mt2063_get_state,
4726 .set_state = mt2063_set_state,
4727 .release = mt2063_release
4730 struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
4731 struct mt2063_config *config,
4732 struct i2c_adapter *i2c)
4734 struct mt2063_state *state = NULL;
4736 state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
4740 state->config = config;
4742 state->frontend = fe;
4743 state->reference = config->refclock / 1000; /* kHz */
4744 state->MT2063_init = false;
4745 fe->tuner_priv = state;
4746 fe->ops.tuner_ops = mt2063_ops;
4748 printk("%s: Attaching MT2063 \n", __func__);
4756 EXPORT_SYMBOL(mt2063_attach);
4757 MODULE_PARM_DESC(verbose, "Set Verbosity level");
4759 MODULE_AUTHOR("Henry");
4760 MODULE_DESCRIPTION("MT2063 Silicon tuner");
4761 MODULE_LICENSE("GPL");