/*********************************************************************** * TX desense with WIFI/BT * ***********************************************************************/ int MT6620_TX_DESENSE(uint16_t freq, int *ctr) { int ret = 0; uint16_t dataRead = 0; uint16_t tmp = 0; FM_LOG_DBG(D_MAIN,"+%s, [freq=%d]\n", __func__, (int)freq); FM_COM_ASSERT(op_cb->read); FM_COM_ASSERT(op_cb->write); FM_COM_ASSERT(op_cb->setbits); // enable FM TX VCO tracking if((ret = op_cb->read(0x29, &dataRead)))//read 29 goto out; FM_LOG_NTC(D_MAIN,"Before VCO On, [0x29=0x%04x]\n", dataRead); if((ret = op_cb->read(0x12, &dataRead)))//read 12 goto out; FM_LOG_NTC(D_MAIN,"Before VCO On, [0x12=0x%04x]\n", dataRead); if((ret = op_cb->setbits(0x12, 0, MASK(15))))//set 12 D15=0 goto out; if((ret = op_cb->setbits(0x41, BITn(0), MASK(0))))//set 41 D0=1 goto out; if((ret = op_cb->setbits(0x48, BITn(15), MASK(15))))//set 48 D15=1 goto out; // wait 100ms (VCO tracking 100ms) if(*ctr > FM_TX_TRACKING_TIME_MAX){ *ctr = FM_TX_TRACKING_TIME_MAX; } Delayms(*ctr); // disable FM TX VCO tracking if((ret = op_cb->setbits(0x28, BITn(2), MASK(2))))//set 28 D2=1 goto out; if((ret = op_cb->read(0x29, &dataRead)))//read 29 D11~D0 goto out; FM_LOG_NTC(D_MAIN,"Before VCO Off, [0x29=0x%04x]\n", dataRead); tmp = dataRead&0x0FFF; // Read 0x29 D11~D0 if((ret = op_cb->read(0x12, &dataRead)))//read 12 goto out; //Set 0x12 D15 to 1, D11:D0 to read(0x29 D11~D0) dataRead &= 0xF000; dataRead |= tmp; dataRead |= 1<<15; if((ret = op_cb->write(0x12, dataRead))) goto out; FM_LOG_NTC(D_MAIN,"Before VCO Off, [0x12=0x%04x]\n", dataRead); if((ret = op_cb->setbits(0x48, 0, MASK(15))))//set 48 D15=0 goto out; if((ret = op_cb->setbits(0x41, 0, MASK(0))))//set 41 D0=0 goto out; out: FM_LOG_DBG(D_MAIN,"-%s, [freq=%d][delay=%dms][ret=%d]\n", __func__, (int)freq, *ctr, ret); return ret; }
/*********************************************************************** * TX PWR CTRL * ***********************************************************************/ int MT6620_TX_PWR_CTRL(uint16_t freq, int *ctr) { #define MT6620_TX_PWR_LEV_MAX 120 #define MT6620_TX_PWR_LEV_MIN 85 int ret = 0; int tmp = 0; uint16_t reg = 0; uint16_t coarse; uint16_t fine; FM_LOG_DBG(D_MAIN,"+%s, [freq=%d]\n", __func__, (int)freq); FM_COM_ASSERT(op_cb->read); FM_COM_ASSERT(op_cb->write); FM_COM_ASSERT(ctr); if(freq < FM_TX_PWR_CTRL_FREQ_THR){ //Power setting - 1dB, 3C(HEX)=A9E9 *ctr -= 1; }else{ //Power setting -2 dB, 3C(HEX)=A8E9 *ctr -= 2; } if(*ctr > MT6620_TX_PWR_LEV_MAX){ *ctr = MT6620_TX_PWR_LEV_MAX; }else if(*ctr < MT6620_TX_PWR_LEV_MIN){ *ctr = MT6620_TX_PWR_LEV_MIN; } fine = 43017 + ((1<<((*ctr-85)%6))-1)*32; FM_LOG_DBG(D_MAIN,"0x3C = 0x%04x \n", fine); coarse = 514 + ((1<<((*ctr-85)/6))-1)*4; FM_LOG_DBG(D_MAIN,"0x3D = 0x%04x \n", coarse); if((ret = op_cb->write(0x3C, fine))) goto out; if((ret = op_cb->write(0x3D, coarse))) goto out; tmp = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ); if((ret = op_cb->read(0x9C, ®))) goto out; reg &= 0xC0FF; if(tmp < FM_TX_PWR_CTRL_TMP_THR_DOWN){ reg |= (0x1C << 8); //9CH, D13~D8 = 1C }else if(tmp > FM_TX_PWR_CTRL_TMP_THR_UP){ reg |= (0x33 << 8); //9CH, D13~D8 ==33 }else{ reg |= (0x25 << 8); //9CH, D13~D8 =25 } if((ret = op_cb->write(0x9C, reg))) goto out; out: FM_LOG_NTC(D_MAIN,"-%s, [temp=%d][ret=%d]\n", __func__, (int)tmp, ret); return ret; }
//fm lock methods static fm_s32 fm_lock_try(struct fm_lock *thiz,fm_s32 retryCnt) { fm_s32 retry_cnt = 0; struct semaphore *sem; struct task_struct *task = current; FMR_ASSERT(thiz); FMR_ASSERT(thiz->priv); while(down_trylock((struct semaphore*)thiz->priv)) { WCN_DBG(FM_WAR | MAIN, "down_trylock failed\n"); if(++retry_cnt < retryCnt) { WCN_DBG(FM_WAR | MAIN,"[retryCnt=%d]\n", retry_cnt); msleep_interruptible(50); continue; } else { WCN_DBG(FM_CRT | MAIN,"down_trylock retry failed\n"); return -FM_ELOCK; } } sem = (struct semaphore*)thiz->priv; FM_LOG_DBG(MAIN, "%s --->trylock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count, task->pid); return 0; }
static fm_s32 fm_spin_lock_unlock(struct fm_lock *thiz) { struct task_struct *task = current; FMR_ASSERT(thiz); FMR_ASSERT(thiz->priv); FM_LOG_DBG(MAIN, "%s <---unlock, pid=%d\n", thiz->name, task->pid); spin_unlock_bh((spinlock_t *) thiz->priv); return 0; }
static fm_s32 fm_lock_unlock(struct fm_lock *thiz) { struct semaphore *sem; struct task_struct *task = current; FMR_ASSERT(thiz); FMR_ASSERT(thiz->priv); sem = (struct semaphore *)thiz->priv; FM_LOG_DBG(MAIN, "%s <---unlock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count + 1, task->pid); up((struct semaphore *)thiz->priv); return 0; }
/* fm try lock methods */ static fm_s32 fm_lock_lock(struct fm_lock *thiz) { struct semaphore *sem; struct task_struct *task = current; FMR_ASSERT(thiz); FMR_ASSERT(thiz->priv); if (down_interruptible((struct semaphore *)thiz->priv)) { WCN_DBG(FM_CRT | MAIN, "get mutex failed\n"); return -FM_ELOCK; } sem = (struct semaphore *)thiz->priv; FM_LOG_DBG(MAIN, "%s --->lock, cnt=%d, pid=%d\n", thiz->name, (int)sem->count, task->pid); return 0; }
/*********************************************************************** * Frequency Avoidance * ***********************************************************************/ int MT6620_MCU_Freq_Avoid(uint16_t freq, int *freqavoid) { int ret = 0; int mcuDsense = FM_MCU_DESENSE_DISABLE; uint16_t len = 0; uint16_t indx = 0; static uint16_t FreqList[] ={780, 794, 832, 926, 960, 1040}; FM_LOG_DBG(D_MAIN,"+%s, [freq=%d]\n", __func__, (int)freq); FM_COM_ASSERT(op_cb->read); FM_COM_ASSERT(op_cb->write); *freqavoid = 0; len = sizeof(FreqList)/sizeof(FreqList[0]); indx = 0; while((indx < len) && (mcuDsense != FM_MCU_DESENSE_ENABLE)){ if(FreqList[indx] == freq){ mcuDsense = FM_MCU_DESENSE_ENABLE; *freqavoid = 1; } indx++; } if(mcuDsense == FM_MCU_DESENSE_DISABLE){ if(mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_DISABLE)){ ret = 0; }else{ ret = -ERR_STP; } }else if(mcuDsense == FM_MCU_DESENSE_ENABLE){ if(mtk_wcn_wmt_dsns_ctrl(WMTDSNS_FM_ENABLE)){ ret = 0; }else{ ret = -ERR_STP; } }else{ FM_LOG_ERR(D_MAIN,"para error!\n"); ret = -ERR_INVALID_PARA; } FM_LOG_NTC(D_MAIN,"-%s, [mcuDsense=%d][ret=%d]\n", __func__, (int)mcuDsense, ret); return ret; }
/*********************************************************************** * Hi-Lo Side Injection * ***********************************************************************/ int MT6620_HL_Side_Adj(uint16_t freq, int *hl) { int ret = 0; int isHiSide= 0; int tblsize = 0; int indx = 0; uint16_t tmp; static uint16_t Hi_Channels[] = {795, 807, 821, 1064}; FM_LOG_DBG(D_INIT,"+%s, [freq=%d]\n", __func__, (int)freq); FM_COM_ASSERT(op_cb->read); FM_COM_ASSERT(op_cb->write); *hl = 0; if(sizeof(Hi_Channels) == 0) goto out; tblsize = sizeof(Hi_Channels)/sizeof(Hi_Channels[0]); for(indx = 0; indx < tblsize; indx++){ if(Hi_Channels[indx] == freq){ isHiSide = 1; *hl = 1; goto set_HL; } } set_HL: if(isHiSide){ //Set high-side injection (AFC) if((ret = op_cb->read(0x0F, &tmp))) goto out; if((ret = op_cb->write(0x0F, tmp |0x0400))) goto out; if((ret = op_cb->write(FM_MAIN_PGSEL, 0))) goto out; //Set high-side injection (DFE) if((ret = op_cb->read(0xCB, &tmp))) goto out; if((ret = op_cb->write(0xCB, tmp | 0x01))) goto out; //op_cb->write(0xCB, dataRead&0xFFFE); }else{ //Set low-side injection (AFC) if((ret = op_cb->read(0x0F, &tmp))) goto out; if((ret = op_cb->write(0x0F, tmp&0xFBFF))) goto out; if((ret = op_cb->write(FM_MAIN_PGSEL, 0))) goto out; //Set low-side injection (DFE) if((ret = op_cb->read(0xCB, &tmp))) goto out; //op_cb->write(0xCB, dataRead | 0x01); if((ret = op_cb->write(0xCB, tmp&0xFFFE))) goto out; } out: FM_LOG_NTC(D_INIT,"-%s, [isHiSide=%d][ret=%d]\n", __func__, (int)isHiSide, ret); return ret; }
/*********************************************************************** * TX RTC PWR CTRL * ***********************************************************************/ int MT6620_RTC_Drift_CTRL(uint16_t freq, int *ctr) { int ret = 0; uint16_t reg = 0; int chanel_resolution = 1; int16_t compensation_int16 = 0; int tmp = 0; int drift = *ctr; FM_LOG_DBG(D_MAIN,"+%s, [freq=%d]\n", __func__, (int)freq); FM_COM_ASSERT(op_cb->read); FM_COM_ASSERT(op_cb->write); FM_COM_ASSERT(op_cb->setbits); FM_COM_ASSERT(ctr); //turn off VCO tracking if((ret = op_cb->setbits(0x48, 0, MASK(15))))//set 48 D15=0 goto out; //get channel resolution if((ret = op_cb->read(0x46, ®))) goto out; reg &= 0xC000; switch(reg >> 14){ case 0: chanel_resolution = 1024; break; case 1: chanel_resolution = 512; break; case 2: chanel_resolution = 256; break; case 3: chanel_resolution = 128; break; default: FM_LOG_ERR(D_MAIN,"chanel_resolution error[%d]\n", (int)(reg >> 14)); break; } //caculate and applye compensation FM_LOG_DBG(D_MAIN,"[resolution=%d][freq=%d][drift=%d]\n", chanel_resolution, (int)(freq/10), (*ctr)); tmp = (2*drift*(freq/10))/chanel_resolution; compensation_int16 = (int16_t)tmp; if(compensation_int16 >= 511){ compensation_int16 = 511; }else if(compensation_int16 <= -512){ compensation_int16 = -512; } if((ret = op_cb->read(0x47, ®))) goto out; reg &= 0x003F; reg |= (compensation_int16 << 6); if((ret = op_cb->write(0x47, reg))) goto out; /* //turn on VCO tracking if((ret = op_cb->setbits(0x48, BITn(15), MASK(15))))//set 48 D15=1 goto out; */ out: FM_LOG_NTC(D_MAIN,"-%s, [compensation=%d][ret=%d]\n", __func__, (int)(compensation_int16), ret); return ret; }
/*********************************************************************** * Frequency Avoidance * ***********************************************************************/ int MT6620_ADPLL_Freq_Avoid(uint16_t freq, int *freqavoid) { int ret = 0; int ADPLL_clk = FM_ADPLL_15M; uint16_t dataRead = 0; uint16_t indx = 0; static uint16_t Avoid_Channels[] ={ 767, 768, 769, 770, 806, 807, 808, 844, 845, 846, 872, 883, 884, 920, 921, 922, 923, 936, 949, 960, 961, 998, 999, 1000, 1013, 1036, 1037, 1038, 1074, 1075, 1076, 1077}; FM_LOG_DBG(D_MAIN,"+%s, [freq=%d]\n", __func__, (int)freq); FM_COM_ASSERT(op_cb->read); FM_COM_ASSERT(op_cb->write); *freqavoid = 0; dataRead = sizeof(Avoid_Channels)/sizeof(Avoid_Channels[0]); indx = 0; while((indx < dataRead) && (ADPLL_clk != FM_ADPLL_16M)){ if(Avoid_Channels[indx] == freq){ ADPLL_clk = FM_ADPLL_16M; *freqavoid = 1; } indx++; } //isADPLL_16M = 1; if((ret = op_cb->read(0x1E, &dataRead))) goto out; if(((dataRead&BITn(9))&&(ADPLL_clk == FM_ADPLL_16M))||(!(dataRead&BITn(9))&&(ADPLL_clk == FM_ADPLL_15M)))//1EH, D9 goto out; //we need not do freq avoid at these caes if(ADPLL_clk == FM_ADPLL_16M){ //Set rgf_f16mode_en = X if((ret = op_cb->setbits(0x61, BITn(0), MASK(0))))//set 61H D0=1, 16.384MHZ goto out; }else if(ADPLL_clk == FM_ADPLL_15M){ //Set rgf_f16mode_en = X if((ret = op_cb->setbits(0x61, 0, MASK(0))))//set 61H D0=0, 15.36MHZ goto out; }else{ ret = -ERR_INVALID_PARA; goto out; } // Disable ADPLL ret = MT6620_ADPLL_Power_OnOff(FM_ADPLL_OFF, ADPLL_clk); if(ret){ FM_LOG_NTC(D_MAIN,"%s, ADPLL OFF failed, [ret=%d]n", __func__, ret); goto out; } //Set FMCR_DCO_CK_SEL = ? (default = 0, 15.36) if(ADPLL_clk == FM_ADPLL_16M){ if((ret = op_cb->setbits(0x1E, BITn(9), MASK(9))))//set 1EH D9=1, 16.384MHZ goto out; }else if(ADPLL_clk == FM_ADPLL_15M){ if((ret = op_cb->setbits(0x1E, 0, MASK(9))))//set 1EH D9=0, 15.36MHZ goto out; }else{ ret = -ERR_INVALID_PARA; goto out; } // Ensable ADPLL ret = MT6620_ADPLL_Power_OnOff(FM_ADPLL_ON, ADPLL_clk); if(ret){ FM_LOG_NTC(D_MAIN,"%s, ADPLL ON failed, [ret=%d]\n", __func__, ret); goto out; } //Set rgfrf_cnt_resync_b = 0 if((ret = op_cb->setbits(0x2A, 0, MASK(1))))//set 2AH D1=0 goto out; //Set rgfrf_cnt_resync_b = 1 if((ret = op_cb->setbits(0x2A, BITn(1), MASK(1))))//set 2AH D1=1 goto out; out: FM_LOG_NTC(D_MAIN,"-%s, [ADPLL_clk=%d][ret=%d]\n", __func__, (int)ADPLL_clk, ret); return ret; }