diff --git a/drivers/media/common/tuners/mt2063.c b/drivers/media/common/tuners/mt2063.c new file mode 100644 index 000000000000..46001916b991 --- /dev/null +++ b/drivers/media/common/tuners/mt2063.c @@ -0,0 +1,4486 @@ + +#include +#include +#include +#include + +#include "drxk_type.h" +#include "mt2063.h" + +/* Version of this module */ +#define MT2063_VERSION 10018 /* Version 01.18 */ + +static unsigned int verbose; +module_param(verbose, int, 0644); + +//i2c operation +static int mt2063_writeregs(struct mt2063_state *state, u8 reg1, + u8 *data, int len) +{ + int ret; + u8 buf[60];/* = { reg1, data };*/ + + struct i2c_msg msg = { + .addr = state->config->tuner_address, + .flags = 0, + .buf = buf, + .len = len + 1 + }; + + msg.buf[0] = reg1; + memcpy(msg.buf + 1, data, len); + + //printk("mt2063_writeregs state->i2c=%p\n", state->i2c); + ret = i2c_transfer(state->i2c, &msg, 1); + + if (ret < 0) + printk("mt2063_writeregs error ret=%d\n", ret); + + return ret; +} + +static int mt2063_read_regs(struct mt2063_state *state, u8 reg1, u8 *b, u8 len) +{ + int ret; + u8 b0[] = { reg1 }; + struct i2c_msg msg[] = { + { + .addr = state->config->tuner_address, + .flags = I2C_M_RD, + .buf = b0, + .len = 1 + }, { + .addr = state->config->tuner_address, + .flags = I2C_M_RD, + .buf = b, + .len = len + } + }; + + //printk("mt2063_read_regs state->i2c=%p\n", state->i2c); + ret = i2c_transfer(state->i2c, msg, 2); + if (ret < 0) + printk("mt2063_readregs error ret=%d\n", ret); + + return ret; +} + + + + +//context of mt2063_userdef.c ====================================== +//################################################################# +//================================================================= +/***************************************************************************** +** +** Name: MT_WriteSub +** +** Description: Write values to device using a two-wire serial bus. +** +** Parameters: hUserData - User-specific I/O parameter that was +** passed to tuner's Open function. +** addr - device serial bus address (value passed +** as parameter to MTxxxx_Open) +** subAddress - serial bus sub-address (Register Address) +** pData - pointer to the Data to be written to the +** device +** cnt - number of bytes/registers to be written +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** user-defined +** +** Notes: This is a callback function that is called from the +** the tuning algorithm. You MUST provide code for this +** function to write data using the tuner's 2-wire serial +** bus. +** +** The hUserData parameter is a user-specific argument. +** If additional arguments are needed for the user's +** serial bus read/write functions, this argument can be +** used to supply the necessary information. +** The hUserData parameter is initialized in the tuner's Open +** function. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** N/A 03-25-2004 DAD Original +** +*****************************************************************************/ +UData_t MT2063_WriteSub(Handle_t hUserData, + UData_t addr, + U8Data subAddress, + U8Data *pData, + UData_t cnt) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct dvb_frontend *fe = hUserData; + struct mt2063_state *state = fe->tuner_priv; + /* + ** ToDo: Add code here to implement a serial-bus write + ** operation to the MTxxxx tuner. If successful, + ** return MT_OK. + */ +/* return status; */ + +//#if !TUNER_CONTROL_BY_DRXK_DRIVER + fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge +//#endif + + if (mt2063_writeregs(state, subAddress,pData, cnt)<0) + { + status = MT2063_ERROR; + } + +//#if !TUNER_CONTROL_BY_DRXK_DRIVER + fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge +//#endif + + return (status); +} + +/***************************************************************************** +** +** Name: MT_ReadSub +** +** Description: Read values from device using a two-wire serial bus. +** +** Parameters: hUserData - User-specific I/O parameter that was +** passed to tuner's Open function. +** addr - device serial bus address (value passed +** as parameter to MTxxxx_Open) +** subAddress - serial bus sub-address (Register Address) +** pData - pointer to the Data to be written to the +** device +** cnt - number of bytes/registers to be written +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** user-defined +** +** Notes: This is a callback function that is called from the +** the tuning algorithm. You MUST provide code for this +** function to read data using the tuner's 2-wire serial +** bus. +** +** The hUserData parameter is a user-specific argument. +** If additional arguments are needed for the user's +** serial bus read/write functions, this argument can be +** used to supply the necessary information. +** The hUserData parameter is initialized in the tuner's Open +** function. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** N/A 03-25-2004 DAD Original +** +*****************************************************************************/ +UData_t MT2063_ReadSub(Handle_t hUserData, + UData_t addr, + U8Data subAddress, + U8Data *pData, + UData_t cnt) +{ + /* + ** ToDo: Add code here to implement a serial-bus read + ** operation to the MTxxxx tuner. If successful, + ** return MT_OK. + */ +/* return status; */ + UData_t status = MT2063_OK; /* Status to be returned */ + struct dvb_frontend *fe = hUserData; + struct mt2063_state *state = fe->tuner_priv; + UData_t i = 0; +//#if !TUNER_CONTROL_BY_DRXK_DRIVER + fe->ops.i2c_gate_ctrl(fe, 1); //I2C bypass drxk3926 close i2c bridge +//#endif + + for (i = 0; i < cnt; i++) + { + if (mt2063_read_regs(state, subAddress+i, pData+i, 1)<0) + { + status = MT2063_ERROR; + break; + } + } + +//#if !TUNER_CONTROL_BY_DRXK_DRIVER + fe->ops.i2c_gate_ctrl(fe, 0); //I2C bypass drxk3926 close i2c bridge +//#endif + + return(status); +} + + +/***************************************************************************** +** +** Name: MT_Sleep +** +** Description: Delay execution for "nMinDelayTime" milliseconds +** +** Parameters: hUserData - User-specific I/O parameter that was +** passed to tuner's Open function. +** nMinDelayTime - Delay time in milliseconds +** +** Returns: None. +** +** Notes: This is a callback function that is called from the +** the tuning algorithm. You MUST provide code that +** blocks execution for the specified period of time. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** N/A 03-25-2004 DAD Original +** +*****************************************************************************/ +void MT2063_Sleep(Handle_t hUserData, + UData_t nMinDelayTime) +{ + /* + ** ToDo: Add code here to implement a OS blocking + ** for a period of "nMinDelayTime" milliseconds. + */ + msleep(nMinDelayTime); +} + + +#if defined(MT2060_CNT) +#if MT2060_CNT > 0 +/***************************************************************************** +** +** Name: MT_TunerGain (MT2060 only) +** +** Description: Measure the relative tuner gain using the demodulator +** +** Parameters: hUserData - User-specific I/O parameter that was +** passed to tuner's Open function. +** pMeas - Tuner gain (1/100 of dB scale). +** ie. 1234 = 12.34 (dB) +** +** Returns: status: +** MT_OK - No errors +** user-defined errors could be set +** +** Notes: This is a callback function that is called from the +** the 1st IF location routine. You MUST provide +** code that measures the relative tuner gain in a dB +** (not linear) scale. The return value is an integer +** value scaled to 1/100 of a dB. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** N/A 06-16-2004 DAD Original +** N/A 11-30-2004 DAD Renamed from MT_DemodInputPower. This name +** better describes what this function does. +** +*****************************************************************************/ +UData_t MT2060_TunerGain(Handle_t hUserData, + SData_t* pMeas) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + + /* + ** ToDo: Add code here to return the gain / power level measured + ** at the input to the demodulator. + */ + + + + return (status); +} +#endif +#endif +//end of mt2063_userdef.c +//================================================================= +//################################################################# +//================================================================= + + +//context of mt2063_spuravoid.c ====================================== +//################################################################# +//================================================================= + +/***************************************************************************** +** +** Name: mt_spuravoid.c +** +** Description: Microtune spur avoidance software module. +** Supports Microtune tuner drivers. +** +** CVS ID: $Id: mt_spuravoid.c,v 1.3 2008/06/26 15:39:52 software Exp $ +** CVS Source: $Source: /export/home/cvsroot/software/tuners/MT2063/mt_spuravoid.c,v $ +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 082 03-25-2005 JWS Original multi-tuner support - requires +** MTxxxx_CNT declarations +** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0. +** 094 04-06-2005 JWS Ver 1.11 Added uceil and ufloor to get rid +** of compiler warnings +** N/A 04-07-2005 DAD Ver 1.13: Merged single- and multi-tuner spur +** avoidance into a single module. +** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range +** (f_min, f_max) < 0, ignore the entry. +** 115 03-23-2007 DAD Fix declaration of spur due to truncation +** errors. +** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from +** tuner DLL. +** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for +** multi-tuners that have +** (delta IF1) > (f_out-f_outbw/2). +** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+) +** Added logic to force f_Center within 1/2 f_Step. +** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2 +** Type casts added to preserve correct sign. +** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT +** frequencies into MT_ResetExclZones(). +** N/A I 06-20-2008 RSK Ver 1.21: New VERSION number for ver checking. +** +*****************************************************************************/ + +#if !defined(MT2063_TUNER_CNT) +#error MT2063_TUNER_CNT is not defined (see mt_userdef.h) +#endif + +#if MT2063_TUNER_CNT == 0 +#error MT2063_TUNER_CNT must be updated in mt_userdef.h +#endif + +/* Version of this module */ +#define MT2063_SPUR_VERSION 10201 /* Version 01.21 */ + + +/* Implement ceiling, floor functions. */ +#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0)) +#define uceil(n, d) ((n)/(d) + ((n)%(d) != 0)) +#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d)) +#define ufloor(n, d) ((n)/(d)) + + +struct MT2063_FIFZone_t +{ + SData_t min_; + SData_t max_; +}; + +#if MT2063_TUNER_CNT > 1 +static struct MT2063_AvoidSpursData_t* TunerList[MT2063_TUNER_CNT]; +static UData_t TunerCount = 0; +#endif + +UData_t MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t* pAS_Info) +{ +#if MT2063_TUNER_CNT == 1 + pAS_Info->nAS_Algorithm = 1; + return MT2063_OK; +#else + UData_t index; + + pAS_Info->nAS_Algorithm = 2; + + /* + ** Check to see if tuner is already registered + */ + for (index = 0; index < TunerCount; index++) + { + if (TunerList[index] == pAS_Info) + { + return MT2063_OK; /* Already here - no problem */ + } + } + + /* + ** Add tuner to list - if there is room. + */ + if (TunerCount < MT2063_TUNER_CNT) + { + TunerList[TunerCount] = pAS_Info; + TunerCount++; + return MT2063_OK; + } + else + return MT2063_TUNER_CNT_ERR; +#endif +} + + +void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t* pAS_Info) +{ +#if MT2063_TUNER_CNT == 1 + pAS_Info; +#else + + UData_t index; + + for (index = 0; index < TunerCount; index++) + { + if (TunerList[index] == pAS_Info) + { + TunerList[index] = TunerList[--TunerCount]; + } + } +#endif +} + + +/* +** Reset all exclusion zones. +** Add zones to protect the PLL FracN regions near zero +** +** N/A I 06-17-2008 RSK Ver 1.19: Refactoring avoidance of DECT +** frequencies into MT_ResetExclZones(). +*/ +void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t* pAS_Info) +{ + UData_t center; +#if MT2063_TUNER_CNT > 1 + UData_t index; + struct MT2063_AvoidSpursData_t* adj; +#endif + + pAS_Info->nZones = 0; /* this clears the used list */ + pAS_Info->usedZones = NULL; /* reset ptr */ + pAS_Info->freeZones = NULL; /* reset ptr */ + + center = pAS_Info->f_ref * ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw/2 + pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in; + while (center < pAS_Info->f_if1_Center + pAS_Info->f_if1_bw/2 + pAS_Info->f_LO1_FracN_Avoid) + { + /* Exclude LO1 FracN */ + MT2063_AddExclZone(pAS_Info, center-pAS_Info->f_LO1_FracN_Avoid, center-1); + MT2063_AddExclZone(pAS_Info, center+1, center+pAS_Info->f_LO1_FracN_Avoid); + center += pAS_Info->f_ref; + } + + center = pAS_Info->f_ref * ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw/2 - pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out; + while (center < pAS_Info->f_if1_Center + pAS_Info->f_if1_bw/2 + pAS_Info->f_LO2_FracN_Avoid) + { + /* Exclude LO2 FracN */ + MT2063_AddExclZone(pAS_Info, center-pAS_Info->f_LO2_FracN_Avoid, center-1); + MT2063_AddExclZone(pAS_Info, center+1, center+pAS_Info->f_LO2_FracN_Avoid); + center += pAS_Info->f_ref; + } + + if( MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT) ) + { + /* Exclude LO1 values that conflict with DECT channels */ + MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in); /* Ctr = 1921.536 */ + MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in); /* Ctr = 1923.264 */ + MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in); /* Ctr = 1924.992 */ + MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in); /* Ctr = 1926.720 */ + MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in); /* Ctr = 1928.448 */ + } + + if( MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT) ) + { + MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in); /* Ctr = 1897.344 */ + MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in); /* Ctr = 1895.616 */ + MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in); /* Ctr = 1893.888 */ + MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in); /* Ctr = 1892.16 */ + MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in); /* Ctr = 1890.432 */ + MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in); /* Ctr = 1888.704 */ + MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in); /* Ctr = 1886.976 */ + MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in); /* Ctr = 1885.248 */ + MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in); /* Ctr = 1883.52 */ + MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in); /* Ctr = 1881.792 */ + } + +#if MT2063_TUNER_CNT > 1 + /* + ** Iterate through all adjacent tuners and exclude frequencies related to them + */ + for (index = 0; index < TunerCount; ++index) + { + adj = TunerList[index]; + if (pAS_Info == adj) /* skip over our own data, don't process it */ + continue; + + /* + ** Add 1st IF exclusion zone covering adjacent tuner's LO2 + ** at "adjfLO2 + f_out" +/- m_MinLOSpacing + */ + if (adj->f_LO2 != 0) + MT2063_AddExclZone(pAS_Info, + (adj->f_LO2 + pAS_Info->f_out) - pAS_Info->f_min_LO_Separation, + (adj->f_LO2 + pAS_Info->f_out) + pAS_Info->f_min_LO_Separation ); + + /* + ** Add 1st IF exclusion zone covering adjacent tuner's LO1 + ** at "adjfLO1 - f_in" +/- m_MinLOSpacing + */ + if (adj->f_LO1 != 0) + MT2063_AddExclZone(pAS_Info, + (adj->f_LO1 - pAS_Info->f_in) - pAS_Info->f_min_LO_Separation, + (adj->f_LO1 - pAS_Info->f_in) + pAS_Info->f_min_LO_Separation ); + } +#endif +} + + +static struct MT2063_ExclZone_t* InsertNode(struct MT2063_AvoidSpursData_t* pAS_Info, + struct MT2063_ExclZone_t* pPrevNode) +{ + struct MT2063_ExclZone_t* pNode; + /* Check for a node in the free list */ + if (pAS_Info->freeZones != NULL) + { + /* Use one from the free list */ + pNode = pAS_Info->freeZones; + pAS_Info->freeZones = pNode->next_; + } + else + { + /* Grab a node from the array */ + pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones]; + } + + if (pPrevNode != NULL) + { + pNode->next_ = pPrevNode->next_; + pPrevNode->next_ = pNode; + } + else /* insert at the beginning of the list */ + { + pNode->next_ = pAS_Info->usedZones; + pAS_Info->usedZones = pNode; + } + + pAS_Info->nZones++; + return pNode; +} + + +static struct MT2063_ExclZone_t* RemoveNode(struct MT2063_AvoidSpursData_t* pAS_Info, + struct MT2063_ExclZone_t* pPrevNode, + struct MT2063_ExclZone_t* pNodeToRemove) +{ + struct MT2063_ExclZone_t* pNext = pNodeToRemove->next_; + + /* Make previous node point to the subsequent node */ + if (pPrevNode != NULL) + pPrevNode->next_ = pNext; + + /* Add pNodeToRemove to the beginning of the freeZones */ + pNodeToRemove->next_ = pAS_Info->freeZones; + pAS_Info->freeZones = pNodeToRemove; + + /* Decrement node count */ + pAS_Info->nZones--; + + return pNext; +} + + +/***************************************************************************** +** +** Name: MT_AddExclZone +** +** Description: Add (and merge) an exclusion zone into the list. +** If the range (f_min, f_max) is totally outside the +** 1st IF BW, ignore the entry. +** If the range (f_min, f_max) is negative, ignore the entry. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 103 01-31-2005 DAD Ver 1.14: In MT_AddExclZone(), if the range +** (f_min, f_max) < 0, ignore the entry. +** +*****************************************************************************/ +void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t* pAS_Info, + UData_t f_min, + UData_t f_max) +{ + struct MT2063_ExclZone_t* pNode = pAS_Info->usedZones; + struct MT2063_ExclZone_t* pPrev = NULL; + struct MT2063_ExclZone_t* pNext = NULL; + + /* Check to see if this overlaps the 1st IF filter */ + if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2))) + && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2))) + && (f_min < f_max)) + { + /* + ** 1 2 3 4 5 6 + ** + ** New entry: |---| |--| |--| |-| |---| |--| + ** or or or or or + ** Existing: |--| |--| |--| |---| |-| |--| + */ + + /* Check for our place in the list */ + while ((pNode != NULL) && (pNode->max_ < f_min)) + { + pPrev = pNode; + pNode = pNode->next_; + } + + if ((pNode != NULL) && (pNode->min_ < f_max)) + { + /* Combine me with pNode */ + if (f_min < pNode->min_) + pNode->min_ = f_min; + if (f_max > pNode->max_) + pNode->max_ = f_max; + } + else + { + pNode = InsertNode(pAS_Info, pPrev); + pNode->min_ = f_min; + pNode->max_ = f_max; + } + + /* Look for merging possibilities */ + pNext = pNode->next_; + while ((pNext != NULL) && (pNext->min_ < pNode->max_)) + { + if (pNext->max_ > pNode->max_) + pNode->max_ = pNext->max_; + pNext = RemoveNode(pAS_Info, pNode, pNext); /* Remove pNext, return ptr to pNext->next */ + } + } +} + + +/***************************************************************************** +** +** Name: MT_ChooseFirstIF +** +** Description: Choose the best available 1st IF +** If f_Desired is not excluded, choose that first. +** Otherwise, return the value closest to f_Center that is +** not excluded +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from +** tuner DLL. +** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+) +** Added logic to force f_Center within 1/2 f_Step. +** +*****************************************************************************/ +UData_t MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t* pAS_Info) +{ + /* + ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step". + ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum + ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step. + ** However, the sum must be. + */ + const UData_t f_Desired = pAS_Info->f_LO1_Step * ((pAS_Info->f_if1_Request + pAS_Info->f_in + pAS_Info->f_LO1_Step/2) / pAS_Info->f_LO1_Step) - pAS_Info->f_in; + const UData_t f_Step = (pAS_Info->f_LO1_Step > pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->f_LO2_Step; + UData_t f_Center; + + SData_t i; + SData_t j = 0; + UData_t bDesiredExcluded = 0; + UData_t bZeroExcluded = 0; + SData_t tmpMin, tmpMax; + SData_t bestDiff; + struct MT2063_ExclZone_t* pNode = pAS_Info->usedZones; + struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES]; + + if (pAS_Info->nZones == 0) + return f_Desired; + + /* f_Center needs to be an integer multiple of f_Step away from f_Desired */ + if (pAS_Info->f_if1_Center > f_Desired) + f_Center = f_Desired + f_Step * ((pAS_Info->f_if1_Center - f_Desired + f_Step/2) / f_Step); + else + f_Center = f_Desired - f_Step * ((f_Desired - pAS_Info->f_if1_Center + f_Step/2) / f_Step); + + //assert; + //if (!abs((SData_t) f_Center - (SData_t) pAS_Info->f_if1_Center) <= (SData_t) (f_Step/2)) + // return 0; + + /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */ + while (pNode != NULL) + { + /* floor function */ + tmpMin = floor((SData_t) (pNode->min_ - f_Center), (SData_t) f_Step); + + /* ceil function */ + tmpMax = ceil((SData_t) (pNode->max_ - f_Center), (SData_t) f_Step); + + if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired)) + bDesiredExcluded = 1; + + if ((tmpMin < 0) && (tmpMax > 0)) + bZeroExcluded = 1; + + /* See if this zone overlaps the previous */ + if ((j>0) && (tmpMin < zones[j-1].max_)) + zones[j-1].max_ = tmpMax; + else + { + /* Add new zone */ + //assert(j=MT2063_MAX_ZONES) + //break; + + zones[j].min_ = tmpMin; + zones[j].max_ = tmpMax; + j++; + } + pNode = pNode->next_; + } + + /* + ** If the desired is okay, return with it + */ + if (bDesiredExcluded == 0) + return f_Desired; + + /* + ** If the desired is excluded and the center is okay, return with it + */ + if (bZeroExcluded == 0) + return f_Center; + + /* Find the value closest to 0 (f_Center) */ + bestDiff = zones[0].min_; + for (i=0; i= b) ? a : b; +} + +#if MT2063_TUNER_CNT > 1 +static SData_t RoundAwayFromZero(SData_t n, SData_t d) +{ + return (n<0) ? floor(n, d) : ceil(n, d); +} + +/**************************************************************************** +** +** Name: IsSpurInAdjTunerBand +** +** Description: Checks to see if a spur will be present within the IF's +** bandwidth or near the zero IF. +** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2) +** and +** (0 +/- fZIFBW/2) +** +** ma mb me mf mc md +** <--+-+-+-----------------+-+-+-----------------+-+-+--> +** | ^ 0 ^ | +** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^ +** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2 +** +** Note that some equations are doubled to prevent round-off +** problems when calculating fIFBW/2 +** +** The spur frequencies are computed as: +** +** fSpur = n * f1 - m * f2 - fOffset +** +** Parameters: f1 - The 1st local oscillator (LO) frequency +** of the tuner whose output we are examining +** f2 - The 1st local oscillator (LO) frequency +** of the adjacent tuner +** fOffset - The 2nd local oscillator of the tuner whose +** output we are examining +** fIFOut - Output IF center frequency +** fIFBW - Output IF Bandwidth +** nMaxH - max # of LO harmonics to search +** fp - If spur, positive distance to spur-free band edge (returned) +** fm - If spur, negative distance to spur-free band edge (returned) +** +** Returns: 1 if an LO spur would be present, otherwise 0. +** +** Dependencies: None. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion. +** 115 03-23-2007 DAD Fix declaration of spur due to truncation +** errors. +** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for +** multi-tuners that have +** (delta IF1) > (f_out-f_outbw/2). +** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2 +** Type casts added to preserve correct sign. +** +****************************************************************************/ +static UData_t IsSpurInAdjTunerBand(UData_t bIsMyOutput, + UData_t f1, + UData_t f2, + UData_t fOffset, + UData_t fIFOut, + UData_t fIFBW, + UData_t fZIFBW, + UData_t nMaxH, + UData_t *fp, + UData_t *fm) +{ + UData_t bSpurFound = 0; + + const UData_t fHalf_IFBW = fIFBW / 2; + const UData_t fHalf_ZIFBW = fZIFBW / 2; + + /* Calculate a scale factor for all frequencies, so that our + calculations all stay within 31 bits */ + const UData_t f_Scale = ((f1 + (fOffset + fIFOut + fHalf_IFBW) / nMaxH) / (MAX_UDATA/2 / nMaxH)) + 1; + + /* + ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into + ** signed data types (smaller than MAX_UDATA/2) + */ + const SData_t _f1 = (SData_t) ( f1 / f_Scale); + const SData_t _f2 = (SData_t) ( f2 / f_Scale); + const SData_t _f3 = (SData_t) (fOffset / f_Scale); + + const SData_t c = (SData_t) (fIFOut - fHalf_IFBW) / (SData_t) f_Scale; + const SData_t d = (SData_t) ((fIFOut + fHalf_IFBW) / f_Scale); + const SData_t f = (SData_t) (fHalf_ZIFBW / f_Scale); + + SData_t ma, mb, mc, md, me, mf; + + SData_t fp_ = 0; + SData_t fm_ = 0; + SData_t n; + + + /* + ** If the other tuner does not have an LO frequency defined, + ** assume that we cannot interfere with it + */ + if (f2 == 0) + return 0; + + + /* Check out all multiples of f1 from -nMaxH to +nMaxH */ + for (n = -(SData_t)nMaxH; n <= (SData_t)nMaxH; ++n) + { + const SData_t nf1 = n*_f1; + md = (_f3 + d - nf1) / _f2; + + /* If # f2 harmonics > nMaxH, then no spurs present */ + if (md <= -(SData_t) nMaxH ) + break; + + ma = (_f3 - d - nf1) / _f2; + if ((ma == md) || (ma >= (SData_t) (nMaxH))) + continue; + + mc = (_f3 + c - nf1) / _f2; + if (mc != md) + { + const SData_t m = (n<0) ? md : mc; + const SData_t fspur = (nf1 + m*_f2 - _f3); + const SData_t den = (bIsMyOutput ? n - 1 : n); + if (den == 0) + { + fp_ = (d - fspur)* f_Scale; + fm_ = (fspur - c)* f_Scale; + } + else + { + fp_ = (SData_t) RoundAwayFromZero((d - fspur)* f_Scale, den); + fm_ = (SData_t) RoundAwayFromZero((fspur - c)* f_Scale, den); + } + if (((UData_t)abs(fm_) >= f_Scale) && ((UData_t)abs(fp_) >= f_Scale)) + { + bSpurFound = 1; + break; + } + } + + /* Location of Zero-IF-spur to be checked */ + mf = (_f3 + f - nf1) / _f2; + me = (_f3 - f - nf1) / _f2; + if (me != mf) + { + const SData_t m = (n<0) ? mf : me; + const SData_t fspur = (nf1 + m*_f2 - _f3); + const SData_t den = (bIsMyOutput ? n - 1 : n); + if (den == 0) + { + fp_ = (d - fspur)* f_Scale; + fm_ = (fspur - c)* f_Scale; + } + else + { + fp_ = (SData_t) RoundAwayFromZero((f - fspur)* f_Scale, den); + fm_ = (SData_t) RoundAwayFromZero((fspur + f)* f_Scale, den); + } + if (((UData_t)abs(fm_) >= f_Scale) && ((UData_t)abs(fp_) >= f_Scale)) + { + bSpurFound = 1; + break; + } + } + + mb = (_f3 - c - nf1) / _f2; + if (ma != mb) + { + const SData_t m = (n<0) ? mb : ma; + const SData_t fspur = (nf1 + m*_f2 - _f3); + const SData_t den = (bIsMyOutput ? n - 1 : n); + if (den == 0) + { + fp_ = (d - fspur)* f_Scale; + fm_ = (fspur - c)* f_Scale; + } + else + { + fp_ = (SData_t) RoundAwayFromZero((-c - fspur)* f_Scale, den); + fm_ = (SData_t) RoundAwayFromZero((fspur +d)* f_Scale, den); + } + if (((UData_t)abs(fm_) >= f_Scale) && ((UData_t)abs(fp_) >= f_Scale)) + { + bSpurFound = 1; + break; + } + } + } + + /* + ** Verify that fm & fp are both positive + ** Add one to ensure next 1st IF choice is not right on the edge + */ + if (fp_ < 0) + { + *fp = -fm_ + 1; + *fm = -fp_ + 1; + } + else if (fp_ > 0) + { + *fp = fp_ + 1; + *fm = fm_ + 1; + } + else + { + *fp = 1; + *fm = abs(fm_) + 1; + } + + return bSpurFound; +} +#endif + +/**************************************************************************** +** +** Name: IsSpurInBand +** +** Description: Checks to see if a spur will be present within the IF's +** bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW) +** +** ma mb mc md +** <--+-+-+-------------------+-------------------+-+-+--> +** | ^ 0 ^ | +** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^ +** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2 +** +** Note that some equations are doubled to prevent round-off +** problems when calculating fIFBW/2 +** +** Parameters: pAS_Info - Avoid Spurs information block +** fm - If spur, amount f_IF1 has to move negative +** fp - If spur, amount f_IF1 has to move positive +** +** Global: None +** +** Returns: 1 if an LO spur would be present, otherwise 0. +** +** Dependencies: None. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** N/A 11-28-2002 DAD Implemented algorithm from applied patent +** +****************************************************************************/ +static UData_t IsSpurInBand(struct MT2063_AvoidSpursData_t* pAS_Info, + UData_t* fm, + UData_t* fp) +{ + /* + ** Calculate LO frequency settings. + */ + UData_t n, n0; + const UData_t f_LO1 = pAS_Info->f_LO1; + const UData_t f_LO2 = pAS_Info->f_LO2; + const UData_t d = pAS_Info->f_out + pAS_Info->f_out_bw/2; + const UData_t c = d - pAS_Info->f_out_bw; + const UData_t f = pAS_Info->f_zif_bw/2; + const UData_t f_Scale = (f_LO1 / (MAX_UDATA/2 / pAS_Info->maxH1)) + 1; + SData_t f_nsLO1, f_nsLO2; + SData_t f_Spur; + UData_t ma, mb, mc, md, me, mf; + UData_t lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs; +#if MT2063_TUNER_CNT > 1 + UData_t index; + + struct MT2063_AvoidSpursData_t *adj; +#endif + *fm = 0; + + /* + ** For each edge (d, c & f), calculate a scale, based on the gcd + ** of f_LO1, f_LO2 and the edge value. Use the larger of this + ** gcd-based scale factor or f_Scale. + */ + lo_gcd = MT2063_gcd(f_LO1, f_LO2); + gd_Scale = MT2063_umax((UData_t) MT2063_gcd(lo_gcd, d), f_Scale); + hgds = gd_Scale/2; + gc_Scale = MT2063_umax((UData_t) MT2063_gcd(lo_gcd, c), f_Scale); + hgcs = gc_Scale/2; + gf_Scale = MT2063_umax((UData_t) MT2063_gcd(lo_gcd, f), f_Scale); + hgfs = gf_Scale/2; + + n0 = uceil(f_LO2 - d, f_LO1 - f_LO2); + + /* Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic */ + for (n=n0; n<=pAS_Info->maxH1; ++n) + { + md = (n*((f_LO1+hgds)/gd_Scale) - ((d+hgds)/gd_Scale)) / ((f_LO2+hgds)/gd_Scale); + + /* If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present */ + if (md >= pAS_Info->maxH1) + break; + + ma = (n*((f_LO1+hgds)/gd_Scale) + ((d+hgds)/gd_Scale)) / ((f_LO2+hgds)/gd_Scale); + + /* If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic */ + if (md == ma) + continue; + + mc = (n*((f_LO1+hgcs)/gc_Scale) - ((c+hgcs)/gc_Scale)) / ((f_LO2+hgcs)/gc_Scale); + if (mc != md) + { + f_nsLO1 = (SData_t) (n*(f_LO1/gc_Scale)); + f_nsLO2 = (SData_t) (mc*(f_LO2/gc_Scale)); + f_Spur = (gc_Scale * (f_nsLO1 - f_nsLO2)) + n*(f_LO1 % gc_Scale) - mc*(f_LO2 % gc_Scale); + + *fp = ((f_Spur - (SData_t) c) / (mc - n)) + 1; + *fm = (((SData_t) d - f_Spur) / (mc - n)) + 1; + return 1; + } + + /* Location of Zero-IF-spur to be checked */ + me = (n*((f_LO1+hgfs)/gf_Scale) + ((f+hgfs)/gf_Scale)) / ((f_LO2+hgfs)/gf_Scale); + mf = (n*((f_LO1+hgfs)/gf_Scale) - ((f+hgfs)/gf_Scale)) / ((f_LO2+hgfs)/gf_Scale); + if (me != mf) + { + f_nsLO1 = n*(f_LO1/gf_Scale); + f_nsLO2 = me*(f_LO2/gf_Scale); + f_Spur = (gf_Scale * (f_nsLO1 - f_nsLO2)) + n*(f_LO1 % gf_Scale) - me*(f_LO2 % gf_Scale); + + *fp = ((f_Spur + (SData_t) f) / (me - n)) + 1; + *fm = (((SData_t) f - f_Spur) / (me - n)) + 1; + return 1; + } + + mb = (n*((f_LO1+hgcs)/gc_Scale) + ((c+hgcs)/gc_Scale)) / ((f_LO2+hgcs)/gc_Scale); + if (ma != mb) + { + f_nsLO1 = n*(f_LO1/gc_Scale); + f_nsLO2 = ma*(f_LO2/gc_Scale); + f_Spur = (gc_Scale * (f_nsLO1 - f_nsLO2)) + n*(f_LO1 % gc_Scale) - ma*(f_LO2 % gc_Scale); + + *fp = (((SData_t) d + f_Spur) / (ma - n)) + 1; + *fm = (-(f_Spur + (SData_t) c) / (ma - n)) + 1; + return 1; + } + } + +#if MT2063_TUNER_CNT > 1 + /* If no spur found, see if there are more tuners on the same board */ + for (index = 0; index < TunerCount; ++index) + { + adj = TunerList[index]; + if (pAS_Info == adj) /* skip over our own data, don't process it */ + continue; + + /* Look for LO-related spurs from the adjacent tuner generated into my IF output */ + if (IsSpurInAdjTunerBand(1, /* check my IF output */ + pAS_Info->f_LO1, /* my fLO1 */ + adj->f_LO1, /* the other tuner's fLO1 */ + pAS_Info->f_LO2, /* my fLO2 */ + pAS_Info->f_out, /* my fOut */ + pAS_Info->f_out_bw, /* my output IF bandwidth */ + pAS_Info->f_zif_bw, /* my Zero-IF bandwidth */ + pAS_Info->maxH2, + fp, /* minimum amount to move LO's positive */ + fm)) /* miminum amount to move LO's negative */ + return 1; + /* Look for LO-related spurs from my tuner generated into the adjacent tuner's IF output */ + if (IsSpurInAdjTunerBand(0, /* check his IF output */ + pAS_Info->f_LO1, /* my fLO1 */ + adj->f_LO1, /* the other tuner's fLO1 */ + adj->f_LO2, /* the other tuner's fLO2 */ + adj->f_out, /* the other tuner's fOut */ + adj->f_out_bw, /* the other tuner's output IF bandwidth */ + pAS_Info->f_zif_bw, /* the other tuner's Zero-IF bandwidth */ + adj->maxH2, + fp, /* minimum amount to move LO's positive */ + fm)) /* miminum amount to move LO's negative */ + return 1; + } +#endif + /* No spurs found */ + return 0; +} + + +/***************************************************************************** +** +** Name: MT_AvoidSpurs +** +** Description: Main entry point to avoid spurs. +** Checks for existing spurs in present LO1, LO2 freqs +** and if present, chooses spur-free LO1, LO2 combination +** that tunes the same input/output frequencies. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 096 04-06-2005 DAD Ver 1.11: Fix divide by 0 error if maxH==0. +** +*****************************************************************************/ +UData_t MT2063_AvoidSpurs(Handle_t h, + struct MT2063_AvoidSpursData_t* pAS_Info) +{ + UData_t status = MT2063_OK; + UData_t fm, fp; /* restricted range on LO's */ + pAS_Info->bSpurAvoided = 0; + pAS_Info->nSpursFound = 0; + + if (pAS_Info->maxH1 == 0) + return MT2063_OK; + + /* + ** Avoid LO Generated Spurs + ** + ** Make sure that have no LO-related spurs within the IF output + ** bandwidth. + ** + ** If there is an LO spur in this band, start at the current IF1 frequency + ** and work out until we find a spur-free frequency or run up against the + ** 1st IF SAW band edge. Use temporary copies of fLO1 and fLO2 so that they + ** will be unchanged if a spur-free setting is not found. + */ + pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp); + if (pAS_Info->bSpurPresent) + { + UData_t zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in; /* current attempt at a 1st IF */ + UData_t zfLO1 = pAS_Info->f_LO1; /* current attempt at an LO1 freq */ + UData_t zfLO2 = pAS_Info->f_LO2; /* current attempt at an LO2 freq */ + UData_t delta_IF1; + UData_t new_IF1; + + /* + ** Spur was found, attempt to find a spur-free 1st IF + */ + do + { + pAS_Info->nSpursFound++; + + /* Raise f_IF1_upper, if needed */ + MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp); + + /* Choose next IF1 that is closest to f_IF1_CENTER */ + new_IF1 = MT2063_ChooseFirstIF(pAS_Info); + + if (new_IF1 > zfIF1) + { + pAS_Info->f_LO1 += (new_IF1 - zfIF1); + pAS_Info->f_LO2 += (new_IF1 - zfIF1); + } + else + { + pAS_Info->f_LO1 -= (zfIF1 - new_IF1); + pAS_Info->f_LO2 -= (zfIF1 - new_IF1); + } + zfIF1 = new_IF1; + + if (zfIF1 > pAS_Info->f_if1_Center) + delta_IF1 = zfIF1 - pAS_Info->f_if1_Center; + else + delta_IF1 = pAS_Info->f_if1_Center - zfIF1; + } + /* + ** Continue while the new 1st IF is still within the 1st IF bandwidth + ** and there is a spur in the band (again) + */ + while ((2*delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && + (pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp))); + + /* + ** Use the LO-spur free values found. If the search went all the way to + ** the 1st IF band edge and always found spurs, just leave the original + ** choice. It's as "good" as any other. + */ + if (pAS_Info->bSpurPresent == 1) + { + status |= MT2063_SPUR_PRESENT_ERR; + pAS_Info->f_LO1 = zfLO1; + pAS_Info->f_LO2 = zfLO2; + } + else + pAS_Info->bSpurAvoided = 1; + } + + status |= ((pAS_Info->nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK); + + return (status); +} + + +UData_t MT2063_AvoidSpursVersion(void) +{ + return (MT2063_SPUR_VERSION); +} +//end of mt2063_spuravoid.c +//================================================================= +//################################################################# +//================================================================= + + +/* +** The expected version of MT_AvoidSpursData_t +** If the version is different, an updated file is needed from Microtune +*/ +/* Expecting version 1.21 of the Spur Avoidance API */ +#define EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION 010201 + +#if MT2063_AVOID_SPURS_INFO_VERSION < EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION +#error Contact Microtune for a newer version of MT_SpurAvoid.c +#elif MT2063_AVOID_SPURS_INFO_VERSION > EXPECTED_MT2063_AVOID_SPURS_INFO_VERSION +#error Contact Microtune for a newer version of mt2063.c +#endif + +#ifndef MT2063_CNT +#error You must define MT2063_CNT in the "mt_userdef.h" file +#endif + + +typedef enum +{ + MT2063_SET_ATTEN, + MT2063_INCR_ATTEN, + MT2063_DECR_ATTEN +} MT2063_ATTEN_CNTL_MODE; + + +//#define TUNER_MT2063_OPTIMIZATION +/* +** Constants used by the tuning algorithm +*/ +#define MT2063_REF_FREQ (16000000UL) /* Reference oscillator Frequency (in Hz) */ +#define MT2063_IF1_BW (22000000UL) /* The IF1 filter bandwidth (in Hz) */ +#define MT2063_TUNE_STEP_SIZE (50000UL) /* Tune in steps of 50 kHz */ +#define MT2063_SPUR_STEP_HZ (250000UL) /* Step size (in Hz) to move IF1 when avoiding spurs */ +#define MT2063_ZIF_BW (2000000UL) /* Zero-IF spur-free bandwidth (in Hz) */ +#define MT2063_MAX_HARMONICS_1 (15UL) /* Highest intra-tuner LO Spur Harmonic to be avoided */ +#define MT2063_MAX_HARMONICS_2 (5UL) /* Highest inter-tuner LO Spur Harmonic to be avoided */ +#define MT2063_MIN_LO_SEP (1000000UL) /* Minimum inter-tuner LO frequency separation */ +#define MT2063_LO1_FRACN_AVOID (0UL) /* LO1 FracN numerator avoid region (in Hz) */ +#define MT2063_LO2_FRACN_AVOID (199999UL) /* LO2 FracN numerator avoid region (in Hz) */ +#define MT2063_MIN_FIN_FREQ (44000000UL) /* Minimum input frequency (in Hz) */ +#define MT2063_MAX_FIN_FREQ (1100000000UL) /* Maximum input frequency (in Hz) */ +#define MT2063_MIN_FOUT_FREQ (36000000UL) /* Minimum output frequency (in Hz) */ +#define MT2063_MAX_FOUT_FREQ (57000000UL) /* Maximum output frequency (in Hz) */ +#define MT2063_MIN_DNC_FREQ (1293000000UL) /* Minimum LO2 frequency (in Hz) */ +#define MT2063_MAX_DNC_FREQ (1614000000UL) /* Maximum LO2 frequency (in Hz) */ +#define MT2063_MIN_UPC_FREQ (1396000000UL) /* Minimum LO1 frequency (in Hz) */ +#define MT2063_MAX_UPC_FREQ (2750000000UL) /* Maximum LO1 frequency (in Hz) */ + + +/* +** Define the supported Part/Rev codes for the MT2063 +*/ +#define MT2063_B0 (0x9B) +#define MT2063_B1 (0x9C) +#define MT2063_B2 (0x9D) +#define MT2063_B3 (0x9E) + +/* +** The number of Tuner Registers +*/ +static const UData_t MT2063_Num_Registers = MT2063_REG_END_REGS; + + +#define USE_GLOBAL_TUNER 0 + +static UData_t nMT2063MaxTuners = MT2063_CNT; +static struct MT2063_Info_t MT2063_Info[MT2063_CNT]; +static struct MT2063_Info_t *MT2063_Avail[MT2063_CNT]; +static UData_t nMT2063OpenTuners = 0; + + +/* +** Constants for setting receiver modes. +** (6 modes defined at this time, enumerated by MT2063_RCVR_MODES) +** (DNC1GC & DNC2GC are the values, which are used, when the specific +** DNC Output is selected, the other is always off) +** +** If PAL-L or L' is received, set: +** MT2063_SetParam(hMT2063,MT2063_TAGC,1); +** +** --------------+---------------------------------------------- +** Mode 0 : | MT2063_CABLE_QAM +** Mode 1 : | MT2063_CABLE_ANALOG +** Mode 2 : | MT2063_OFFAIR_COFDM +** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS +** Mode 4 : | MT2063_OFFAIR_ANALOG +** Mode 5 : | MT2063_OFFAIR_8VSB +** --------------+----+----+----+----+-----+-----+-------------- +** Mode | 0 | 1 | 2 | 3 | 4 | 5 | +** --------------+----+----+----+----+-----+-----+ +** +** +*/ +static const U8Data RFAGCEN[] = { 0, 0, 0, 0, 0, 0 }; +static const U8Data LNARIN[] = { 0, 0, 3, 3, 3, 3 }; +static const U8Data FIFFQEN[] = { 1, 1, 1, 1, 1, 1 }; +static const U8Data FIFFQ[] = { 0, 0, 0, 0, 0, 0 }; +static const U8Data DNC1GC[] = { 0, 0, 0, 0, 0, 0 }; +static const U8Data DNC2GC[] = { 0, 0, 0, 0, 0, 0 }; +static const U8Data ACLNAMAX[] = { 31, 31, 31, 31, 31, 31 }; +static const U8Data LNATGT[] = { 44, 43, 43, 43, 43, 43 }; +static const U8Data RFOVDIS[] = { 0, 0, 0, 0, 0, 0 }; +static const U8Data ACRFMAX[] = { 31, 31, 31, 31, 31, 31 }; +static const U8Data PD1TGT[] = { 36, 36, 38, 38, 36, 38 }; +static const U8Data FIFOVDIS[] = { 0, 0, 0, 0, 0, 0 }; +static const U8Data ACFIFMAX[] = { 29, 29, 29, 29, 29, 29 }; +static const U8Data PD2TGT[] = { 40, 33, 38, 42, 30, 38 }; + +/* +** Local Function Prototypes - not available for external access. +*/ + +/* Forward declaration(s): */ +static UData_t MT2063_CalcLO1Mult(UData_t *Div, UData_t *FracN, UData_t f_LO, UData_t f_LO_Step, UData_t f_Ref); +static UData_t MT2063_CalcLO2Mult(UData_t *Div, UData_t *FracN, UData_t f_LO, UData_t f_LO_Step, UData_t f_Ref); +static UData_t MT2063_fLO_FractionalTerm(UData_t f_ref, UData_t num, UData_t denom); + + +/****************************************************************************** +** +** Name: MT2063_Open +** +** Description: Initialize the tuner's register values. +** +** Parameters: MT2063_Addr - Serial bus address of the tuner. +** hMT2063 - Tuner handle passed back. +** hUserData - User-defined data, if needed for the +** MT_ReadSub() & MT_WriteSub functions. +** +** Returns: status: +** MT_OK - No errors +** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch +** MT_TUNER_INIT_ERR - Tuner initialization failed +** MT_COMM_ERR - Serial bus communications error +** MT_ARG_NULL - Null pointer argument passed +** MT_TUNER_CNT_ERR - Too many tuners open +** +** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus +** MT_WriteSub - Write byte(s) of data to the two-wire bus +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +******************************************************************************/ +UData_t MT2063_Open(UData_t MT2063_Addr, + Handle_t* hMT2063, + Handle_t hUserData) +{ + UData_t status = MT2063_OK; /* Status to be returned. */ + SData_t i; + struct MT2063_Info_t* pInfo = NULL; + struct dvb_frontend *fe= (struct dvb_frontend *)hUserData; + struct mt2063_state *state = fe->tuner_priv; + + /* Check the argument before using */ + if (hMT2063 == NULL) + { + return MT2063_ARG_NULL; + } + + /* Default tuner handle to NULL. If successful, it will be reassigned */ + +#if USE_GLOBAL_TUNER + *hMT2063 = NULL; + + /* + ** If this is our first tuner, initialize the address fields and + ** the list of available control blocks. + */ + if (nMT2063OpenTuners == 0) + { + for (i=MT2063_CNT-1; i>=0; i--) + { + MT2063_Info[i].handle = NULL; + MT2063_Info[i].address = MAX_UDATA; + MT2063_Info[i].rcvr_mode = MT2063_CABLE_QAM; + MT2063_Info[i].hUserData = NULL; + MT2063_Avail[i] = &MT2063_Info[i]; + } + } + + /* + ** Look for an existing MT2063_State_t entry with this address. + */ + for (i=MT2063_CNT-1; i>=0; i--) + { + /* + ** If an open'ed handle provided, we'll re-initialize that structure. + ** + ** We recognize an open tuner because the address and hUserData are + ** the same as one that has already been opened + */ + if ((MT2063_Info[i].address == MT2063_Addr) && + (MT2063_Info[i].hUserData == hUserData)) + { + pInfo = &MT2063_Info[i]; + break; + } + } + + /* If not found, choose an empty spot. */ + if (pInfo == NULL) + { + /* Check to see that we're not over-allocating */ + if (nMT2063OpenTuners == MT2063_CNT) + { + return MT2063_TUNER_CNT_ERR; + } + /* Use the next available block from the list */ + pInfo = MT2063_Avail[nMT2063OpenTuners]; + nMT2063OpenTuners++; + } +#else + if (state->MT2063_init==FALSE) + { + pInfo = kzalloc(sizeof (struct MT2063_Info_t), GFP_KERNEL); + if (pInfo == NULL) + { + return MT2063_TUNER_OPEN_ERR; + } + pInfo->handle = NULL; + pInfo->address = MAX_UDATA; + pInfo->rcvr_mode = MT2063_CABLE_QAM; + pInfo->hUserData = NULL; + } + else + { + pInfo = *hMT2063; + } +#endif + + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_RegisterTuner(&pInfo->AS_Data); + } + + if (MT2063_NO_ERROR(status)) + { + pInfo->handle = (Handle_t) pInfo; + + pInfo->hUserData = hUserData; + pInfo->address = MT2063_Addr; + pInfo->rcvr_mode = MT2063_CABLE_QAM; + status |= MT2063_ReInit((Handle_t) pInfo); + } + + if (MT2063_IS_ERROR(status)) + /* MT2063_Close handles the un-registration of the tuner */ + MT2063_Close((Handle_t) pInfo); + else + { + state->MT2063_init = TRUE; + *hMT2063 = pInfo->handle; + + } + + return (status); +} + + +static UData_t MT2063_IsValidHandle(struct MT2063_Info_t* handle) +{ + return ((handle != NULL) && (handle->handle == handle)) ? 1 : 0; +} + + +/****************************************************************************** +** +** Name: MT2063_Close +** +** Description: Release the handle to the tuner. +** +** Parameters: hMT2063 - Handle to the MT2063 tuner +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** +** Dependencies: mt_errordef.h - definition of error codes +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +******************************************************************************/ +UData_t MT2063_Close(Handle_t hMT2063) +{ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) hMT2063; + + if (!MT2063_IsValidHandle(pInfo)) + return MT2063_INV_HANDLE; + + /* Unregister tuner with SpurAvoidance routines (if needed) */ + MT2063_UnRegisterTuner(&pInfo->AS_Data); + /* Now remove the tuner from our own list of tuners */ + pInfo->handle = NULL; + pInfo->address = MAX_UDATA; + pInfo->hUserData = NULL; + #if USE_GLOBAL_TUNER + nMT2063OpenTuners--; + MT2063_Avail[nMT2063OpenTuners] = pInfo; /* Return control block to available list */ + #else + //kfree(pInfo); + //pInfo = NULL; + #endif + return MT2063_OK; +} + + +/****************************************************************************** +** +** Name: MT2063_GetGPIO +** +** Description: Get the current MT2063 GPIO value. +** +** Parameters: h - Open handle to the tuner (from MT2063_Open). +** gpio_id - Selects GPIO0, GPIO1 or GPIO2 +** attr - Selects input readback, I/O direction or +** output value +** *value - current setting of GPIO pin +** +** Usage: status = MT2063_GetGPIO(hMT2063, MT2063_GPIO_OUT, &value); +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Null pointer argument passed +** +** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +******************************************************************************/ +UData_t MT2063_GetGPIO(Handle_t h, enum MT2063_GPIO_ID gpio_id, + enum MT2063_GPIO_Attr attr, + UData_t* value) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + U8Data regno; + SData_t shift; + static U8Data GPIOreg[3] = {MT2063_REG_RF_STATUS, MT2063_REG_FIF_OV, MT2063_REG_RF_OV}; + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + if (MT2063_IsValidHandle(pInfo) == 0) + return MT2063_INV_HANDLE; + + if (value == NULL) + return MT2063_ARG_NULL; + + regno = GPIOreg[attr]; + + /* We'll read the register just in case the write didn't work last time */ + status = MT2063_ReadSub(pInfo->hUserData, pInfo->address, regno, &pInfo->reg[regno], 1); + + shift = (gpio_id - MT2063_GPIO0 + 5); + *value = (pInfo->reg[regno] >> shift) & 1; + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_GetLocked +** +** Description: Checks to see if LO1 and LO2 are locked. +** +** Parameters: h - Open handle to the tuner (from MT2063_Open). +** +** Returns: status: +** MT_OK - No errors +** MT_UPC_UNLOCK - Upconverter PLL unlocked +** MT_DNC_UNLOCK - Downconverter PLL unlocked +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** +** Dependencies: MT_ReadSub - Read byte(s) of data from the serial bus +** MT_Sleep - Delay execution for x milliseconds +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_GetLocked(Handle_t h) +{ + const UData_t nMaxWait = 100; /* wait a maximum of 100 msec */ + const UData_t nPollRate = 2; /* poll status bits every 2 ms */ + const UData_t nMaxLoops = nMaxWait / nPollRate; + const U8Data LO1LK = 0x80; + U8Data LO2LK = 0x08; + UData_t status = MT2063_OK; /* Status to be returned */ + UData_t nDelays = 0; + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + if (MT2063_IsValidHandle(pInfo) == 0) + return MT2063_INV_HANDLE; + + /* LO2 Lock bit was in a different place for B0 version */ + if (pInfo->tuner_id == MT2063_B0) + LO2LK = 0x40; + + do + { + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO_STATUS, &pInfo->reg[MT2063_REG_LO_STATUS], 1); + + if (MT2063_IS_ERROR(status)) + return (status); + + if ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) == (LO1LK | LO2LK)) + { + return (status); + } + MT2063_Sleep(pInfo->hUserData, nPollRate); /* Wait between retries */ + } + while (++nDelays < nMaxLoops); + + if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO1LK) == 0x00) + status |= MT2063_UPC_UNLOCK; + if ((pInfo->reg[MT2063_REG_LO_STATUS] & LO2LK) == 0x00) + status |= MT2063_DNC_UNLOCK; + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_GetParam +** +** Description: Gets a tuning algorithm parameter. +** +** This function provides access to the internals of the +** tuning algorithm - mostly for testing purposes. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** param - Tuning algorithm parameter +** (see enum MT2063_Param) +** pValue - ptr to returned value +** +** param Description +** ---------------------- -------------------------------- +** MT2063_IC_ADDR Serial Bus address of this tuner +** MT2063_MAX_OPEN Max # of MT2063's allowed open +** MT2063_NUM_OPEN # of MT2063's open +** MT2063_SRO_FREQ crystal frequency +** MT2063_STEPSIZE minimum tuning step size +** MT2063_INPUT_FREQ input center frequency +** MT2063_LO1_FREQ LO1 Frequency +** MT2063_LO1_STEPSIZE LO1 minimum step size +** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region +** MT2063_IF1_ACTUAL Current 1st IF in use +** MT2063_IF1_REQUEST Requested 1st IF +** MT2063_IF1_CENTER Center of 1st IF SAW filter +** MT2063_IF1_BW Bandwidth of 1st IF SAW filter +** MT2063_ZIF_BW zero-IF bandwidth +** MT2063_LO2_FREQ LO2 Frequency +** MT2063_LO2_STEPSIZE LO2 minimum step size +** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region +** MT2063_OUTPUT_FREQ output center frequency +** MT2063_OUTPUT_BW output bandwidth +** MT2063_LO_SEPARATION min inter-tuner LO separation +** MT2063_AS_ALG ID of avoid-spurs algorithm in use +** MT2063_MAX_HARM1 max # of intra-tuner harmonics +** MT2063_MAX_HARM2 max # of inter-tuner harmonics +** MT2063_EXCL_ZONES # of 1st IF exclusion zones +** MT2063_NUM_SPURS # of spurs found/avoided +** MT2063_SPUR_AVOIDED >0 spurs avoided +** MT2063_SPUR_PRESENT >0 spurs in output (mathematically) +** MT2063_RCVR_MODE Predefined modes. +** MT2063_ACLNA LNA attenuator gain code +** MT2063_ACRF RF attenuator gain code +** MT2063_ACFIF FIF attenuator gain code +** MT2063_ACLNA_MAX LNA attenuator limit +** MT2063_ACRF_MAX RF attenuator limit +** MT2063_ACFIF_MAX FIF attenuator limit +** MT2063_PD1 Actual value of PD1 +** MT2063_PD2 Actual value of PD2 +** MT2063_DNC_OUTPUT_ENABLE DNC output selection +** MT2063_VGAGC VGA gain code +** MT2063_VGAOI VGA output current +** MT2063_TAGC TAGC setting +** MT2063_AMPGC AMP gain code +** MT2063_AVOID_DECT Avoid DECT Frequencies +** MT2063_CTFILT_SW Cleartune filter selection +** +** Usage: status |= MT2063_GetParam(hMT2063, +** MT2063_IF1_ACTUAL, +** &f_IF1_Actual); +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Null pointer argument passed +** MT_ARG_RANGE - Invalid parameter requested +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** See Also: MT2063_SetParam, MT2063_Open +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ +** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC +** 173 M 01-23-2008 RSK Ver 1.12: Read LO1C and LO2C registers from HW +** in GetParam. +** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT +** Split SetParam up to ACLNA / ACLNA_MAX +** removed ACLNA_INRC/DECR (+RF & FIF) +** removed GCUAUTO / BYPATNDN/UP +** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs. +** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. +** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW +** +****************************************************************************/ +UData_t MT2063_GetParam(Handle_t h, + enum MT2063_Param param, + UData_t* pValue) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + UData_t Div; + UData_t Num; + + if (pValue == NULL) + status |= MT2063_ARG_NULL; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status |= MT2063_INV_HANDLE; + + if (MT2063_NO_ERROR(status)) + { + switch (param) + { + /* Serial Bus address of this tuner */ + case MT2063_IC_ADDR: + *pValue = pInfo->address; + break; + + /* Max # of MT2063's allowed to be open */ + case MT2063_MAX_OPEN: + *pValue = nMT2063MaxTuners; + break; + + /* # of MT2063's open */ + case MT2063_NUM_OPEN: + *pValue = nMT2063OpenTuners; + break; + + /* crystal frequency */ + case MT2063_SRO_FREQ: + *pValue = pInfo->AS_Data.f_ref; + break; + + /* minimum tuning step size */ + case MT2063_STEPSIZE: + *pValue = pInfo->AS_Data.f_LO2_Step; + break; + + /* input center frequency */ + case MT2063_INPUT_FREQ: + *pValue = pInfo->AS_Data.f_in; + break; + + /* LO1 Frequency */ + case MT2063_LO1_FREQ: + { + /* read the actual tuner register values for LO1C_1 and LO1C_2 */ + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1C_1, &pInfo->reg[MT2063_REG_LO1C_1], 2); + Div = pInfo->reg[MT2063_REG_LO1C_1]; + Num = pInfo->reg[MT2063_REG_LO1C_2] & 0x3F; + pInfo->AS_Data.f_LO1 = (pInfo->AS_Data.f_ref * Div) + MT2063_fLO_FractionalTerm(pInfo->AS_Data.f_ref, Num, 64); + } + *pValue = pInfo->AS_Data.f_LO1; + break; + + /* LO1 minimum step size */ + case MT2063_LO1_STEPSIZE: + *pValue = pInfo->AS_Data.f_LO1_Step; + break; + + /* LO1 FracN keep-out region */ + case MT2063_LO1_FRACN_AVOID_PARAM: + *pValue = pInfo->AS_Data.f_LO1_FracN_Avoid; + break; + + /* Current 1st IF in use */ + case MT2063_IF1_ACTUAL: + *pValue = pInfo->f_IF1_actual; + break; + + /* Requested 1st IF */ + case MT2063_IF1_REQUEST: + *pValue = pInfo->AS_Data.f_if1_Request; + break; + + /* Center of 1st IF SAW filter */ + case MT2063_IF1_CENTER: + *pValue = pInfo->AS_Data.f_if1_Center; + break; + + /* Bandwidth of 1st IF SAW filter */ + case MT2063_IF1_BW: + *pValue = pInfo->AS_Data.f_if1_bw; + break; + + /* zero-IF bandwidth */ + case MT2063_ZIF_BW: + *pValue = pInfo->AS_Data.f_zif_bw; + break; + + /* LO2 Frequency */ + case MT2063_LO2_FREQ: + { + /* Read the actual tuner register values for LO2C_1, LO2C_2 and LO2C_3 */ + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2C_1, &pInfo->reg[MT2063_REG_LO2C_1], 3); + Div = (pInfo->reg[MT2063_REG_LO2C_1] & 0xFE ) >> 1; + Num = ((pInfo->reg[MT2063_REG_LO2C_1] & 0x01 ) << 12) | (pInfo->reg[MT2063_REG_LO2C_2] << 4) | (pInfo->reg[MT2063_REG_LO2C_3] & 0x00F); + pInfo->AS_Data.f_LO2 = (pInfo->AS_Data.f_ref * Div) + MT2063_fLO_FractionalTerm(pInfo->AS_Data.f_ref, Num, 8191); + } + *pValue = pInfo->AS_Data.f_LO2; + break; + + /* LO2 minimum step size */ + case MT2063_LO2_STEPSIZE: + *pValue = pInfo->AS_Data.f_LO2_Step; + break; + + /* LO2 FracN keep-out region */ + case MT2063_LO2_FRACN_AVOID: + *pValue = pInfo->AS_Data.f_LO2_FracN_Avoid; + break; + + /* output center frequency */ + case MT2063_OUTPUT_FREQ: + *pValue = pInfo->AS_Data.f_out; + break; + + /* output bandwidth */ + case MT2063_OUTPUT_BW: + *pValue = pInfo->AS_Data.f_out_bw - 750000; + break; + + /* min inter-tuner LO separation */ + case MT2063_LO_SEPARATION: + *pValue = pInfo->AS_Data.f_min_LO_Separation; + break; + + /* ID of avoid-spurs algorithm in use */ + case MT2063_AS_ALG: + *pValue = pInfo->AS_Data.nAS_Algorithm; + break; + + /* max # of intra-tuner harmonics */ + case MT2063_MAX_HARM1: + *pValue = pInfo->AS_Data.maxH1; + break; + + /* max # of inter-tuner harmonics */ + case MT2063_MAX_HARM2: + *pValue = pInfo->AS_Data.maxH2; + break; + + /* # of 1st IF exclusion zones */ + case MT2063_EXCL_ZONES: + *pValue = pInfo->AS_Data.nZones; + break; + + /* # of spurs found/avoided */ + case MT2063_NUM_SPURS: + *pValue = pInfo->AS_Data.nSpursFound; + break; + + /* >0 spurs avoided */ + case MT2063_SPUR_AVOIDED: + *pValue = pInfo->AS_Data.bSpurAvoided; + break; + + /* >0 spurs in output (mathematically) */ + case MT2063_SPUR_PRESENT: + *pValue = pInfo->AS_Data.bSpurPresent; + break; + + /* Predefined receiver setup combination */ + case MT2063_RCVR_MODE: + *pValue = pInfo->rcvr_mode; + break; + + case MT2063_PD1: + case MT2063_PD2: + { + U8Data mask = (param == MT2063_PD1 ? 0x01 : 0x03); /* PD1 vs PD2 */ + U8Data orig = (pInfo->reg[MT2063_REG_BYP_CTRL]); + U8Data reg = (orig & 0xF1) | mask; /* Only set 3 bits (not 5) */ + int i; + + *pValue = 0; + + /* Initiate ADC output to reg 0x0A */ + if (reg != orig) + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_BYP_CTRL, ®, 1); + + if (MT2063_IS_ERROR(status)) + return (status); + + for (i=0; i<8; i++) { + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_ADC_OUT, &pInfo->reg[MT2063_REG_ADC_OUT], 1); + + if (MT2063_NO_ERROR(status)) + *pValue += pInfo->reg[MT2063_REG_ADC_OUT]; + else + { + if( i ) *pValue /= i; + return (status); + } + } + *pValue /= 8; /* divide by number of reads */ + *pValue >>=2; /* only want 6 MSB's out of 8 */ + + /* Restore value of Register BYP_CTRL */ + if (reg != orig) + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_BYP_CTRL, &orig, 1); + } + break; + + /* Get LNA attenuator code */ + case MT2063_ACLNA: + { + U8Data val; + status |= MT2063_GetReg(pInfo, MT2063_REG_XO_STATUS, &val); + *pValue = val & 0x1f; + } + break; + + /* Get RF attenuator code */ + case MT2063_ACRF: + { + U8Data val; + status |= MT2063_GetReg(pInfo, MT2063_REG_RF_STATUS, &val); + *pValue = val & 0x1f; + } + break; + + /* Get FIF attenuator code */ + case MT2063_ACFIF: + { + U8Data val; + status |= MT2063_GetReg(pInfo, MT2063_REG_FIF_STATUS, &val); + *pValue = val & 0x1f; + } + break; + + /* Get LNA attenuator limit */ + case MT2063_ACLNA_MAX: + { + U8Data val; + status |= MT2063_GetReg(pInfo, MT2063_REG_LNA_OV, &val); + *pValue = val & 0x1f; + } + break; + + /* Get RF attenuator limit */ + case MT2063_ACRF_MAX: + { + U8Data val; + status |= MT2063_GetReg(pInfo, MT2063_REG_RF_OV, &val); + *pValue = val & 0x1f; + } + break; + + /* Get FIF attenuator limit */ + case MT2063_ACFIF_MAX: + { + U8Data val; + status |= MT2063_GetReg(pInfo, MT2063_REG_FIF_OV, &val); + *pValue = val & 0x1f; + } + break; + + /* Get current used DNC output */ + case MT2063_DNC_OUTPUT_ENABLE: + { + if ( (pInfo->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) /* if DNC1 is off */ + { + if ( (pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */ + *pValue = (UData_t)MT2063_DNC_NONE; + else + *pValue = (UData_t)MT2063_DNC_2; + } + else /* DNC1 is on */ + { + if ( (pInfo->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03) /* if DNC2 is off */ + *pValue = (UData_t)MT2063_DNC_1; + else + *pValue = (UData_t)MT2063_DNC_BOTH; + } + } + break; + + /* Get VGA Gain Code */ + case MT2063_VGAGC: + *pValue = ( (pInfo->reg[MT2063_REG_VGA_GAIN] & 0x0C) >> 2 ); + break; + + /* Get VGA bias current */ + case MT2063_VGAOI: + *pValue = (pInfo->reg[MT2063_REG_RSVD_31] & 0x07); + break; + + /* Get TAGC setting */ + case MT2063_TAGC: + *pValue = (pInfo->reg[MT2063_REG_RSVD_1E] & 0x03); + break; + + /* Get AMP Gain Code */ + case MT2063_AMPGC: + *pValue = (pInfo->reg[MT2063_REG_TEMP_SEL] & 0x03); + break; + + /* Avoid DECT Frequencies */ + case MT2063_AVOID_DECT: + *pValue = pInfo->AS_Data.avoidDECT; + break; + + /* Cleartune filter selection: 0 - by IC (default), 1 - by software */ + case MT2063_CTFILT_SW: + *pValue = pInfo->ctfilt_sw; + break; + + case MT2063_EOP: + default: + status |= MT2063_ARG_RANGE; + } + } + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_GetReg +** +** Description: Gets an MT2063 register. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** reg - MT2063 register/subaddress location +** *val - MT2063 register/subaddress value +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Null pointer argument passed +** MT_ARG_RANGE - Argument out of range +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Use this function if you need to read a register from +** the MT2063. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_GetReg(Handle_t h, + U8Data reg, + U8Data* val) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status |= MT2063_INV_HANDLE; + + if (val == NULL) + status |= MT2063_ARG_NULL; + + if (reg >= MT2063_REG_END_REGS) + status |= MT2063_ARG_RANGE; + + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, reg, &pInfo->reg[reg], 1); + if (MT2063_NO_ERROR(status)) + *val = pInfo->reg[reg]; + } + + return (status); +} + + +/****************************************************************************** +** +** Name: MT2063_GetTemp +** +** Description: Get the MT2063 Temperature register. +** +** Parameters: h - Open handle to the tuner (from MT2063_Open). +** *value - value read from the register +** +** Binary +** Value Returned Value Approx Temp +** --------------------------------------------- +** MT2063_T_0C 0000 0C +** MT2063_T_10C 0001 10C +** MT2063_T_20C 0010 20C +** MT2063_T_30C 0011 30C +** MT2063_T_40C 0100 40C +** MT2063_T_50C 0101 50C +** MT2063_T_60C 0110 60C +** MT2063_T_70C 0111 70C +** MT2063_T_80C 1000 80C +** MT2063_T_90C 1001 90C +** MT2063_T_100C 1010 100C +** MT2063_T_110C 1011 110C +** MT2063_T_120C 1100 120C +** MT2063_T_130C 1101 130C +** MT2063_T_140C 1110 140C +** MT2063_T_150C 1111 150C +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Null pointer argument passed +** MT_ARG_RANGE - Argument out of range +** +** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus +** MT_WriteSub - Write byte(s) of data to the two-wire bus +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +******************************************************************************/ +UData_t MT2063_GetTemp(Handle_t h, enum MT2063_Temperature* value) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + if (MT2063_IsValidHandle(pInfo) == 0) + return MT2063_INV_HANDLE; + + if (value == NULL) + return MT2063_ARG_NULL; + + if ((MT2063_NO_ERROR(status)) && ((pInfo->reg[MT2063_REG_TEMP_SEL] & 0xE0) != 0x00)) + { + pInfo->reg[MT2063_REG_TEMP_SEL] &= (0x1F); + status |= MT2063_WriteSub(pInfo->hUserData, + pInfo->address, + MT2063_REG_TEMP_SEL, + &pInfo->reg[MT2063_REG_TEMP_SEL], + 1); + } + + if (MT2063_NO_ERROR(status)) + status |= MT2063_ReadSub(pInfo->hUserData, + pInfo->address, + MT2063_REG_TEMP_STATUS, + &pInfo->reg[MT2063_REG_TEMP_STATUS], + 1); + + if (MT2063_NO_ERROR(status)) + *value = (enum MT2063_Temperature) (pInfo->reg[MT2063_REG_TEMP_STATUS] >> 4); + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_GetUserData +** +** Description: Gets the user-defined data item. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Null pointer argument passed +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** The hUserData parameter is a user-specific argument +** that is stored internally with the other tuner- +** specific information. +** +** For example, if additional arguments are needed +** for the user to identify the device communicating +** with the tuner, this argument can be used to supply +** the necessary information. +** +** The hUserData parameter is initialized in the tuner's +** Open function to NULL. +** +** See Also: MT2063_Open +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_GetUserData(Handle_t h, + Handle_t* hUserData) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status = MT2063_INV_HANDLE; + + if (hUserData == NULL) + status |= MT2063_ARG_NULL; + + if (MT2063_NO_ERROR(status)) + *hUserData = pInfo->hUserData; + + return (status); +} + + + +/****************************************************************************** +** +** Name: MT2063_SetReceiverMode +** +** Description: Set the MT2063 receiver mode +** +** --------------+---------------------------------------------- +** Mode 0 : | MT2063_CABLE_QAM +** Mode 1 : | MT2063_CABLE_ANALOG +** Mode 2 : | MT2063_OFFAIR_COFDM +** Mode 3 : | MT2063_OFFAIR_COFDM_SAWLESS +** Mode 4 : | MT2063_OFFAIR_ANALOG +** Mode 5 : | MT2063_OFFAIR_8VSB +** --------------+----+----+----+----+-----+-------------------- +** (DNC1GC & DNC2GC are the values, which are used, when the specific +** DNC Output is selected, the other is always off) +** +** |<---------- Mode -------------->| +** Reg Field | 0 | 1 | 2 | 3 | 4 | 5 | +** ------------+-----+-----+-----+-----+-----+-----+ +** RFAGCen | OFF | OFF | OFF | OFF | OFF | OFF +** LNARin | 0 | 0 | 3 | 3 | 3 | 3 +** FIFFQen | 1 | 1 | 1 | 1 | 1 | 1 +** FIFFq | 0 | 0 | 0 | 0 | 0 | 0 +** DNC1gc | 0 | 0 | 0 | 0 | 0 | 0 +** DNC2gc | 0 | 0 | 0 | 0 | 0 | 0 +** GCU Auto | 1 | 1 | 1 | 1 | 1 | 1 +** LNA max Atn | 31 | 31 | 31 | 31 | 31 | 31 +** LNA Target | 44 | 43 | 43 | 43 | 43 | 43 +** ign RF Ovl | 0 | 0 | 0 | 0 | 0 | 0 +** RF max Atn | 31 | 31 | 31 | 31 | 31 | 31 +** PD1 Target | 36 | 36 | 38 | 38 | 36 | 38 +** ign FIF Ovl | 0 | 0 | 0 | 0 | 0 | 0 +** FIF max Atn | 5 | 5 | 5 | 5 | 5 | 5 +** PD2 Target | 40 | 33 | 42 | 42 | 33 | 42 +** +** +** Parameters: pInfo - ptr to MT2063_Info_t structure +** Mode - desired reciever mode +** +** Usage: status = MT2063_SetReceiverMode(hMT2063, Mode); +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: MT2063_SetReg - Write a byte of data to a HW register. +** Assumes that the tuner cache is valid. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** N/A 01-10-2007 PINZ Added additional GCU Settings, FIFF Calib will be triggered +** 155 10-01-2007 DAD Ver 1.06: Add receiver mode for SECAM positive +** modulation +** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE) +** N/A 10-22-2007 PINZ Ver 1.07: Changed some Registers at init to have +** the same settings as with MT Launcher +** N/A 10-30-2007 PINZ Add SetParam VGAGC & VGAOI +** Add SetParam DNC_OUTPUT_ENABLE +** Removed VGAGC from receiver mode, +** default now 1 +** N/A 10-31-2007 PINZ Ver 1.08: Add SetParam TAGC, removed from rcvr-mode +** Add SetParam AMPGC, removed from rcvr-mode +** Corrected names of GCU values +** reorganized receiver modes, removed, +** (MT2063_ANALOG_TV_POS_NO_RFAGC_MODE) +** Actualized Receiver-Mode values +** N/A 11-12-2007 PINZ Ver 1.09: Actualized Receiver-Mode values +** N/A 11-27-2007 PINZ Improved buffered writing +** 01-03-2008 PINZ Ver 1.10: Added a trigger of BYPATNUP for +** correct wakeup of the LNA after shutdown +** Set AFCsd = 1 as default +** Changed CAP1sel default +** 01-14-2008 PINZ Ver 1.11: Updated gain settings +** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT +** Split SetParam up to ACLNA / ACLNA_MAX +** removed ACLNA_INRC/DECR (+RF & FIF) +** removed GCUAUTO / BYPATNDN/UP +** +******************************************************************************/ +static UData_t MT2063_SetReceiverMode(struct MT2063_Info_t* pInfo, enum MT2063_RCVR_MODES Mode) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + U8Data val; + UData_t longval; + + + if (Mode >= MT2063_NUM_RCVR_MODES) + status = MT2063_ARG_RANGE; + + /* RFAGCen */ + if (MT2063_NO_ERROR(status)) + { + val = (pInfo->reg[MT2063_REG_PD1_TGT] & (U8Data)~0x40) | (RFAGCEN[Mode] ? 0x40 : 0x00); + if( pInfo->reg[MT2063_REG_PD1_TGT] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val); + } + } + + /* LNARin */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_LNA_RIN, LNARIN[Mode]); + } + + /* FIFFQEN and FIFFQ */ + if (MT2063_NO_ERROR(status)) + { + val = (pInfo->reg[MT2063_REG_FIFF_CTRL2] & (U8Data)~0xF0) | (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4); + if( pInfo->reg[MT2063_REG_FIFF_CTRL2] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL2, val); + /* trigger FIFF calibration, needed after changing FIFFQ */ + val = (pInfo->reg[MT2063_REG_FIFF_CTRL] | (U8Data)0x01); + status |= MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val); + val = (pInfo->reg[MT2063_REG_FIFF_CTRL] & (U8Data)~0x01); + status |= MT2063_SetReg(pInfo, MT2063_REG_FIFF_CTRL, val); + } + } + + /* DNC1GC & DNC2GC */ + status |= MT2063_GetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, &longval); + status |= MT2063_SetParam(pInfo, MT2063_DNC_OUTPUT_ENABLE, longval); + + /* acLNAmax */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_ACLNA_MAX, ACLNAMAX[Mode]); + } + + /* LNATGT */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_LNA_TGT, LNATGT[Mode]); + } + + /* ACRF */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_ACRF_MAX, ACRFMAX[Mode]); + } + + /* PD1TGT */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_PD1_TGT, PD1TGT[Mode]); + } + + /* FIFATN */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_ACFIF_MAX, ACFIFMAX[Mode]); + } + + /* PD2TGT */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_SetParam(pInfo, MT2063_PD2_TGT, PD2TGT[Mode]); + } + + /* Ignore ATN Overload */ + if (MT2063_NO_ERROR(status)) + { + val = (pInfo->reg[MT2063_REG_LNA_TGT] & (U8Data)~0x80) | (RFOVDIS[Mode] ? 0x80 : 0x00); + if( pInfo->reg[MT2063_REG_LNA_TGT] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val); + } + } + + /* Ignore FIF Overload */ + if (MT2063_NO_ERROR(status)) + { + val = (pInfo->reg[MT2063_REG_PD1_TGT] & (U8Data)~0x80) | (FIFOVDIS[Mode] ? 0x80 : 0x00); + if( pInfo->reg[MT2063_REG_PD1_TGT] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val); + } + } + + if (MT2063_NO_ERROR(status)) + pInfo->rcvr_mode = Mode; + + return (status); +} + + +/****************************************************************************** +** +** Name: MT2063_ReInit +** +** Description: Initialize the tuner's register values. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** +** Returns: status: +** MT_OK - No errors +** MT_TUNER_ID_ERR - Tuner Part/Rev code mismatch +** MT_INV_HANDLE - Invalid tuner handle +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: MT_ReadSub - Read byte(s) of data from the two-wire bus +** MT_WriteSub - Write byte(s) of data to the two-wire bus +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** 148 09-04-2007 RSK Ver 1.02: Corrected logic of Reg 3B Reference +** 153 09-07-2007 RSK Ver 1.03: Lock Time improvements +** N/A 10-31-2007 PINZ Ver 1.08: Changed values suitable to rcvr-mode 0 +** N/A 11-12-2007 PINZ Ver 1.09: Changed values suitable to rcvr-mode 0 +** N/A 01-03-2007 PINZ Ver 1.10: Added AFCsd = 1 into defaults +** N/A 01-04-2007 PINZ Ver 1.10: Changed CAP1sel default +** 01-14-2008 PINZ Ver 1.11: Updated gain settings +** 03-18-2008 PINZ Ver 1.13: Added Support for B3 +** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. +** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW +** +******************************************************************************/ +UData_t MT2063_ReInit(Handle_t h) +{ + U8Data all_resets = 0xF0; /* reset/load bits */ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + U8Data *def; + + U8Data MT2063B0_defaults[] = { /* Reg, Value */ + 0x19, 0x05, + 0x1B, 0x1D, + 0x1C, 0x1F, + 0x1D, 0x0F, + 0x1E, 0x3F, + 0x1F, 0x0F, + 0x20, 0x3F, + 0x22, 0x21, + 0x23, 0x3F, + 0x24, 0x20, + 0x25, 0x3F, + 0x27, 0xEE, + 0x2C, 0x27, /* bit at 0x20 is cleared below */ + 0x30, 0x03, + 0x2C, 0x07, /* bit at 0x20 is cleared here */ + 0x2D, 0x87, + 0x2E, 0xAA, + 0x28, 0xE1, /* Set the FIFCrst bit here */ + 0x28, 0xE0, /* Clear the FIFCrst bit here */ + 0x00 }; + + /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */ + U8Data MT2063B1_defaults[] = { /* Reg, Value */ + 0x05, 0xF0, + 0x11, 0x10, /* New Enable AFCsd */ + 0x19, 0x05, + 0x1A, 0x6C, + 0x1B, 0x24, + 0x1C, 0x28, + 0x1D, 0x8F, + 0x1E, 0x14, + 0x1F, 0x8F, + 0x20, 0x57, + 0x22, 0x21, /* New - ver 1.03 */ + 0x23, 0x3C, /* New - ver 1.10 */ + 0x24, 0x20, /* New - ver 1.03 */ + 0x2C, 0x24, /* bit at 0x20 is cleared below */ + 0x2D, 0x87, /* FIFFQ=0 */ + 0x2F, 0xF3, + 0x30, 0x0C, /* New - ver 1.11 */ + 0x31, 0x1B, /* New - ver 1.11 */ + 0x2C, 0x04, /* bit at 0x20 is cleared here */ + 0x28, 0xE1, /* Set the FIFCrst bit here */ + 0x28, 0xE0, /* Clear the FIFCrst bit here */ + 0x00 }; + + /* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */ + U8Data MT2063B3_defaults[] = { /* Reg, Value */ + 0x05, 0xF0, + 0x19, 0x3D, + 0x2C, 0x24, /* bit at 0x20 is cleared below */ + 0x2C, 0x04, /* bit at 0x20 is cleared here */ + 0x28, 0xE1, /* Set the FIFCrst bit here */ + 0x28, 0xE0, /* Clear the FIFCrst bit here */ + 0x00 }; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status |= MT2063_INV_HANDLE; + + /* Read the Part/Rev code from the tuner */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_PART_REV, pInfo->reg, 1); + } + + if (MT2063_NO_ERROR(status) /* Check the part/rev code */ + && ( (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B0) /* MT2063 B0 */ + && (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B1) /* MT2063 B1 */ + && (pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3))) /* MT2063 B3 */ + status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */ + + /* Read the Part/Rev code (2nd byte) from the tuner */ + if (MT2063_NO_ERROR(status)) + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_RSVD_3B, &pInfo->reg[MT2063_REG_RSVD_3B], 1); + + if (MT2063_NO_ERROR(status) /* Check the 2nd part/rev code */ + && ((pInfo->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) /* b7 != 0 ==> NOT MT2063 */ + status |= MT2063_TUNER_ID_ERR; /* Wrong tuner Part/Rev code */ + + /* Reset the tuner */ + if (MT2063_NO_ERROR(status)) + status |= MT2063_WriteSub(pInfo->hUserData, + pInfo->address, + MT2063_REG_LO2CQ_3, + &all_resets, + 1); + + /* change all of the default values that vary from the HW reset values */ + /* def = (pInfo->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */ + switch (pInfo->reg[MT2063_REG_PART_REV]) + { + case MT2063_B3 : + def = MT2063B3_defaults; + break; + + case MT2063_B1 : + def = MT2063B1_defaults; + break; + + case MT2063_B0 : + def = MT2063B0_defaults; + break; + + default : + status |= MT2063_TUNER_ID_ERR; + break; + } + + while (MT2063_NO_ERROR(status) && *def) + { + U8Data reg = *def++; + U8Data val = *def++; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val, 1); + } + + /* Wait for FIFF location to complete. */ + if (MT2063_NO_ERROR(status)) + { + UData_t FCRUN = 1; + SData_t maxReads = 10; + while (MT2063_NO_ERROR(status) && (FCRUN != 0) && (maxReads-- > 0)) + { + MT2063_Sleep(pInfo->hUserData, 2); + status |= MT2063_ReadSub(pInfo->hUserData, + pInfo->address, + MT2063_REG_XO_STATUS, + &pInfo->reg[MT2063_REG_XO_STATUS], + 1); + FCRUN = (pInfo->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6; + } + + if (FCRUN != 0) + status |= MT2063_TUNER_INIT_ERR | MT2063_TUNER_TIMEOUT; + + if (MT2063_NO_ERROR(status)) /* Re-read FIFFC value */ + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_FIFFC, &pInfo->reg[MT2063_REG_FIFFC], 1); + } + + /* Read back all the registers from the tuner */ + if (MT2063_NO_ERROR(status)) + status |= MT2063_ReadSub(pInfo->hUserData, + pInfo->address, + MT2063_REG_PART_REV, + pInfo->reg, + MT2063_REG_END_REGS); + + if (MT2063_NO_ERROR(status)) + { + /* Initialize the tuner state. */ + pInfo->version = MT2063_VERSION; + pInfo->tuner_id = pInfo->reg[MT2063_REG_PART_REV]; + pInfo->AS_Data.f_ref = MT2063_REF_FREQ; + pInfo->AS_Data.f_if1_Center = (pInfo->AS_Data.f_ref / 8) * ((UData_t) pInfo->reg[MT2063_REG_FIFFC] + 640); + pInfo->AS_Data.f_if1_bw = MT2063_IF1_BW; + pInfo->AS_Data.f_out = 43750000UL; + pInfo->AS_Data.f_out_bw = 6750000UL; + pInfo->AS_Data.f_zif_bw = MT2063_ZIF_BW; + pInfo->AS_Data.f_LO1_Step = pInfo->AS_Data.f_ref / 64; + pInfo->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE; + pInfo->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1; + pInfo->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2; + pInfo->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP; + pInfo->AS_Data.f_if1_Request = pInfo->AS_Data.f_if1_Center; + pInfo->AS_Data.f_LO1 = 2181000000UL; + pInfo->AS_Data.f_LO2 = 1486249786UL; + pInfo->f_IF1_actual = pInfo->AS_Data.f_if1_Center; + pInfo->AS_Data.f_in = pInfo->AS_Data.f_LO1 - pInfo->f_IF1_actual; + pInfo->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID; + pInfo->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID; + pInfo->num_regs = MT2063_REG_END_REGS; + pInfo->AS_Data.avoidDECT = MT2063_AVOID_BOTH; + pInfo->ctfilt_sw = 0; + } + + if (MT2063_NO_ERROR(status)) + { + pInfo->CTFiltMax[ 0] = 69230000; + pInfo->CTFiltMax[ 1] = 105770000; + pInfo->CTFiltMax[ 2] = 140350000; + pInfo->CTFiltMax[ 3] = 177110000; + pInfo->CTFiltMax[ 4] = 212860000; + pInfo->CTFiltMax[ 5] = 241130000; + pInfo->CTFiltMax[ 6] = 274370000; + pInfo->CTFiltMax[ 7] = 309820000; + pInfo->CTFiltMax[ 8] = 342450000; + pInfo->CTFiltMax[ 9] = 378870000; + pInfo->CTFiltMax[10] = 416210000; + pInfo->CTFiltMax[11] = 456500000; + pInfo->CTFiltMax[12] = 495790000; + pInfo->CTFiltMax[13] = 534530000; + pInfo->CTFiltMax[14] = 572610000; + pInfo->CTFiltMax[15] = 598970000; + pInfo->CTFiltMax[16] = 635910000; + pInfo->CTFiltMax[17] = 672130000; + pInfo->CTFiltMax[18] = 714840000; + pInfo->CTFiltMax[19] = 739660000; + pInfo->CTFiltMax[20] = 770410000; + pInfo->CTFiltMax[21] = 814660000; + pInfo->CTFiltMax[22] = 846950000; + pInfo->CTFiltMax[23] = 867820000; + pInfo->CTFiltMax[24] = 915980000; + pInfo->CTFiltMax[25] = 947450000; + pInfo->CTFiltMax[26] = 983110000; + pInfo->CTFiltMax[27] = 1021630000; + pInfo->CTFiltMax[28] = 1061870000; + pInfo->CTFiltMax[29] = 1098330000; + pInfo->CTFiltMax[30] = 1138990000; + } + + /* + ** Fetch the FCU osc value and use it and the fRef value to + ** scale all of the Band Max values + */ + if (MT2063_NO_ERROR(status)) + { + UData_t fcu_osc; + UData_t i; + + pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x0A; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_CTUNE_CTRL, &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1); + /* Read the ClearTune filter calibration value */ + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_FIFFC, &pInfo->reg[MT2063_REG_FIFFC], 1); + fcu_osc = pInfo->reg[MT2063_REG_FIFFC]; + + pInfo->reg[MT2063_REG_CTUNE_CTRL] = 0x00; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_CTUNE_CTRL, &pInfo->reg[MT2063_REG_CTUNE_CTRL], 1); + + /* Adjust each of the values in the ClearTune filter cross-over table */ + for (i = 0; i < 31; i++) + { + pInfo->CTFiltMax[i] = (pInfo->CTFiltMax[i]/768) * (fcu_osc + 640); + } + } + + return (status); +} + + +/****************************************************************************** +** +** Name: MT2063_SetGPIO +** +** Description: Modify the MT2063 GPIO value. +** +** Parameters: h - Open handle to the tuner (from MT2063_Open). +** gpio_id - Selects GPIO0, GPIO1 or GPIO2 +** attr - Selects input readback, I/O direction or +** output value +** value - value to set GPIO pin 15, 14 or 19 +** +** Usage: status = MT2063_SetGPIO(hMT2063, MT2063_GPIO1, MT2063_GPIO_OUT, 1); +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** +** Dependencies: MT_WriteSub - Write byte(s) of data to the two-wire-bus +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +******************************************************************************/ +UData_t MT2063_SetGPIO(Handle_t h, enum MT2063_GPIO_ID gpio_id, + enum MT2063_GPIO_Attr attr, + UData_t value) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + U8Data regno; + SData_t shift; + static U8Data GPIOreg[3] = {0x15, 0x19, 0x18}; + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + if (MT2063_IsValidHandle(pInfo) == 0) + return MT2063_INV_HANDLE; + + regno = GPIOreg[attr]; + + shift = (gpio_id - MT2063_GPIO0 + 5); + + if (value & 0x01) + pInfo->reg[regno] |= (0x01 << shift); + else + pInfo->reg[regno] &= ~(0x01 << shift); + status = MT2063_WriteSub(pInfo->hUserData, pInfo->address, regno, &pInfo->reg[regno], 1); + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_SetParam +** +** Description: Sets a tuning algorithm parameter. +** +** This function provides access to the internals of the +** tuning algorithm. You can override many of the tuning +** algorithm defaults using this function. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** param - Tuning algorithm parameter +** (see enum MT2063_Param) +** nValue - value to be set +** +** param Description +** ---------------------- -------------------------------- +** MT2063_SRO_FREQ crystal frequency +** MT2063_STEPSIZE minimum tuning step size +** MT2063_LO1_FREQ LO1 frequency +** MT2063_LO1_STEPSIZE LO1 minimum step size +** MT2063_LO1_FRACN_AVOID LO1 FracN keep-out region +** MT2063_IF1_REQUEST Requested 1st IF +** MT2063_ZIF_BW zero-IF bandwidth +** MT2063_LO2_FREQ LO2 frequency +** MT2063_LO2_STEPSIZE LO2 minimum step size +** MT2063_LO2_FRACN_AVOID LO2 FracN keep-out region +** MT2063_OUTPUT_FREQ output center frequency +** MT2063_OUTPUT_BW output bandwidth +** MT2063_LO_SEPARATION min inter-tuner LO separation +** MT2063_MAX_HARM1 max # of intra-tuner harmonics +** MT2063_MAX_HARM2 max # of inter-tuner harmonics +** MT2063_RCVR_MODE Predefined modes +** MT2063_LNA_RIN Set LNA Rin (*) +** MT2063_LNA_TGT Set target power level at LNA (*) +** MT2063_PD1_TGT Set target power level at PD1 (*) +** MT2063_PD2_TGT Set target power level at PD2 (*) +** MT2063_ACLNA_MAX LNA attenuator limit (*) +** MT2063_ACRF_MAX RF attenuator limit (*) +** MT2063_ACFIF_MAX FIF attenuator limit (*) +** MT2063_DNC_OUTPUT_ENABLE DNC output selection +** MT2063_VGAGC VGA gain code +** MT2063_VGAOI VGA output current +** MT2063_TAGC TAGC setting +** MT2063_AMPGC AMP gain code +** MT2063_AVOID_DECT Avoid DECT Frequencies +** MT2063_CTFILT_SW Cleartune filter selection +** +** (*) This parameter is set by MT2063_RCVR_MODE, do not call +** additionally. +** +** Usage: status |= MT2063_SetParam(hMT2063, +** MT2063_STEPSIZE, +** 50000); +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Null pointer argument passed +** MT_ARG_RANGE - Invalid parameter requested +** or set value out of range +** or non-writable parameter +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** See Also: MT2063_GetParam, MT2063_Open +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** 154 09-13-2007 RSK Ver 1.05: Get/SetParam changes for LOx_FREQ +** 10-31-2007 PINZ Ver 1.08: Get/SetParam add VGAGC, VGAOI, AMPGC, TAGC +** 04-18-2008 PINZ Ver 1.15: Add SetParam LNARIN & PDxTGT +** Split SetParam up to ACLNA / ACLNA_MAX +** removed ACLNA_INRC/DECR (+RF & FIF) +** removed GCUAUTO / BYPATNDN/UP +** 175 I 06-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs. +** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. +** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW +** +****************************************************************************/ +UData_t MT2063_SetParam(Handle_t h, + enum MT2063_Param param, + UData_t nValue) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + U8Data val=0; + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status |= MT2063_INV_HANDLE; + + if (MT2063_NO_ERROR(status)) + { + switch (param) + { + /* crystal frequency */ + case MT2063_SRO_FREQ: + pInfo->AS_Data.f_ref = nValue; + pInfo->AS_Data.f_LO1_FracN_Avoid = 0; + pInfo->AS_Data.f_LO2_FracN_Avoid = nValue / 80 - 1; + pInfo->AS_Data.f_LO1_Step = nValue / 64; + pInfo->AS_Data.f_if1_Center = (pInfo->AS_Data.f_ref / 8) * (pInfo->reg[MT2063_REG_FIFFC] + 640); + break; + + /* minimum tuning step size */ + case MT2063_STEPSIZE: + pInfo->AS_Data.f_LO2_Step = nValue; + break; + + + /* LO1 frequency */ + case MT2063_LO1_FREQ: + { + /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */ + /* Capture the Divider and Numerator portions of other LO */ + U8Data tempLO2CQ[3]; + U8Data tempLO2C[3]; + U8Data tmpOneShot; + UData_t Div, FracN; + U8Data restore = 0; + + /* Buffer the queue for restoration later and get actual LO2 values. */ + status |= MT2063_ReadSub (pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_1, &(tempLO2CQ[0]), 3); + status |= MT2063_ReadSub (pInfo->hUserData, pInfo->address, MT2063_REG_LO2C_1, &(tempLO2C[0]), 3); + + /* clear the one-shot bits */ + tempLO2CQ[2] = tempLO2CQ[2] & 0x0F; + tempLO2C[2] = tempLO2C[2] & 0x0F; + + /* only write the queue values if they are different from the actual. */ + if( ( tempLO2CQ[0] != tempLO2C[0] ) || + ( tempLO2CQ[1] != tempLO2C[1] ) || + ( tempLO2CQ[2] != tempLO2C[2] ) ) + { + /* put actual LO2 value into queue (with 0 in one-shot bits) */ + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_1, &(tempLO2C[0]), 3); + + if( status == MT2063_OK ) + { + /* cache the bytes just written. */ + pInfo->reg[MT2063_REG_LO2CQ_1] = tempLO2C[0]; + pInfo->reg[MT2063_REG_LO2CQ_2] = tempLO2C[1]; + pInfo->reg[MT2063_REG_LO2CQ_3] = tempLO2C[2]; + } + restore = 1; + } + + /* Calculate the Divider and Numberator components of LO1 */ + status = MT2063_CalcLO1Mult(&Div, &FracN, nValue, pInfo->AS_Data.f_ref/64, pInfo->AS_Data.f_ref); + pInfo->reg[MT2063_REG_LO1CQ_1] = (U8Data)(Div & 0x00FF); + pInfo->reg[MT2063_REG_LO1CQ_2] = (U8Data)(FracN); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 2); + + /* set the one-shot bit to load the pair of LO values */ + tmpOneShot = tempLO2CQ[2] | 0xE0; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &tmpOneShot, 1); + + /* only restore the queue values if they were different from the actual. */ + if( restore ) + { + /* put actual LO2 value into queue (0 in one-shot bits) */ + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_1, &(tempLO2CQ[0]), 3); + + /* cache the bytes just written. */ + pInfo->reg[MT2063_REG_LO2CQ_1] = tempLO2CQ[0]; + pInfo->reg[MT2063_REG_LO2CQ_2] = tempLO2CQ[1]; + pInfo->reg[MT2063_REG_LO2CQ_3] = tempLO2CQ[2]; + } + + MT2063_GetParam( pInfo->hUserData, MT2063_LO1_FREQ, &pInfo->AS_Data.f_LO1 ); + } + break; + + /* LO1 minimum step size */ + case MT2063_LO1_STEPSIZE: + pInfo->AS_Data.f_LO1_Step = nValue; + break; + + /* LO1 FracN keep-out region */ + case MT2063_LO1_FRACN_AVOID_PARAM: + pInfo->AS_Data.f_LO1_FracN_Avoid = nValue; + break; + + /* Requested 1st IF */ + case MT2063_IF1_REQUEST: + pInfo->AS_Data.f_if1_Request = nValue; + break; + + /* zero-IF bandwidth */ + case MT2063_ZIF_BW: + pInfo->AS_Data.f_zif_bw = nValue; + break; + + /* LO2 frequency */ + case MT2063_LO2_FREQ: + { + /* Note: LO1 and LO2 are BOTH written at toggle of LDLOos */ + /* Capture the Divider and Numerator portions of other LO */ + U8Data tempLO1CQ[2]; + U8Data tempLO1C[2]; + UData_t Div2; + UData_t FracN2; + U8Data tmpOneShot; + U8Data restore = 0; + + /* Buffer the queue for restoration later and get actual LO2 values. */ + status |= MT2063_ReadSub (pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &(tempLO1CQ[0]), 2); + status |= MT2063_ReadSub (pInfo->hUserData, pInfo->address, MT2063_REG_LO1C_1, &(tempLO1C[0]), 2); + + /* only write the queue values if they are different from the actual. */ + if( (tempLO1CQ[0] != tempLO1C[0]) || (tempLO1CQ[1] != tempLO1C[1]) ) + { + /* put actual LO1 value into queue */ + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &(tempLO1C[0]), 2); + + /* cache the bytes just written. */ + pInfo->reg[MT2063_REG_LO1CQ_1] = tempLO1C[0]; + pInfo->reg[MT2063_REG_LO1CQ_2] = tempLO1C[1]; + restore = 1; + } + + /* Calculate the Divider and Numberator components of LO2 */ + status = MT2063_CalcLO2Mult(&Div2, &FracN2, nValue, pInfo->AS_Data.f_ref/8191, pInfo->AS_Data.f_ref); + pInfo->reg[MT2063_REG_LO2CQ_1] = (U8Data)((Div2 << 1) | ((FracN2 >> 12) & 0x01) ) & 0xFF; + pInfo->reg[MT2063_REG_LO2CQ_2] = (U8Data)((FracN2 >> 4) & 0xFF); + pInfo->reg[MT2063_REG_LO2CQ_3] = (U8Data)((FracN2 & 0x0F) ); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 3); + + /* set the one-shot bit to load the LO values */ + tmpOneShot = pInfo->reg[MT2063_REG_LO2CQ_3] | 0xE0; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &tmpOneShot, 1); + + /* only restore LO1 queue value if they were different from the actual. */ + if( restore ) + { + /* put previous LO1 queue value back into queue */ + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &(tempLO1CQ[0]), 2); + + /* cache the bytes just written. */ + pInfo->reg[MT2063_REG_LO1CQ_1] = tempLO1CQ[0]; + pInfo->reg[MT2063_REG_LO1CQ_2] = tempLO1CQ[1]; + } + + MT2063_GetParam( pInfo->hUserData, MT2063_LO2_FREQ, &pInfo->AS_Data.f_LO2 ); + } + break; + + /* LO2 minimum step size */ + case MT2063_LO2_STEPSIZE: + pInfo->AS_Data.f_LO2_Step = nValue; + break; + + /* LO2 FracN keep-out region */ + case MT2063_LO2_FRACN_AVOID: + pInfo->AS_Data.f_LO2_FracN_Avoid = nValue; + break; + + /* output center frequency */ + case MT2063_OUTPUT_FREQ: + pInfo->AS_Data.f_out = nValue; + break; + + /* output bandwidth */ + case MT2063_OUTPUT_BW: + pInfo->AS_Data.f_out_bw = nValue + 750000; + break; + + /* min inter-tuner LO separation */ + case MT2063_LO_SEPARATION: + pInfo->AS_Data.f_min_LO_Separation = nValue; + break; + + /* max # of intra-tuner harmonics */ + case MT2063_MAX_HARM1: + pInfo->AS_Data.maxH1 = nValue; + break; + + /* max # of inter-tuner harmonics */ + case MT2063_MAX_HARM2: + pInfo->AS_Data.maxH2 = nValue; + break; + + case MT2063_RCVR_MODE: + status |= MT2063_SetReceiverMode(pInfo, (enum MT2063_RCVR_MODES)nValue); + break; + + /* Set LNA Rin -- nValue is desired value */ + case MT2063_LNA_RIN: + val = ( pInfo->reg[MT2063_REG_CTRL_2C] & (U8Data)~0x03) | (nValue & 0x03); + if( pInfo->reg[MT2063_REG_CTRL_2C] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_CTRL_2C, val); + } + break; + + /* Set target power level at LNA -- nValue is desired value */ + case MT2063_LNA_TGT: + val = ( pInfo->reg[MT2063_REG_LNA_TGT] & (U8Data)~0x3F) | (nValue & 0x3F); + if( pInfo->reg[MT2063_REG_LNA_TGT] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_TGT, val); + } + break; + + /* Set target power level at PD1 -- nValue is desired value */ + case MT2063_PD1_TGT: + val = ( pInfo->reg[MT2063_REG_PD1_TGT] & (U8Data)~0x3F) | (nValue & 0x3F); + if( pInfo->reg[MT2063_REG_PD1_TGT] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_PD1_TGT, val); + } + break; + + /* Set target power level at PD2 -- nValue is desired value */ + case MT2063_PD2_TGT: + val = ( pInfo->reg[MT2063_REG_PD2_TGT] & (U8Data)~0x3F) | (nValue & 0x3F); + if( pInfo->reg[MT2063_REG_PD2_TGT] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_PD2_TGT, val); + } + break; + + /* Set LNA atten limit -- nValue is desired value */ + case MT2063_ACLNA_MAX: + val = ( pInfo->reg[MT2063_REG_LNA_OV] & (U8Data)~0x1F) | (nValue & 0x1F); + if( pInfo->reg[MT2063_REG_LNA_OV] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_LNA_OV, val); + } + break; + + /* Set RF atten limit -- nValue is desired value */ + case MT2063_ACRF_MAX: + val = ( pInfo->reg[MT2063_REG_RF_OV] & (U8Data)~0x1F) | (nValue & 0x1F); + if( pInfo->reg[MT2063_REG_RF_OV] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_RF_OV, val); + } + break; + + /* Set FIF atten limit -- nValue is desired value, max. 5 if no B3 */ + case MT2063_ACFIF_MAX: + if ( pInfo->reg[MT2063_REG_PART_REV] != MT2063_B3 && nValue > 5) + nValue = 5; + val = ( pInfo->reg[MT2063_REG_FIF_OV] & (U8Data)~0x1F) | (nValue & 0x1F); + if( pInfo->reg[MT2063_REG_FIF_OV] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_FIF_OV, val); + } + break; + + case MT2063_DNC_OUTPUT_ENABLE: + /* selects, which DNC output is used */ + switch ((enum MT2063_DNC_Output_Enable)nValue) + { + case MT2063_DNC_NONE : + { + val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC ) | 0x03; /* Set DNC1GC=3 */ + if (pInfo->reg[MT2063_REG_DNC_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_DNC_GAIN, val); + + val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC ) | 0x03; /* Set DNC2GC=3 */ + if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_VGA_GAIN, val); + + val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */ + if (pInfo->reg[MT2063_REG_RSVD_20] != val) + status |= MT2063_SetReg(h, MT2063_REG_RSVD_20, val); + + break; + } + case MT2063_DNC_1 : + { + val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC ) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */ + if (pInfo->reg[MT2063_REG_DNC_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_DNC_GAIN, val); + + val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC ) | 0x03; /* Set DNC2GC=3 */ + if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_VGA_GAIN, val); + + val = (pInfo->reg[MT2063_REG_RSVD_20] & ~0x40); /* Set PD2MUX=0 */ + if (pInfo->reg[MT2063_REG_RSVD_20] != val) + status |= MT2063_SetReg(h, MT2063_REG_RSVD_20, val); + + break; + } + case MT2063_DNC_2 : + { + val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC ) | 0x03; /* Set DNC1GC=3 */ + if (pInfo->reg[MT2063_REG_DNC_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_DNC_GAIN, val); + + val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC ) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */ + if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_VGA_GAIN, val); + + val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */ + if (pInfo->reg[MT2063_REG_RSVD_20] != val) + status |= MT2063_SetReg(h, MT2063_REG_RSVD_20, val); + + break; + } + case MT2063_DNC_BOTH : + { + val = (pInfo->reg[MT2063_REG_DNC_GAIN] & 0xFC ) | (DNC1GC[pInfo->rcvr_mode] & 0x03); /* Set DNC1GC=x */ + if (pInfo->reg[MT2063_REG_DNC_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_DNC_GAIN, val); + + val = (pInfo->reg[MT2063_REG_VGA_GAIN] & 0xFC ) | (DNC2GC[pInfo->rcvr_mode] & 0x03); /* Set DNC2GC=x */ + if (pInfo->reg[MT2063_REG_VGA_GAIN] != val) + status |= MT2063_SetReg(h, MT2063_REG_VGA_GAIN, val); + + val = (pInfo->reg[MT2063_REG_RSVD_20] | 0x40); /* Set PD2MUX=1 */ + if (pInfo->reg[MT2063_REG_RSVD_20] != val) + status |= MT2063_SetReg(h, MT2063_REG_RSVD_20, val); + + break; + } + default : break; + } + break; + + case MT2063_VGAGC: + /* Set VGA gain code */ + val = (pInfo->reg[MT2063_REG_VGA_GAIN] & (U8Data)~0x0C) | ( (nValue & 0x03) << 2); + if( pInfo->reg[MT2063_REG_VGA_GAIN] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_VGA_GAIN, val); + } + break; + + case MT2063_VGAOI: + /* Set VGA bias current */ + val = (pInfo->reg[MT2063_REG_RSVD_31] & (U8Data)~0x07) | (nValue & 0x07); + if( pInfo->reg[MT2063_REG_RSVD_31] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_RSVD_31, val); + } + break; + + case MT2063_TAGC: + /* Set TAGC */ + val = (pInfo->reg[MT2063_REG_RSVD_1E] & (U8Data)~0x03) | (nValue & 0x03); + if( pInfo->reg[MT2063_REG_RSVD_1E] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_RSVD_1E, val); + } + break; + + case MT2063_AMPGC: + /* Set Amp gain code */ + val = (pInfo->reg[MT2063_REG_TEMP_SEL] & (U8Data)~0x03) | (nValue & 0x03); + if( pInfo->reg[MT2063_REG_TEMP_SEL] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_TEMP_SEL, val); + } + break; + + /* Avoid DECT Frequencies */ + case MT2063_AVOID_DECT: + { + enum MT2063_DECT_Avoid_Type newAvoidSetting = (enum MT2063_DECT_Avoid_Type) nValue; + if( (newAvoidSetting >= MT2063_NO_DECT_AVOIDANCE) && (newAvoidSetting <= MT2063_AVOID_BOTH) ) + { + pInfo->AS_Data.avoidDECT = newAvoidSetting; + } + } + break; + + /* Cleartune filter selection: 0 - by IC (default), 1 - by software */ + case MT2063_CTFILT_SW: + pInfo->ctfilt_sw = (nValue & 0x01); + break; + + /* These parameters are read-only */ + case MT2063_IC_ADDR: + case MT2063_MAX_OPEN: + case MT2063_NUM_OPEN: + case MT2063_INPUT_FREQ: + case MT2063_IF1_ACTUAL: + case MT2063_IF1_CENTER: + case MT2063_IF1_BW: + case MT2063_AS_ALG: + case MT2063_EXCL_ZONES: + case MT2063_SPUR_AVOIDED: + case MT2063_NUM_SPURS: + case MT2063_SPUR_PRESENT: + case MT2063_ACLNA: + case MT2063_ACRF: + case MT2063_ACFIF: + case MT2063_EOP: + default: + status |= MT2063_ARG_RANGE; + } + } + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_SetPowerMaskBits +** +** Description: Sets the power-down mask bits for various sections of +** the MT2063 +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** Bits - Mask bits to be set. +** +** See definition of MT2063_Mask_Bits type for description +** of each of the power bits. +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_SetPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits Bits) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status = MT2063_INV_HANDLE; + else + { + Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */ + if ((Bits & 0xFF00) != 0) + { + pInfo->reg[MT2063_REG_PWR_2] |= (U8Data)((Bits & 0xFF00) >> 8); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_2, &pInfo->reg[MT2063_REG_PWR_2], 1); + } + if ((Bits & 0xFF) != 0) + { + pInfo->reg[MT2063_REG_PWR_1] |= ((U8Data)Bits & 0xFF); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_1, &pInfo->reg[MT2063_REG_PWR_1], 1); + } + } + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_ClearPowerMaskBits +** +** Description: Clears the power-down mask bits for various sections of +** the MT2063 +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** Bits - Mask bits to be cleared. +** +** See definition of MT2063_Mask_Bits type for description +** of each of the power bits. +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_ClearPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits Bits) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status = MT2063_INV_HANDLE; + else + { + Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */ + if ((Bits & 0xFF00) != 0) + { + pInfo->reg[MT2063_REG_PWR_2] &= ~(U8Data)(Bits >> 8); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_2, &pInfo->reg[MT2063_REG_PWR_2], 1); + } + if ((Bits & 0xFF) != 0) + { + pInfo->reg[MT2063_REG_PWR_1] &= ~(U8Data)(Bits & 0xFF); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_1, &pInfo->reg[MT2063_REG_PWR_1], 1); + } + } + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_GetPowerMaskBits +** +** Description: Returns a mask of the enabled power shutdown bits +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** Bits - Mask bits to currently set. +** +** See definition of MT2063_Mask_Bits type for description +** of each of the power bits. +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_NULL - Output argument is NULL +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_GetPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits *Bits) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status = MT2063_INV_HANDLE; + else + { + if (Bits == NULL) + status |= MT2063_ARG_NULL; + + if (MT2063_NO_ERROR(status)) + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_1, &pInfo->reg[MT2063_REG_PWR_1], 2); + + if (MT2063_NO_ERROR(status)) + { + *Bits = (enum MT2063_Mask_Bits)(((SData_t)pInfo->reg[MT2063_REG_PWR_2] << 8) + pInfo->reg[MT2063_REG_PWR_1]); + *Bits = (enum MT2063_Mask_Bits)(*Bits & MT2063_ALL_SD); /* Only valid bits for this tuner */ + } + } + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_EnableExternalShutdown +** +** Description: Enables or disables the operation of the external +** shutdown pin +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** Enabled - 0 = disable the pin, otherwise enable it +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_EnableExternalShutdown(Handle_t h, U8Data Enabled) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status = MT2063_INV_HANDLE; + else + { + if (Enabled == 0) + pInfo->reg[MT2063_REG_PWR_1] &= ~0x08; /* Turn off the bit */ + else + pInfo->reg[MT2063_REG_PWR_1] |= 0x08; /* Turn the bit on */ + + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_1, &pInfo->reg[MT2063_REG_PWR_1], 1); + } + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_SoftwareShutdown +** +** Description: Enables or disables software shutdown function. When +** Shutdown==1, any section whose power mask is set will be +** shutdown. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** Shutdown - 1 = shutdown the masked sections, otherwise +** power all sections on +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_COMM_ERR - Serial bus communications error +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** 01-03-2008 PINZ Ver 1.xx: Added a trigger of BYPATNUP for +** correct wakeup of the LNA +** +****************************************************************************/ +UData_t MT2063_SoftwareShutdown(Handle_t h, U8Data Shutdown) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + { + status = MT2063_INV_HANDLE; + } + else + { + if (Shutdown == 1) + pInfo->reg[MT2063_REG_PWR_1] |= 0x04; /* Turn the bit on */ + else + pInfo->reg[MT2063_REG_PWR_1] &= ~0x04; /* Turn off the bit */ + + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_PWR_1, &pInfo->reg[MT2063_REG_PWR_1], 1); + + if (Shutdown != 1) + { + pInfo->reg[MT2063_REG_BYP_CTRL] = (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_BYP_CTRL, &pInfo->reg[MT2063_REG_BYP_CTRL], 1); + pInfo->reg[MT2063_REG_BYP_CTRL] = (pInfo->reg[MT2063_REG_BYP_CTRL] & 0x9F); + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_BYP_CTRL, &pInfo->reg[MT2063_REG_BYP_CTRL], 1); + } + } + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_SetExtSRO +** +** Description: Sets the external SRO driver. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** Ext_SRO_Setting - external SRO drive setting +** +** (default) MT2063_EXT_SRO_OFF - ext driver off +** MT2063_EXT_SRO_BY_1 - ext driver = SRO frequency +** MT2063_EXT_SRO_BY_2 - ext driver = SRO/2 frequency +** MT2063_EXT_SRO_BY_4 - ext driver = SRO/4 frequency +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** The Ext_SRO_Setting settings default to OFF +** Use this function if you need to override the default +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** 189 S 05-13-2008 RSK Ver 1.16: Correct location for ExtSRO control. +** +****************************************************************************/ +UData_t MT2063_SetExtSRO(Handle_t h, + enum MT2063_Ext_SRO Ext_SRO_Setting) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status = MT2063_INV_HANDLE; + else + { + pInfo->reg[MT2063_REG_CTRL_2C] = (pInfo->reg[MT2063_REG_CTRL_2C] & 0x3F) | ((U8Data)Ext_SRO_Setting << 6); + status = MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_CTRL_2C, &pInfo->reg[MT2063_REG_CTRL_2C], 1); + } + + return (status); +} + + +/**************************************************************************** +** +** Name: MT2063_SetReg +** +** Description: Sets an MT2063 register. +** +** Parameters: h - Tuner handle (returned by MT2063_Open) +** reg - MT2063 register/subaddress location +** val - MT2063 register/subaddress value +** +** Returns: status: +** MT_OK - No errors +** MT_COMM_ERR - Serial bus communications error +** MT_INV_HANDLE - Invalid tuner handle +** MT_ARG_RANGE - Argument out of range +** +** Dependencies: USERS MUST CALL MT2063_Open() FIRST! +** +** Use this function if you need to override a default +** register value +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +UData_t MT2063_SetReg(Handle_t h, + U8Data reg, + U8Data val) +{ + UData_t status = MT2063_OK; /* Status to be returned */ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + status |= MT2063_INV_HANDLE; + + if (reg >= MT2063_REG_END_REGS) + status |= MT2063_ARG_RANGE; + + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, reg, &val, 1); + if (MT2063_NO_ERROR(status)) + pInfo->reg[reg] = val; + } + + return (status); +} + + +static UData_t MT2063_Round_fLO(UData_t f_LO, UData_t f_LO_Step, UData_t f_ref) +{ + return f_ref * (f_LO / f_ref) + + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step); +} + + +/**************************************************************************** +** +** Name: fLO_FractionalTerm +** +** Description: Calculates the portion contributed by FracN / denom. +** +** This function preserves maximum precision without +** risk of overflow. It accurately calculates +** f_ref * num / denom to within 1 HZ with fixed math. +** +** Parameters: num - Fractional portion of the multiplier +** denom - denominator portion of the ratio +** This routine successfully handles denom values +** up to and including 2^18. +** f_Ref - SRO frequency. This calculation handles +** f_ref as two separate 14-bit fields. +** Therefore, a maximum value of 2^28-1 +** may safely be used for f_ref. This is +** the genesis of the magic number "14" and the +** magic mask value of 0x03FFF. +** +** Returns: f_ref * num / denom +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +static UData_t MT2063_fLO_FractionalTerm( UData_t f_ref, + UData_t num, + UData_t denom ) +{ + UData_t t1 = (f_ref >> 14) * num; + UData_t term1 = t1 / denom; + UData_t loss = t1 % denom; + UData_t term2 = ( ((f_ref & 0x00003FFF) * num + (loss<<14)) + (denom/2) ) / denom; + return ((term1 << 14) + term2); +} + + +/**************************************************************************** +** +** Name: CalcLO1Mult +** +** Description: Calculates Integer divider value and the numerator +** value for a FracN PLL. +** +** This function assumes that the f_LO and f_Ref are +** evenly divisible by f_LO_Step. +** +** Parameters: Div - OUTPUT: Whole number portion of the multiplier +** FracN - OUTPUT: Fractional portion of the multiplier +** f_LO - desired LO frequency. +** f_LO_Step - Minimum step size for the LO (in Hz). +** f_Ref - SRO frequency. +** f_Avoid - Range of PLL frequencies to avoid near +** integer multiples of f_Ref (in Hz). +** +** Returns: Recalculated LO frequency. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +static UData_t MT2063_CalcLO1Mult(UData_t *Div, + UData_t *FracN, + UData_t f_LO, + UData_t f_LO_Step, + UData_t f_Ref) +{ + /* Calculate the whole number portion of the divider */ + *Div = f_LO / f_Ref; + + /* Calculate the numerator value (round to nearest f_LO_Step) */ + *FracN = (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) + (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step); + + return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm( f_Ref, *FracN, 64 ); +} + + +/**************************************************************************** +** +** Name: CalcLO2Mult +** +** Description: Calculates Integer divider value and the numerator +** value for a FracN PLL. +** +** This function assumes that the f_LO and f_Ref are +** evenly divisible by f_LO_Step. +** +** Parameters: Div - OUTPUT: Whole number portion of the multiplier +** FracN - OUTPUT: Fractional portion of the multiplier +** f_LO - desired LO frequency. +** f_LO_Step - Minimum step size for the LO (in Hz). +** f_Ref - SRO frequency. +** f_Avoid - Range of PLL frequencies to avoid near +** integer multiples of f_Ref (in Hz). +** +** Returns: Recalculated LO frequency. +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** +****************************************************************************/ +static UData_t MT2063_CalcLO2Mult(UData_t *Div, + UData_t *FracN, + UData_t f_LO, + UData_t f_LO_Step, + UData_t f_Ref) +{ + /* Calculate the whole number portion of the divider */ + *Div = f_LO / f_Ref; + + /* Calculate the numerator value (round to nearest f_LO_Step) */ + *FracN = (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) + (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step); + + return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm( f_Ref, *FracN, 8191 ); +} + +/**************************************************************************** +** +** Name: FindClearTuneFilter +** +** Description: Calculate the corrrect ClearTune filter to be used for +** a given input frequency. +** +** Parameters: pInfo - ptr to tuner data structure +** f_in - RF input center frequency (in Hz). +** +** Returns: ClearTune filter number (0-31) +** +** Dependencies: MUST CALL MT2064_Open BEFORE FindClearTuneFilter! +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 04-10-2008 PINZ Ver 1.14: Use software-controlled ClearTune +** cross-over frequency values. +** +****************************************************************************/ +static UData_t FindClearTuneFilter(struct MT2063_Info_t* pInfo, UData_t f_in) +{ + UData_t RFBand; + UData_t idx; /* index loop */ + + /* + ** Find RF Band setting + */ + RFBand = 31; /* def when f_in > all */ + for (idx=0; idx<31; ++idx) + { + if (pInfo->CTFiltMax[idx] >= f_in) + { + RFBand = idx; + break; + } + } + return (RFBand); +} + + + +/**************************************************************************** +** +** Name: MT2063_Tune +** +** Description: Change the tuner's tuned frequency to RFin. +** +** Parameters: h - Open handle to the tuner (from MT2063_Open). +** f_in - RF input center frequency (in Hz). +** +** Returns: status: +** MT_OK - No errors +** MT_INV_HANDLE - Invalid tuner handle +** MT_UPC_UNLOCK - Upconverter PLL unlocked +** MT_DNC_UNLOCK - Downconverter PLL unlocked +** MT_COMM_ERR - Serial bus communications error +** MT_SPUR_CNT_MASK - Count of avoided LO spurs +** MT_SPUR_PRESENT - LO spur possible in output +** MT_FIN_RANGE - Input freq out of range +** MT_FOUT_RANGE - Output freq out of range +** MT_UPC_RANGE - Upconverter freq out of range +** MT_DNC_RANGE - Downconverter freq out of range +** +** Dependencies: MUST CALL MT2063_Open BEFORE MT2063_Tune! +** +** MT_ReadSub - Read data from the two-wire serial bus +** MT_WriteSub - Write data to the two-wire serial bus +** MT_Sleep - Delay execution for x milliseconds +** MT2063_GetLocked - Checks to see if LO1 and LO2 are locked +** +** Revision History: +** +** SCR Date Author Description +** ------------------------------------------------------------------------- +** 138 06-19-2007 DAD Ver 1.00: Initial, derived from mt2067_b. +** 04-10-2008 PINZ Ver 1.05: Use software-controlled ClearTune +** cross-over frequency values. +** 175 I 16-06-2008 PINZ Ver 1.16: Add control to avoid US DECT freqs. +** 175 I 06-19-2008 RSK Ver 1.17: Refactor DECT control to SpurAvoid. +** 06-24-2008 PINZ Ver 1.18: Add Get/SetParam CTFILT_SW +** +****************************************************************************/ +UData_t MT2063_Tune(Handle_t h, + UData_t f_in) /* RF input center frequency */ +{ + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + + UData_t status = MT2063_OK; /* status of operation */ + UData_t LO1; /* 1st LO register value */ + UData_t Num1; /* Numerator for LO1 reg. value */ + UData_t f_IF1; /* 1st IF requested */ + UData_t LO2; /* 2nd LO register value */ + UData_t Num2; /* Numerator for LO2 reg. value */ + UData_t ofLO1, ofLO2; /* last time's LO frequencies */ + UData_t ofin, ofout; /* last time's I/O frequencies */ + U8Data fiffc = 0x80; /* FIFF center freq from tuner */ + UData_t fiffof; /* Offset from FIFF center freq */ + const U8Data LO1LK = 0x80; /* Mask for LO1 Lock bit */ + U8Data LO2LK = 0x08; /* Mask for LO2 Lock bit */ + U8Data val; + UData_t RFBand; + + /* Verify that the handle passed points to a valid tuner */ + if (MT2063_IsValidHandle(pInfo) == 0) + return MT2063_INV_HANDLE; + + /* Check the input and output frequency ranges */ + if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ)) + status |= MT2063_FIN_RANGE; + + if ((pInfo->AS_Data.f_out < MT2063_MIN_FOUT_FREQ) || (pInfo->AS_Data.f_out > MT2063_MAX_FOUT_FREQ)) + status |= MT2063_FOUT_RANGE; + + /* + ** Save original LO1 and LO2 register values + */ + ofLO1 = pInfo->AS_Data.f_LO1; + ofLO2 = pInfo->AS_Data.f_LO2; + ofin = pInfo->AS_Data.f_in; + ofout = pInfo->AS_Data.f_out; + + /* + ** Find and set RF Band setting + */ + if (pInfo->ctfilt_sw == 1) + { + val = ( pInfo->reg[MT2063_REG_CTUNE_CTRL] | 0x08 ); + if( pInfo->reg[MT2063_REG_CTUNE_CTRL] != val ) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_CTUNE_CTRL, val); + } + val = pInfo->reg[MT2063_REG_CTUNE_OV]; + RFBand = FindClearTuneFilter(pInfo, f_in); + pInfo->reg[MT2063_REG_CTUNE_OV] = (U8Data)((pInfo->reg[MT2063_REG_CTUNE_OV] & ~0x1F) + | RFBand); + if (pInfo->reg[MT2063_REG_CTUNE_OV] != val) + { + status |= MT2063_SetReg(pInfo, MT2063_REG_CTUNE_OV, val); + } + } + + /* + ** Read the FIFF Center Frequency from the tuner + */ + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_ReadSub(pInfo->hUserData, pInfo->address, MT2063_REG_FIFFC, &pInfo->reg[MT2063_REG_FIFFC], 1); + fiffc = pInfo->reg[MT2063_REG_FIFFC]; + } + /* + ** Assign in the requested values + */ + pInfo->AS_Data.f_in = f_in; + /* Request a 1st IF such that LO1 is on a step size */ + pInfo->AS_Data.f_if1_Request = MT2063_Round_fLO(pInfo->AS_Data.f_if1_Request + f_in, pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref) - f_in; + + /* + ** Calculate frequency settings. f_IF1_FREQ + f_in is the + ** desired LO1 frequency + */ + MT2063_ResetExclZones(&pInfo->AS_Data); + + f_IF1 = MT2063_ChooseFirstIF(&pInfo->AS_Data); + + pInfo->AS_Data.f_LO1 = MT2063_Round_fLO(f_IF1 + f_in, pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref); + + pInfo->AS_Data.f_LO2 = MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in, pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref); + + /* + ** Check for any LO spurs in the output bandwidth and adjust + ** the LO settings to avoid them if needed + */ + status |= MT2063_AvoidSpurs(h, &pInfo->AS_Data); + /* + ** MT_AvoidSpurs spurs may have changed the LO1 & LO2 values. + ** Recalculate the LO frequencies and the values to be placed + ** in the tuning registers. + */ + pInfo->AS_Data.f_LO1 = MT2063_CalcLO1Mult(&LO1, &Num1, pInfo->AS_Data.f_LO1, pInfo->AS_Data.f_LO1_Step, pInfo->AS_Data.f_ref); + pInfo->AS_Data.f_LO2 = MT2063_Round_fLO(pInfo->AS_Data.f_LO1 - pInfo->AS_Data.f_out - f_in, pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref); + pInfo->AS_Data.f_LO2 = MT2063_CalcLO2Mult(&LO2, &Num2, pInfo->AS_Data.f_LO2, pInfo->AS_Data.f_LO2_Step, pInfo->AS_Data.f_ref); + + + /* + ** Check the upconverter and downconverter frequency ranges + */ + if ((pInfo->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ) || (pInfo->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ)) + status |= MT2063_UPC_RANGE; + if ((pInfo->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ) || (pInfo->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ)) + status |= MT2063_DNC_RANGE; + /* LO2 Lock bit was in a different place for B0 version */ + if (pInfo->tuner_id == MT2063_B0) + LO2LK = 0x40; + + /* + ** If we have the same LO frequencies and we're already locked, + ** then skip re-programming the LO registers. + */ + if ((ofLO1 != pInfo->AS_Data.f_LO1) + || (ofLO2 != pInfo->AS_Data.f_LO2) + || ((pInfo->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) != (LO1LK | LO2LK))) + { + /* + ** Calculate the FIFFOF register value + ** + ** IF1_Actual + ** FIFFOF = ------------ - 8 * FIFFC - 4992 + ** f_ref/64 + */ + fiffof = (pInfo->AS_Data.f_LO1 - f_in) / (pInfo->AS_Data.f_ref / 64) - 8 * (UData_t)fiffc - 4992; + if (fiffof > 0xFF) + fiffof = 0xFF; + + /* + ** Place all of the calculated values into the local tuner + ** register fields. + */ + if (MT2063_NO_ERROR(status)) + { + pInfo->reg[MT2063_REG_LO1CQ_1] = (U8Data)(LO1 & 0xFF); /* DIV1q */ + pInfo->reg[MT2063_REG_LO1CQ_2] = (U8Data)(Num1 & 0x3F); /* NUM1q */ + pInfo->reg[MT2063_REG_LO2CQ_1] = (U8Data)(((LO2 & 0x7F) << 1) /* DIV2q */ + | (Num2 >> 12)); /* NUM2q (hi) */ + pInfo->reg[MT2063_REG_LO2CQ_2] = (U8Data)((Num2 & 0x0FF0) >> 4); /* NUM2q (mid) */ + pInfo->reg[MT2063_REG_LO2CQ_3] = (U8Data)(0xE0 | (Num2 & 0x000F)); /* NUM2q (lo) */ + + /* + ** Now write out the computed register values + ** IMPORTANT: There is a required order for writing + ** (0x05 must follow all the others). + */ + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO1CQ_1, &pInfo->reg[MT2063_REG_LO1CQ_1], 5); /* 0x01 - 0x05 */ + if (pInfo->tuner_id == MT2063_B0) + { + /* Re-write the one-shot bits to trigger the tune operation */ + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_LO2CQ_3, &pInfo->reg[MT2063_REG_LO2CQ_3], 1); /* 0x05 */ + } + /* Write out the FIFF offset only if it's changing */ + if (pInfo->reg[MT2063_REG_FIFF_OFFSET] != (U8Data)fiffof) + { + pInfo->reg[MT2063_REG_FIFF_OFFSET] = (U8Data)fiffof; + status |= MT2063_WriteSub(pInfo->hUserData, pInfo->address, MT2063_REG_FIFF_OFFSET, &pInfo->reg[MT2063_REG_FIFF_OFFSET], 1); + } + } + + /* + ** Check for LO's locking + */ + + + if (MT2063_NO_ERROR(status)) + { + status |= MT2063_GetLocked(h); + } + /* + ** If we locked OK, assign calculated data to MT2063_Info_t structure + */ + if (MT2063_NO_ERROR(status)) + { + pInfo->f_IF1_actual = pInfo->AS_Data.f_LO1 - f_in; + } + } + + return (status); +} + +UData_t MT_Tune_atv(Handle_t h, UData_t f_in, UData_t bw_in, enum MTTune_atv_standard tv_type) +{ + + UData_t status = MT2063_OK; + struct MT2063_Info_t* pInfo = (struct MT2063_Info_t*) h; + struct dvb_frontend *fe = (struct dvb_frontend *)pInfo->hUserData; + struct mt2063_state *state = fe->tuner_priv; + + SData_t pict_car = 0; + SData_t pict2chanb_vsb = 0; + SData_t pict2chanb_snd = 0; + SData_t pict2snd1 = 0; + SData_t pict2snd2 = 0; + SData_t ch_bw = 0; + + SData_t if_mid = 0; + SData_t rcvr_mode =0; + UData_t mode_get =0; + + + switch (tv_type) { + case MTTUNEA_PAL_B : { + pict_car = 38900000; + ch_bw = 8000000; + pict2chanb_vsb = -1250000; + pict2snd1 = 5500000; + pict2snd2 = 5742000; + rcvr_mode =1; + break; + } + case MTTUNEA_PAL_G : { + pict_car = 38900000; + ch_bw = 7000000; + pict2chanb_vsb = -1250000; + pict2snd1 = 5500000; + pict2snd2 = 0; + rcvr_mode =1; + break; + } + case MTTUNEA_PAL_I : { + pict_car = 38900000; + ch_bw = 8000000; + pict2chanb_vsb = -1250000; + pict2snd1 = 6000000; + pict2snd2 = 0; + rcvr_mode =1; + break; + } + case MTTUNEA_PAL_L : { + pict_car = 38900000; + ch_bw = 8000000; + pict2chanb_vsb = -1250000; + pict2snd1 = 6500000; + pict2snd2 = 0; + rcvr_mode =1; + break; + } + case MTTUNEA_PAL_MN : { + pict_car = 38900000; + ch_bw = 6000000; + pict2chanb_vsb = -1250000; + pict2snd1 = 4500000; + pict2snd2 = 0; + rcvr_mode =1; + break; + } + case MTTUNEA_PAL_DK : { + pict_car = 38900000; + ch_bw = 8000000; + pict2chanb_vsb = -1250000; + pict2snd1 = 6500000; + pict2snd2 = 0; + rcvr_mode =1; + break; + } + case MTTUNEA_DIGITAL : { + pict_car = 36125000; + ch_bw = 8000000; + pict2chanb_vsb = -(ch_bw/2); + pict2snd1 = 0; + pict2snd2 = 0; + rcvr_mode = 2; + break; + } + case MTTUNEA_FMRADIO : { + pict_car = 38900000; + ch_bw = 8000000; + pict2chanb_vsb = -(ch_bw/2); + pict2snd1 = 0; + pict2snd2 = 0; + rcvr_mode =4; + //f_in -= 2900000; + break; + } + case MTTUNEA_DVBC : { + pict_car = 36125000; + ch_bw = 8000000; + pict2chanb_vsb = -(ch_bw/2); + pict2snd1 = 0; + pict2snd2 = 0; + rcvr_mode = MT2063_CABLE_QAM; + break; + } + case MTTUNEA_DVBT : { + pict_car = 36125000; + ch_bw = bw_in;//8000000 + pict2chanb_vsb = -(ch_bw/2); + pict2snd1 = 0; + pict2snd2 = 0; + rcvr_mode = MT2063_OFFAIR_COFDM; + break; + } + case MTTUNEA_UNKNOWN : break; + default : break; + } + + pict2chanb_snd = pict2chanb_vsb - ch_bw; + if_mid = pict_car - (pict2chanb_vsb + (ch_bw/2) ); + + status |= MT2063_SetParam(h,MT2063_STEPSIZE,125000); + status |= MT2063_SetParam(h,MT2063_OUTPUT_FREQ,if_mid); + status |= MT2063_SetParam(h,MT2063_OUTPUT_BW,ch_bw); + status |=MT2063_GetParam(h,MT2063_RCVR_MODE,&mode_get); + + status |= MT2063_SetParam(h,MT2063_RCVR_MODE,rcvr_mode); + status |= MT2063_Tune(h,( f_in + (pict2chanb_vsb + (ch_bw/2) ) ) ); + status |=MT2063_GetParam(h,MT2063_RCVR_MODE,&mode_get); + + return (UData_t)status; +} + + +static int mt2063_init(struct dvb_frontend *fe) +{ + UData_t status = MT2063_ERROR; + struct mt2063_state *state = fe->tuner_priv; + + status = MT2063_Open(0xC0, &(state->MT2063_ht), fe); + status |= MT2063_SoftwareShutdown(state->MT2063_ht, 1); + status |= MT2063_ClearPowerMaskBits(state->MT2063_ht, MT2063_ALL_SD); + + if(MT2063_OK != status) + { + printk("%s %d error status = 0x%x!!\n", __func__, __LINE__, status); + return -1; + } + + return 0; +} + +static int mt2063_sleep(struct dvb_frontend *fe) +{ + /* TODO: power down */ + return 0; +} + +static int mt2063_get_status(struct dvb_frontend *fe, u32 *status) +{ + int rc = 0; + + //get tuner lock status + + return rc; +} + + +static int mt2063_get_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *state) +{ + struct mt2063_state *mt2063State = fe->tuner_priv; + + switch (param) { + case DVBFE_TUNER_FREQUENCY: + //get frequency + break; + case DVBFE_TUNER_TUNERSTEP: + break; + case DVBFE_TUNER_IFFREQ: + break; + case DVBFE_TUNER_BANDWIDTH: + //get bandwidth + break; + case DVBFE_TUNER_REFCLOCK: + state->refclock = (u32_t)MT2063_GetLocked((Handle_t)(mt2063State->MT2063_ht)); + break; + default: + break; + } + + return (int)state->refclock; +} + +static int mt2063_set_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *state) +{ + struct mt2063_state *mt2063State = fe->tuner_priv; + UData_t status = MT2063_OK; + + switch (param) { + case DVBFE_TUNER_FREQUENCY: + //set frequency + + status = MT_Tune_atv((Handle_t)(mt2063State->MT2063_ht), state->frequency, state->bandwidth, mt2063State->tv_type); + + mt2063State->frequency = state->frequency; + break; + case DVBFE_TUNER_TUNERSTEP: + break; + case DVBFE_TUNER_IFFREQ: + break; + case DVBFE_TUNER_BANDWIDTH: + //set bandwidth + mt2063State->bandwidth = state->bandwidth; + break; + case DVBFE_TUNER_REFCLOCK: + + break; + case DVBFE_TUNER_OPEN: + status = MT2063_Open(MT2063_I2C, &(mt2063State->MT2063_ht), fe); + break; + case DVBFE_TUNER_SOFTWARE_SHUTDOWN: + status = MT2063_SoftwareShutdown(mt2063State->MT2063_ht, 1); + break; + case DVBFE_TUNER_CLEAR_POWER_MASKBITS: + status = MT2063_ClearPowerMaskBits(mt2063State->MT2063_ht, MT2063_ALL_SD); + break; + default: + break; + } + + return (int)status; +} + +static int mt2063_release(struct dvb_frontend *fe) +{ + struct mt2063_state *state = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(state); + + return 0; +} + +static struct dvb_tuner_ops mt2063_ops = { + .info = { + .name = "MT2063 Silicon Tuner", + .frequency_min = 45000000, + .frequency_max = 850000000, + .frequency_step = 0, + }, + + .init = mt2063_init, + .sleep = mt2063_sleep, + .get_status = mt2063_get_status, + .get_state = mt2063_get_state, + .set_state = mt2063_set_state, + .release = mt2063_release +}; + +struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, + struct mt2063_config *config, + struct i2c_adapter *i2c) +{ + struct mt2063_state *state = NULL; + + state = kzalloc(sizeof (struct mt2063_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->config = config; + state->i2c = i2c; + state->frontend = fe; + state->reference = config->refclock / 1000; /* kHz */ + state->MT2063_init = FALSE; + fe->tuner_priv = state; + fe->ops.tuner_ops = mt2063_ops; + + printk("%s: Attaching MT2063 \n", __func__); + return fe; + +error: + kfree(state); + return NULL; +} + + + +EXPORT_SYMBOL(mt2063_attach); +MODULE_PARM_DESC(verbose, "Set Verbosity level"); + +MODULE_AUTHOR("Henry"); +MODULE_DESCRIPTION("MT2063 Silicon tuner"); +MODULE_LICENSE("GPL"); + + + diff --git a/drivers/media/common/tuners/mt2063.h b/drivers/media/common/tuners/mt2063.h new file mode 100644 index 000000000000..423d1a79b963 --- /dev/null +++ b/drivers/media/common/tuners/mt2063.h @@ -0,0 +1,729 @@ +#ifndef __MT2063_H__ +#define __MT2063_H__ + +#include +#include "dvb_frontend.h" + +//context of mt2063_errordef.h ====================================== +//################################################################# +//================================================================= + +/* +** Note to users: DO NOT EDIT THIS FILE +** +** If you wish to rename any of the "user defined" bits, +** it should be done in the user file that includes this +** source file (e.g. mt_userdef.h) +** +*/ + + + +#define MT2063_ERROR (1 << 31) +#define MT2063_USER_ERROR (1 << 30) + +/* Macro to be used to check for errors */ +#define MT2063_IS_ERROR(s) (((s) >> 30) != 0) +#define MT2063_NO_ERROR(s) (((s) >> 30) == 0) + + +#define MT2063_OK (0x00000000) + +/* Unknown error */ +#define MT2063_UNKNOWN (0x80000001) + +/* Error: Upconverter PLL is not locked */ +#define MT2063_UPC_UNLOCK (0x80000002) + +/* Error: Downconverter PLL is not locked */ +#define MT2063_DNC_UNLOCK (0x80000004) + +/* Error: Two-wire serial bus communications error */ +#define MT2063_COMM_ERR (0x80000008) + +/* Error: Tuner handle passed to function was invalid */ +#define MT2063_INV_HANDLE (0x80000010) + +/* Error: Function argument is invalid (out of range) */ +#define MT2063_ARG_RANGE (0x80000020) + +/* Error: Function argument (ptr to return value) was NULL */ +#define MT2063_ARG_NULL (0x80000040) + +/* Error: Attempt to open more than MT_TUNER_CNT tuners */ +#define MT2063_TUNER_CNT_ERR (0x80000080) + +/* Error: Tuner Part Code / Rev Code mismatches expected value */ +#define MT2063_TUNER_ID_ERR (0x80000100) + +/* Error: Tuner Initialization failure */ +#define MT2063_TUNER_INIT_ERR (0x80000200) + +#define MT2063_TUNER_OPEN_ERR (0x80000400) + +/* User-definable fields (see mt_userdef.h) */ +#define MT2063_USER_DEFINED1 (0x00001000) +#define MT2063_USER_DEFINED2 (0x00002000) +#define MT2063_USER_DEFINED3 (0x00004000) +#define MT2063_USER_DEFINED4 (0x00008000) +#define MT2063_USER_MASK (0x4000f000) +#define MT2063_USER_SHIFT (12) + +/* Info: Mask of bits used for # of LO-related spurs that were avoided during tuning */ +#define MT2063_SPUR_CNT_MASK (0x001f0000) +#define MT2063_SPUR_SHIFT (16) + +/* Info: Tuner timeout waiting for condition */ +#define MT2063_TUNER_TIMEOUT (0x00400000) + +/* Info: Unavoidable LO-related spur may be present in the output */ +#define MT2063_SPUR_PRESENT_ERR (0x00800000) + +/* Info: Tuner input frequency is out of range */ +#define MT2063_FIN_RANGE (0x01000000) + +/* Info: Tuner output frequency is out of range */ +#define MT2063_FOUT_RANGE (0x02000000) + +/* Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */ +#define MT2063_UPC_RANGE (0x04000000) + +/* Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */ +#define MT2063_DNC_RANGE (0x08000000) + +//end of mt2063_errordef.h +//================================================================= +//################################################################# +//================================================================= + +//context of mt2063_userdef.h ====================================== +//################################################################# +//================================================================= +/* +** Data Types +*/ +#define MT2060_CNT 10 + +typedef unsigned char U8Data; /* type corresponds to 8 bits */ +typedef unsigned int UData_t; /* type must be at least 32 bits */ +typedef int SData_t; /* type must be at least 32 bits */ +typedef void * Handle_t; /* memory pointer type */ +//typedef double FData_t; /* floating point data type */ + +#define MAX_UDATA (4294967295) /* max value storable in UData_t */ + +/* +** Define an MTxxxx_CNT macro for each type of tuner that will be built +** into your application (e.g., MT2121, MT2060). MT_TUNER_CNT +** must be set to the SUM of all of the MTxxxx_CNT macros. +** +** #define MT2050_CNT (1) +** #define MT2060_CNT (1) +** #define MT2111_CNT (1) +** #define MT2121_CNT (3) +*/ + +#define MT2063_CNT (1) + +#if !defined( MT2063_TUNER_CNT ) +#define MT2063_TUNER_CNT (1) /* total num of MicroTuner tuners */ +#endif +#define MT2063_I2C (0xC0) + +UData_t MT2063_WriteSub(Handle_t hUserData, + UData_t addr, + U8Data subAddress, + U8Data *pData, + UData_t cnt); + + +UData_t MT2063_ReadSub(Handle_t hUserData, + UData_t addr, + U8Data subAddress, + U8Data *pData, + UData_t cnt); + + +void MT2063_Sleep(Handle_t hUserData, + UData_t nMinDelayTime); + + +#if defined(MT2060_CNT) +#if MT2060_CNT > 0 +UData_t MT2060_TunerGain(Handle_t hUserData, + SData_t* pMeas); +#endif +#endif +//end of mt2063_userdef.h +//================================================================= +//################################################################# +//================================================================= + + +//context of mt2063_spruavoid.h ====================================== +//################################################################# +//================================================================= +/* +** Constant defining the version of the following structure +** and therefore the API for this code. +** +** When compiling the tuner driver, the preprocessor will +** check against this version number to make sure that +** it matches the version that the tuner driver knows about. +*/ +/* Version 010201 => 1.21 */ +#define MT2063_AVOID_SPURS_INFO_VERSION 010201 + + +/* DECT Frequency Avoidance */ +#define MT2063_DECT_AVOID_US_FREQS 0x00000001 + +#define MT2063_DECT_AVOID_EURO_FREQS 0x00000002 + +#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0) + +#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0) + + +enum MT2063_DECT_Avoid_Type +{ + MT2063_NO_DECT_AVOIDANCE = 0, /* Do not create DECT exclusion zones. */ + MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS, /* Avoid US DECT frequencies. */ + MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS, /* Avoid European DECT frequencies. */ + MT2063_AVOID_BOTH /* Avoid both regions. Not typically used. */ + +} ; + + +#define MT2063_MAX_ZONES 48 + +struct MT2063_ExclZone_t; + +struct MT2063_ExclZone_t +{ + UData_t min_; + UData_t max_; + struct MT2063_ExclZone_t* next_; +}; + +/* +** Structure of data needed for Spur Avoidance +*/ +struct MT2063_AvoidSpursData_t +{ + UData_t nAS_Algorithm; + UData_t f_ref; + UData_t f_in; + UData_t f_LO1; + UData_t f_if1_Center; + UData_t f_if1_Request; + UData_t f_if1_bw; + UData_t f_LO2; + UData_t f_out; + UData_t f_out_bw; + UData_t f_LO1_Step; + UData_t f_LO2_Step; + UData_t f_LO1_FracN_Avoid; + UData_t f_LO2_FracN_Avoid; + UData_t f_zif_bw; + UData_t f_min_LO_Separation; + UData_t maxH1; + UData_t maxH2; + enum MT2063_DECT_Avoid_Type avoidDECT; + UData_t bSpurPresent; + UData_t bSpurAvoided; + UData_t nSpursFound; + UData_t nZones; + struct MT2063_ExclZone_t* freeZones; + struct MT2063_ExclZone_t* usedZones; + struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES]; +}; + +UData_t MT2063_RegisterTuner(struct MT2063_AvoidSpursData_t* pAS_Info); + +void MT2063_UnRegisterTuner(struct MT2063_AvoidSpursData_t* pAS_Info); + +void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t* pAS_Info); + +void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t* pAS_Info, + UData_t f_min, + UData_t f_max); + +UData_t MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t* pAS_Info); + +UData_t MT2063_AvoidSpurs(Handle_t h, + struct MT2063_AvoidSpursData_t* pAS_Info); + +UData_t MT2063_AvoidSpursVersion(void); + +//end of mt2063_spuravoid.h +//================================================================= +//################################################################# +//================================================================= + + +/* +** Values returned by the MT2063's on-chip temperature sensor +** to be read/written. +*/ +enum MT2063_Temperature +{ + MT2063_T_0C = 0, /* Temperature approx 0C */ + MT2063_T_10C, /* Temperature approx 10C */ + MT2063_T_20C, /* Temperature approx 20C */ + MT2063_T_30C, /* Temperature approx 30C */ + MT2063_T_40C, /* Temperature approx 40C */ + MT2063_T_50C, /* Temperature approx 50C */ + MT2063_T_60C, /* Temperature approx 60C */ + MT2063_T_70C, /* Temperature approx 70C */ + MT2063_T_80C, /* Temperature approx 80C */ + MT2063_T_90C, /* Temperature approx 90C */ + MT2063_T_100C, /* Temperature approx 100C */ + MT2063_T_110C, /* Temperature approx 110C */ + MT2063_T_120C, /* Temperature approx 120C */ + MT2063_T_130C, /* Temperature approx 130C */ + MT2063_T_140C, /* Temperature approx 140C */ + MT2063_T_150C, /* Temperature approx 150C */ +}; + + +/* +** Parameters for selecting GPIO bits +*/ +enum MT2063_GPIO_Attr +{ + MT2063_GPIO_IN, + MT2063_GPIO_DIR, + MT2063_GPIO_OUT, +}; + +enum MT2063_GPIO_ID +{ + MT2063_GPIO0, + MT2063_GPIO1, + MT2063_GPIO2, +}; + + +/* +** Parameter for function MT2063_SetExtSRO that specifies the external +** SRO drive frequency. +** +** MT2063_EXT_SRO_OFF is the power-up default value. +*/ +enum MT2063_Ext_SRO +{ + MT2063_EXT_SRO_OFF, /* External SRO drive off */ + MT2063_EXT_SRO_BY_4, /* External SRO drive divide by 4 */ + MT2063_EXT_SRO_BY_2, /* External SRO drive divide by 2 */ + MT2063_EXT_SRO_BY_1 /* External SRO drive divide by 1 */ +}; + + +/* +** Parameter for function MT2063_SetPowerMask that specifies the power down +** of various sections of the MT2063. +*/ +enum MT2063_Mask_Bits +{ + MT2063_REG_SD = 0x0040, /* Shutdown regulator */ + MT2063_SRO_SD = 0x0020, /* Shutdown SRO */ + MT2063_AFC_SD = 0x0010, /* Shutdown AFC A/D */ + MT2063_PD_SD = 0x0002, /* Enable power detector shutdown */ + MT2063_PDADC_SD = 0x0001, /* Enable power detector A/D shutdown */ + MT2063_VCO_SD = 0x8000, /* Enable VCO shutdown */ + MT2063_LTX_SD = 0x4000, /* Enable LTX shutdown */ + MT2063_LT1_SD = 0x2000, /* Enable LT1 shutdown */ + MT2063_LNA_SD = 0x1000, /* Enable LNA shutdown */ + MT2063_UPC_SD = 0x0800, /* Enable upconverter shutdown */ + MT2063_DNC_SD = 0x0400, /* Enable downconverter shutdown */ + MT2063_VGA_SD = 0x0200, /* Enable VGA shutdown */ + MT2063_AMP_SD = 0x0100, /* Enable AMP shutdown */ + MT2063_ALL_SD = 0xFF73, /* All shutdown bits for this tuner */ + MT2063_NONE_SD = 0x0000 /* No shutdown bits */ +}; + + +/* +** Parameter for function MT2063_GetParam & MT2063_SetParam that +** specifies the tuning algorithm parameter to be read/written. +*/ +enum MT2063_Param +{ + /* tuner address set by MT2063_Open() */ + MT2063_IC_ADDR, + + /* max number of MT2063 tuners set by MT_TUNER_CNT in mt_userdef.h */ + MT2063_MAX_OPEN, + + /* current number of open MT2063 tuners set by MT2063_Open() */ + MT2063_NUM_OPEN, + + /* crystal frequency (default: 16000000 Hz) */ + MT2063_SRO_FREQ, + + /* min tuning step size (default: 50000 Hz) */ + MT2063_STEPSIZE, + + /* input center frequency set by MT2063_Tune() */ + MT2063_INPUT_FREQ, + + /* LO1 Frequency set by MT2063_Tune() */ + MT2063_LO1_FREQ, + + /* LO1 minimum step size (default: 250000 Hz) */ + MT2063_LO1_STEPSIZE, + + /* LO1 FracN keep-out region (default: 999999 Hz) */ + MT2063_LO1_FRACN_AVOID_PARAM, + + /* Current 1st IF in use set by MT2063_Tune() */ + MT2063_IF1_ACTUAL, + + /* Requested 1st IF set by MT2063_Tune() */ + MT2063_IF1_REQUEST, + + /* Center of 1st IF SAW filter (default: 1218000000 Hz) */ + MT2063_IF1_CENTER, + + /* Bandwidth of 1st IF SAW filter (default: 20000000 Hz) */ + MT2063_IF1_BW, + + /* zero-IF bandwidth (default: 2000000 Hz) */ + MT2063_ZIF_BW, + + /* LO2 Frequency set by MT2063_Tune() */ + MT2063_LO2_FREQ, + + /* LO2 minimum step size (default: 50000 Hz) */ + MT2063_LO2_STEPSIZE, + + /* LO2 FracN keep-out region (default: 374999 Hz) */ + MT2063_LO2_FRACN_AVOID, + + /* output center frequency set by MT2063_Tune() */ + MT2063_OUTPUT_FREQ, + + /* output bandwidth set by MT2063_Tune() */ + MT2063_OUTPUT_BW, + + /* min inter-tuner LO separation (default: 1000000 Hz) */ + MT2063_LO_SEPARATION, + + /* ID of avoid-spurs algorithm in use compile-time constant */ + MT2063_AS_ALG, + + /* max # of intra-tuner harmonics (default: 15) */ + MT2063_MAX_HARM1, + + /* max # of inter-tuner harmonics (default: 7) */ + MT2063_MAX_HARM2, + + /* # of 1st IF exclusion zones used set by MT2063_Tune() */ + MT2063_EXCL_ZONES, + + /* # of spurs found/avoided set by MT2063_Tune() */ + MT2063_NUM_SPURS, + + /* >0 spurs avoided set by MT2063_Tune() */ + MT2063_SPUR_AVOIDED, + + /* >0 spurs in output (mathematically) set by MT2063_Tune() */ + MT2063_SPUR_PRESENT, + + /* Receiver Mode for some parameters. 1 is DVB-T */ + MT2063_RCVR_MODE, + + /* directly set LNA attenuation, parameter is value to set */ + MT2063_ACLNA, + + /* maximum LNA attenuation, parameter is value to set */ + MT2063_ACLNA_MAX, + + /* directly set ATN attenuation. Paremeter is value to set. */ + MT2063_ACRF, + + /* maxium ATN attenuation. Paremeter is value to set. */ + MT2063_ACRF_MAX, + + /* directly set FIF attenuation. Paremeter is value to set. */ + MT2063_ACFIF, + + /* maxium FIF attenuation. Paremeter is value to set. */ + MT2063_ACFIF_MAX, + + /* LNA Rin */ + MT2063_LNA_RIN, + + /* Power Detector LNA level target */ + MT2063_LNA_TGT, + + /* Power Detector 1 level */ + MT2063_PD1, + + /* Power Detector 1 level target */ + MT2063_PD1_TGT, + + /* Power Detector 2 level */ + MT2063_PD2, + + /* Power Detector 2 level target */ + MT2063_PD2_TGT, + + /* Selects, which DNC is activ */ + MT2063_DNC_OUTPUT_ENABLE, + + /* VGA gain code */ + MT2063_VGAGC, + + /* VGA bias current */ + MT2063_VGAOI, + + /* TAGC, determins the speed of the AGC */ + MT2063_TAGC, + + /* AMP gain code */ + MT2063_AMPGC, + + /* Control setting to avoid DECT freqs (default: MT_AVOID_BOTH) */ + MT2063_AVOID_DECT, + + /* Cleartune filter selection: 0 - by IC (default), 1 - by software */ + MT2063_CTFILT_SW, + + MT2063_EOP /* last entry in enumerated list */ + +}; + + +/* +** Parameter for selecting tuner mode +*/ +enum MT2063_RCVR_MODES +{ + MT2063_CABLE_QAM = 0, /* Digital cable */ + MT2063_CABLE_ANALOG, /* Analog cable */ + MT2063_OFFAIR_COFDM, /* Digital offair */ + MT2063_OFFAIR_COFDM_SAWLESS, /* Digital offair without SAW */ + MT2063_OFFAIR_ANALOG, /* Analog offair */ + MT2063_OFFAIR_8VSB, /* Analog offair */ + MT2063_NUM_RCVR_MODES +}; + + +/* +** Possible values for MT2063_DNC_OUTPUT +*/ +enum MT2063_DNC_Output_Enable{ + MT2063_DNC_NONE = 0, + MT2063_DNC_1, + MT2063_DNC_2, + MT2063_DNC_BOTH +}; + +/* +** Two-wire serial bus subaddresses of the tuner registers. +** Also known as the tuner's register addresses. +*/ +enum MT2063_Register_Offsets +{ + MT2063_REG_PART_REV = 0, /* 0x00: Part/Rev Code */ + MT2063_REG_LO1CQ_1, /* 0x01: LO1C Queued Byte 1 */ + MT2063_REG_LO1CQ_2, /* 0x02: LO1C Queued Byte 2 */ + MT2063_REG_LO2CQ_1, /* 0x03: LO2C Queued Byte 1 */ + MT2063_REG_LO2CQ_2, /* 0x04: LO2C Queued Byte 2 */ + MT2063_REG_LO2CQ_3, /* 0x05: LO2C Queued Byte 3 */ + MT2063_REG_RSVD_06, /* 0x06: Reserved */ + MT2063_REG_LO_STATUS, /* 0x07: LO Status */ + MT2063_REG_FIFFC, /* 0x08: FIFF Center */ + MT2063_REG_CLEARTUNE, /* 0x09: ClearTune Filter */ + MT2063_REG_ADC_OUT, /* 0x0A: ADC_OUT */ + MT2063_REG_LO1C_1, /* 0x0B: LO1C Byte 1 */ + MT2063_REG_LO1C_2, /* 0x0C: LO1C Byte 2 */ + MT2063_REG_LO2C_1, /* 0x0D: LO2C Byte 1 */ + MT2063_REG_LO2C_2, /* 0x0E: LO2C Byte 2 */ + MT2063_REG_LO2C_3, /* 0x0F: LO2C Byte 3 */ + MT2063_REG_RSVD_10, /* 0x10: Reserved */ + MT2063_REG_PWR_1, /* 0x11: PWR Byte 1 */ + MT2063_REG_PWR_2, /* 0x12: PWR Byte 2 */ + MT2063_REG_TEMP_STATUS, /* 0x13: Temp Status */ + MT2063_REG_XO_STATUS, /* 0x14: Crystal Status */ + MT2063_REG_RF_STATUS, /* 0x15: RF Attn Status */ + MT2063_REG_FIF_STATUS, /* 0x16: FIF Attn Status */ + MT2063_REG_LNA_OV, /* 0x17: LNA Attn Override */ + MT2063_REG_RF_OV, /* 0x18: RF Attn Override */ + MT2063_REG_FIF_OV, /* 0x19: FIF Attn Override */ + MT2063_REG_LNA_TGT, /* 0x1A: Reserved */ + MT2063_REG_PD1_TGT, /* 0x1B: Pwr Det 1 Target */ + MT2063_REG_PD2_TGT, /* 0x1C: Pwr Det 2 Target */ + MT2063_REG_RSVD_1D, /* 0x1D: Reserved */ + MT2063_REG_RSVD_1E, /* 0x1E: Reserved */ + MT2063_REG_RSVD_1F, /* 0x1F: Reserved */ + MT2063_REG_RSVD_20, /* 0x20: Reserved */ + MT2063_REG_BYP_CTRL, /* 0x21: Bypass Control */ + MT2063_REG_RSVD_22, /* 0x22: Reserved */ + MT2063_REG_RSVD_23, /* 0x23: Reserved */ + MT2063_REG_RSVD_24, /* 0x24: Reserved */ + MT2063_REG_RSVD_25, /* 0x25: Reserved */ + MT2063_REG_RSVD_26, /* 0x26: Reserved */ + MT2063_REG_RSVD_27, /* 0x27: Reserved */ + MT2063_REG_FIFF_CTRL, /* 0x28: FIFF Control */ + MT2063_REG_FIFF_OFFSET, /* 0x29: FIFF Offset */ + MT2063_REG_CTUNE_CTRL, /* 0x2A: Reserved */ + MT2063_REG_CTUNE_OV, /* 0x2B: Reserved */ + MT2063_REG_CTRL_2C, /* 0x2C: Reserved */ + MT2063_REG_FIFF_CTRL2, /* 0x2D: Fiff Control */ + MT2063_REG_RSVD_2E, /* 0x2E: Reserved */ + MT2063_REG_DNC_GAIN, /* 0x2F: DNC Control */ + MT2063_REG_VGA_GAIN, /* 0x30: VGA Gain Ctrl */ + MT2063_REG_RSVD_31, /* 0x31: Reserved */ + MT2063_REG_TEMP_SEL, /* 0x32: Temperature Selection */ + MT2063_REG_RSVD_33, /* 0x33: Reserved */ + MT2063_REG_RSVD_34, /* 0x34: Reserved */ + MT2063_REG_RSVD_35, /* 0x35: Reserved */ + MT2063_REG_RSVD_36, /* 0x36: Reserved */ + MT2063_REG_RSVD_37, /* 0x37: Reserved */ + MT2063_REG_RSVD_38, /* 0x38: Reserved */ + MT2063_REG_RSVD_39, /* 0x39: Reserved */ + MT2063_REG_RSVD_3A, /* 0x3A: Reserved */ + MT2063_REG_RSVD_3B, /* 0x3B: Reserved */ + MT2063_REG_RSVD_3C, /* 0x3C: Reserved */ + MT2063_REG_END_REGS +}; + +struct MT2063_Info_t +{ + Handle_t handle; + Handle_t hUserData; + UData_t address; + UData_t version; + UData_t tuner_id; + struct MT2063_AvoidSpursData_t AS_Data; + UData_t f_IF1_actual; + UData_t rcvr_mode; + UData_t ctfilt_sw; + UData_t CTFiltMax[31]; + UData_t num_regs; + U8Data reg[MT2063_REG_END_REGS]; +} ; +typedef struct MT2063_Info_t* pMT2063_Info_t; + +enum MTTune_atv_standard{ + MTTUNEA_UNKNOWN = 0, + MTTUNEA_PAL_B, + MTTUNEA_PAL_G, + MTTUNEA_PAL_I, + MTTUNEA_PAL_L, + MTTUNEA_PAL_MN, + MTTUNEA_PAL_DK, + MTTUNEA_DIGITAL, + MTTUNEA_FMRADIO, + MTTUNEA_DVBC, + MTTUNEA_DVBT +}; + +/* ====== Functions which are declared in MT2063.c File ======= */ + +UData_t MT2063_Open(UData_t MT2063_Addr, + Handle_t* hMT2063, + Handle_t hUserData); + + +UData_t MT2063_Close(Handle_t hMT2063); + +UData_t MT2063_Tune(Handle_t h, + UData_t f_in); /* RF input center frequency */ + +UData_t MT2063_GetGPIO(Handle_t h, enum MT2063_GPIO_ID gpio_id, enum MT2063_GPIO_Attr attr, UData_t* value); + + +UData_t MT2063_GetLocked(Handle_t h); + + +UData_t MT2063_GetParam(Handle_t h, + enum MT2063_Param param, + UData_t* pValue); + + +UData_t MT2063_GetReg(Handle_t h, + U8Data reg, + U8Data* val); + + +UData_t MT2063_GetTemp(Handle_t h, enum MT2063_Temperature* value); + + +UData_t MT2063_GetUserData(Handle_t h, + Handle_t* hUserData); + +UData_t MT2063_ReInit(Handle_t h); + + +UData_t MT2063_SetGPIO(Handle_t h, enum MT2063_GPIO_ID gpio_id, enum MT2063_GPIO_Attr attr, UData_t value); + +UData_t MT2063_SetParam(Handle_t h, + enum MT2063_Param param, + UData_t nValue); + + +UData_t MT2063_SetPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits Bits); + +UData_t MT2063_ClearPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits Bits); + +UData_t MT2063_GetPowerMaskBits(Handle_t h, enum MT2063_Mask_Bits *Bits); + +UData_t MT2063_EnableExternalShutdown(Handle_t h, U8Data Enabled); + +UData_t MT2063_SoftwareShutdown(Handle_t h, U8Data Shutdown); + +UData_t MT2063_SetExtSRO(Handle_t h, enum MT2063_Ext_SRO Ext_SRO_Setting); + +UData_t MT2063_SetReg(Handle_t h, + U8Data reg, + U8Data val); + +UData_t MT_Tune_atv(Handle_t h, UData_t f_in,UData_t bw_in, enum MTTune_atv_standard tv_type); + + + +struct mt2063_config { + u8 tuner_address; + u32 refclock; +}; + +struct mt2063_state { + struct i2c_adapter *i2c; + + const struct mt2063_config *config; + struct dvb_tuner_ops ops; + struct dvb_frontend *frontend; + struct tuner_state status; + const struct MT2063_Info_t *MT2063_ht; + enum Bool_t MT2063_init; + + enum MTTune_atv_standard tv_type; + u32 frequency; + u32 srate; + u32 bandwidth; + u32 reference; +}; + +#if defined(CONFIG_DVB_MT2063) || (defined(CONFIG_DVB_MT2063_MODULE) && defined(MODULE)) + +extern struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, + struct mt2063_config *config, + struct i2c_adapter *i2c); + +#else + +static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe, + struct mt2063_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif //CONFIG_DVB_MT2063 + +#endif //__MT2063_H__ diff --git a/drivers/media/common/tuners/mt2063_cfg.h b/drivers/media/common/tuners/mt2063_cfg.h new file mode 100644 index 000000000000..2b6bd50eddde --- /dev/null +++ b/drivers/media/common/tuners/mt2063_cfg.h @@ -0,0 +1,111 @@ + + +static unsigned int mt2063_setTune(struct dvb_frontend *fe, UData_t f_in,UData_t bw_in, enum MTTune_atv_standard tv_type) +{ + //return (int)MT_Tune_atv(h, f_in, bw_in, tv_type); + + struct dvb_frontend_ops *frontend_ops = NULL; + struct dvb_tuner_ops *tuner_ops = NULL; + struct tuner_state t_state; + struct mt2063_state *mt2063State = fe->tuner_priv; + int err = 0; + + t_state.frequency = f_in; + t_state.bandwidth = bw_in; + mt2063State->tv_type = tv_type; + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->set_state) { + if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) { + printk("%s: Invalid parameter\n", __func__); + return err; + } + } + + return err; +} + +static unsigned int mt2063_lockStatus(struct dvb_frontend *fe) +{ + struct dvb_frontend_ops *frontend_ops = &fe->ops; + struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; + struct tuner_state t_state; + int err = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->get_state) { + if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_REFCLOCK, &t_state)) < 0) { + printk("%s: Invalid parameter\n", __func__); + return err; + } + } + return err; +} + +static unsigned int tuner_MT2063_Open(struct dvb_frontend *fe) +{ + struct dvb_frontend_ops *frontend_ops = &fe->ops; + struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; + struct tuner_state t_state; + int err = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->set_state) { + if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_OPEN, &t_state)) < 0) { + printk("%s: Invalid parameter\n", __func__); + return err; + } + } + + return err; +} + +static unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe) +{ + struct dvb_frontend_ops *frontend_ops = &fe->ops; + struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; + struct tuner_state t_state; + int err = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->set_state) { + if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_SOFTWARE_SHUTDOWN, &t_state)) < 0) { + printk("%s: Invalid parameter\n", __func__); + return err; + } + } + + return err; +} + +static unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe) +{ + struct dvb_frontend_ops *frontend_ops = &fe->ops; + struct dvb_tuner_ops *tuner_ops = &frontend_ops->tuner_ops; + struct tuner_state t_state; + int err = 0; + + if (&fe->ops) + frontend_ops = &fe->ops; + if (&frontend_ops->tuner_ops) + tuner_ops = &frontend_ops->tuner_ops; + if (tuner_ops->set_state) { + if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_CLEAR_POWER_MASKBITS, &t_state)) < 0) { + printk("%s: Invalid parameter\n", __func__); + return err; + } + } + + return err; +}