/****************************************************************************** * * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * ******************************************************************************/ #include "mp_precomp.h" #include "phydm_precomp.h" #define CALCULATE_SWINGTALBE_OFFSET(_offset, _direction, _size, _deltaThermal) \ do {\ for(_offset = 0; _offset < _size; _offset++)\ {\ if(_deltaThermal < thermalThreshold[_direction][_offset])\ {\ if(_offset != 0)\ _offset--;\ break;\ }\ } \ if(_offset >= _size)\ _offset = _size-1;\ } while(0) void ConfigureTxpowerTrack( IN PDM_ODM_T pDM_Odm, OUT PTXPWRTRACK_CFG pConfig ) { #if RTL8192E_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8192E) ConfigureTxpowerTrack_8192E(pConfig); #endif #if RTL8821A_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8821) ConfigureTxpowerTrack_8821A(pConfig); #endif #if RTL8812A_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8812) ConfigureTxpowerTrack_8812A(pConfig); #endif #if RTL8188E_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8188E) ConfigureTxpowerTrack_8188E(pConfig); #endif #if RTL8188F_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8188F) ConfigureTxpowerTrack_8188F(pConfig); #endif #if RTL8723B_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8723B) ConfigureTxpowerTrack_8723B(pConfig); #endif #if RTL8814A_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8814A) ConfigureTxpowerTrack_8814A(pConfig); #endif #if RTL8703B_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8703B) ConfigureTxpowerTrack_8703B(pConfig); #endif #if RTL8822B_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8822B) ConfigureTxpowerTrack_8822B(pConfig); #endif #if RTL8723D_SUPPORT if (pDM_Odm->SupportICType == ODM_RTL8723D) ConfigureTxpowerTrack_8723D(pConfig); #endif } //====================================================================== // <20121113, Kordan> This function should be called when TxAGC changed. // Otherwise the previous compensation is gone, because we record the // delta of temperature between two TxPowerTracking watch dogs. // // NOTE: If Tx BB swing or Tx scaling is varified during run-time, still // need to call this function. //====================================================================== VOID ODM_ClearTxPowerTrackingState( IN PDM_ODM_T pDM_Odm ) { PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pDM_Odm->Adapter); u1Byte p = 0; PODM_RF_CAL_T pRFCalibrateInfo = &(pDM_Odm->RFCalibrateInfo); pRFCalibrateInfo->BbSwingIdxCckBase = pRFCalibrateInfo->DefaultCckIndex; pRFCalibrateInfo->BbSwingIdxCck = pRFCalibrateInfo->DefaultCckIndex; pRFCalibrateInfo->CCK_index = 0; for (p = ODM_RF_PATH_A; p < MAX_RF_PATH; ++p) { pRFCalibrateInfo->BbSwingIdxOfdmBase[p] = pRFCalibrateInfo->DefaultOfdmIndex; pRFCalibrateInfo->BbSwingIdxOfdm[p] = pRFCalibrateInfo->DefaultOfdmIndex; pRFCalibrateInfo->OFDM_index[p] = pRFCalibrateInfo->DefaultOfdmIndex; pRFCalibrateInfo->PowerIndexOffset[p] = 0; pRFCalibrateInfo->DeltaPowerIndex[p] = 0; pRFCalibrateInfo->DeltaPowerIndexLast[p] = 0; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = 0; /* Initial Mix mode power tracking*/ pRFCalibrateInfo->Remnant_OFDMSwingIdx[p] = 0; pRFCalibrateInfo->KfreeOffset[p] = 0; } pRFCalibrateInfo->Modify_TxAGC_Flag_PathA = FALSE; /*Initial at Modify Tx Scaling Mode*/ pRFCalibrateInfo->Modify_TxAGC_Flag_PathB = FALSE; /*Initial at Modify Tx Scaling Mode*/ pRFCalibrateInfo->Modify_TxAGC_Flag_PathC = FALSE; /*Initial at Modify Tx Scaling Mode*/ pRFCalibrateInfo->Modify_TxAGC_Flag_PathD = FALSE; /*Initial at Modify Tx Scaling Mode*/ pRFCalibrateInfo->Remnant_CCKSwingIdx = 0; pRFCalibrateInfo->ThermalValue = pHalData->EEPROMThermalMeter; pRFCalibrateInfo->Modify_TxAGC_Value_CCK=0; //modify by Mingzhi.Guo pRFCalibrateInfo->Modify_TxAGC_Value_OFDM=0; //modify by Mingzhi.Guo } VOID ODM_TXPowerTrackingCallback_ThermalMeter( #if (DM_ODM_SUPPORT_TYPE & ODM_AP) IN PDM_ODM_T pDM_Odm #else IN PADAPTER Adapter #endif ) { #if !(DM_ODM_SUPPORT_TYPE & ODM_AP) HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); #if (DM_ODM_SUPPORT_TYPE == ODM_WIN) PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc; #elif (DM_ODM_SUPPORT_TYPE == ODM_CE) PDM_ODM_T pDM_Odm = &pHalData->odmpriv; #endif #endif PODM_RF_CAL_T pRFCalibrateInfo = &(pDM_Odm->RFCalibrateInfo); u1Byte ThermalValue = 0, delta, delta_LCK, delta_IQK, p = 0, i = 0; s1Byte diff_DPK[4] = {0}; u1Byte ThermalValue_AVG_count = 0; u4Byte ThermalValue_AVG = 0, RegC80, RegCd0, RegCd4, Regab4; u1Byte OFDM_min_index = 0; // OFDM BB Swing should be less than +3.0dB, which is required by Arthur u1Byte Indexforchannel = 0; // GetRightChnlPlaceforIQK(pHalData->CurrentChannel) u1Byte PowerTrackingType = pHalData->RfPowerTrackingType; u1Byte XtalOffsetEanble = 0; TXPWRTRACK_CFG c; //4 1. The following TWO tables decide the final index of OFDM/CCK swing table. pu1Byte deltaSwingTableIdx_TUP_A = NULL; pu1Byte deltaSwingTableIdx_TDOWN_A = NULL; pu1Byte deltaSwingTableIdx_TUP_B = NULL; pu1Byte deltaSwingTableIdx_TDOWN_B = NULL; /*for 8814 add by Yu Chen*/ pu1Byte deltaSwingTableIdx_TUP_C = NULL; pu1Byte deltaSwingTableIdx_TDOWN_C = NULL; pu1Byte deltaSwingTableIdx_TUP_D = NULL; pu1Byte deltaSwingTableIdx_TDOWN_D = NULL; /*for Xtal Offset by James.Tung*/ ps1Byte deltaSwingTableXtal_UP = NULL; ps1Byte deltaSwingTableXtal_DOWN = NULL; //4 2. Initilization ( 7 steps in total ) ConfigureTxpowerTrack(pDM_Odm, &c); (*c.GetDeltaSwingTable)(pDM_Odm, (pu1Byte *)&deltaSwingTableIdx_TUP_A, (pu1Byte *)&deltaSwingTableIdx_TDOWN_A, (pu1Byte *)&deltaSwingTableIdx_TUP_B, (pu1Byte *)&deltaSwingTableIdx_TDOWN_B); if (pDM_Odm->SupportICType & ODM_RTL8814A) /*for 8814 path C & D*/ (*c.GetDeltaSwingTable8814only)(pDM_Odm, (pu1Byte *)&deltaSwingTableIdx_TUP_C, (pu1Byte *)&deltaSwingTableIdx_TDOWN_C, (pu1Byte *)&deltaSwingTableIdx_TUP_D, (pu1Byte *)&deltaSwingTableIdx_TDOWN_D); if (pDM_Odm->SupportICType & (ODM_RTL8703B | ODM_RTL8723D)) /*for Xtal Offset*/ (*c.GetDeltaSwingXtalTable)(pDM_Odm, (ps1Byte *)&deltaSwingTableXtal_UP, (ps1Byte *)&deltaSwingTableXtal_DOWN); pRFCalibrateInfo->TXPowerTrackingCallbackCnt++; /*cosa add for debug*/ pRFCalibrateInfo->bTXPowerTrackingInit = TRUE; /*pRFCalibrateInfo->TxPowerTrackControl = pHalData->TxPowerTrackControl; We should keep updating the control variable according to HalData. RFCalibrateInfo.RegA24 will be initialized when ODM HW configuring, but MP configures with para files. */ #if (DM_ODM_SUPPORT_TYPE & ODM_WIN) #if (MP_DRIVER == 1) pRFCalibrateInfo->RegA24 = 0x090e1317; #endif #elif (DM_ODM_SUPPORT_TYPE & ODM_CE) if (pDM_Odm->mp_mode == TRUE) pRFCalibrateInfo->RegA24 = 0x090e1317; #endif ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("===>ODM_TXPowerTrackingCallback_ThermalMeter\n pRFCalibrateInfo->BbSwingIdxCckBase: %d, pRFCalibrateInfo->BbSwingIdxOfdmBase[A]: %d, pRFCalibrateInfo->DefaultOfdmIndex: %d\n", pRFCalibrateInfo->BbSwingIdxCckBase, pRFCalibrateInfo->BbSwingIdxOfdmBase[ODM_RF_PATH_A], pRFCalibrateInfo->DefaultOfdmIndex)); ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("pRFCalibrateInfo->TxPowerTrackControl=%d, pHalData->EEPROMThermalMeter %d\n", pRFCalibrateInfo->TxPowerTrackControl, pHalData->EEPROMThermalMeter)); ThermalValue = (u1Byte)ODM_GetRFReg(pDM_Odm, ODM_RF_PATH_A, c.ThermalRegAddr, 0xfc00); //0x42: RF Reg[15:10] 88E /*add log by zhao he, check c80/c94/c14/ca0 value*/ if (pDM_Odm->SupportICType == ODM_RTL8723D) { RegC80 = ODM_GetBBReg(pDM_Odm, 0xc80, bMaskDWord); RegCd0 = ODM_GetBBReg(pDM_Odm, 0xcd0, bMaskDWord); RegCd4 = ODM_GetBBReg(pDM_Odm, 0xcd4, bMaskDWord); Regab4 = ODM_GetBBReg(pDM_Odm, 0xab4, 0x000007FF); ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("0xc80 = 0x%x 0xcd0 = 0x%x 0xcd4 = 0x%x 0xab4 = 0x%x\n", RegC80, RegCd0, RegCd4, Regab4)); } if (!pRFCalibrateInfo->TxPowerTrackControl) return; /*4 3. Initialize ThermalValues of RFCalibrateInfo*/ if (pRFCalibrateInfo->bReloadtxpowerindex) ODM_RT_TRACE(pDM_Odm,ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,("reload ofdm index for band switch\n")); /*4 4. Calculate average thermal meter*/ pRFCalibrateInfo->ThermalValue_AVG[pRFCalibrateInfo->ThermalValue_AVG_index] = ThermalValue; pRFCalibrateInfo->ThermalValue_AVG_index++; if (pRFCalibrateInfo->ThermalValue_AVG_index == c.AverageThermalNum) /*Average times = c.AverageThermalNum*/ pRFCalibrateInfo->ThermalValue_AVG_index = 0; for(i = 0; i < c.AverageThermalNum; i++) { if (pRFCalibrateInfo->ThermalValue_AVG[i]) { ThermalValue_AVG += pRFCalibrateInfo->ThermalValue_AVG[i]; ThermalValue_AVG_count++; } } if(ThermalValue_AVG_count) //Calculate Average ThermalValue after average enough times { ThermalValue = (u1Byte)(ThermalValue_AVG / ThermalValue_AVG_count); ODM_RT_TRACE(pDM_Odm,ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", ThermalValue, pHalData->EEPROMThermalMeter)); } //4 5. Calculate delta, delta_LCK, delta_IQK. //"delta" here is used to determine whether thermal value changes or not. delta = (ThermalValue > pRFCalibrateInfo->ThermalValue)?(ThermalValue - pRFCalibrateInfo->ThermalValue):(pRFCalibrateInfo->ThermalValue - ThermalValue); delta_LCK = (ThermalValue > pRFCalibrateInfo->ThermalValue_LCK)?(ThermalValue - pRFCalibrateInfo->ThermalValue_LCK):(pRFCalibrateInfo->ThermalValue_LCK - ThermalValue); delta_IQK = (ThermalValue > pRFCalibrateInfo->ThermalValue_IQK)?(ThermalValue - pRFCalibrateInfo->ThermalValue_IQK):(pRFCalibrateInfo->ThermalValue_IQK - ThermalValue); if (pRFCalibrateInfo->ThermalValue_IQK == 0xff) { /*no PG, use thermal value for IQK*/ pRFCalibrateInfo->ThermalValue_IQK = ThermalValue; delta_IQK = (ThermalValue > pRFCalibrateInfo->ThermalValue_IQK)?(ThermalValue - pRFCalibrateInfo->ThermalValue_IQK):(pRFCalibrateInfo->ThermalValue_IQK - ThermalValue); ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("no PG, use ThermalValue for IQK\n")); } for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) diff_DPK[p] = (s1Byte)ThermalValue - (s1Byte)pRFCalibrateInfo->DpkThermal[p]; /*4 6. If necessary, do LCK.*/ if (!(pDM_Odm->SupportICType & ODM_RTL8821)) { /*no PG , do LCK at initial status*/ if (pRFCalibrateInfo->ThermalValue_LCK == 0xff) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("no PG, do LCK\n")); pRFCalibrateInfo->ThermalValue_LCK = ThermalValue; /*Use RTLCK, so close power tracking driver LCK*/ if (!(pDM_Odm->SupportICType & ODM_RTL8814A)) { if (c.PHY_LCCalibrate) (*c.PHY_LCCalibrate)(pDM_Odm); } delta_LCK = (ThermalValue > pRFCalibrateInfo->ThermalValue_LCK)?(ThermalValue - pRFCalibrateInfo->ThermalValue_LCK):(pRFCalibrateInfo->ThermalValue_LCK - ThermalValue); } ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", delta, delta_LCK, delta_IQK)); /* Delta temperature is equal to or larger than 20 centigrade.*/ if (delta_LCK >= c.Threshold_IQK) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("delta_LCK(%d) >= Threshold_IQK(%d)\n", delta_LCK, c.Threshold_IQK)); pRFCalibrateInfo->ThermalValue_LCK = ThermalValue; /*Use RTLCK, so close power tracking driver LCK*/ if (!(pDM_Odm->SupportICType & ODM_RTL8814A)) { if (c.PHY_LCCalibrate) (*c.PHY_LCCalibrate)(pDM_Odm); } } } /*3 7. If necessary, move the index of swing table to adjust Tx power.*/ if (delta > 0 && pRFCalibrateInfo->TxPowerTrackControl) { //"delta" here is used to record the absolute value of differrence. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN|ODM_CE)) delta = ThermalValue > pHalData->EEPROMThermalMeter?(ThermalValue - pHalData->EEPROMThermalMeter):(pHalData->EEPROMThermalMeter - ThermalValue); #else delta = (ThermalValue > pDM_Odm->priv->pmib->dot11RFEntry.ther)?(ThermalValue - pDM_Odm->priv->pmib->dot11RFEntry.ther):(pDM_Odm->priv->pmib->dot11RFEntry.ther - ThermalValue); #endif if (delta >= TXPWR_TRACK_TABLE_SIZE) delta = TXPWR_TRACK_TABLE_SIZE - 1; /*4 7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN|ODM_CE)) if(ThermalValue > pHalData->EEPROMThermalMeter) { #else if(ThermalValue > pDM_Odm->priv->pmib->dot11RFEntry.ther) { #endif for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { pRFCalibrateInfo->DeltaPowerIndexLast[p] = pRFCalibrateInfo->DeltaPowerIndex[p]; /*recording poer index offset*/ switch (p) { case ODM_RF_PATH_B: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TUP_B[%d] = %d\n", delta, deltaSwingTableIdx_TUP_B[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = deltaSwingTableIdx_TUP_B[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = deltaSwingTableIdx_TUP_B[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is higher and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; case ODM_RF_PATH_C: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TUP_C[%d] = %d\n", delta, deltaSwingTableIdx_TUP_C[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = deltaSwingTableIdx_TUP_C[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = deltaSwingTableIdx_TUP_C[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is higher and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_C] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; case ODM_RF_PATH_D: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TUP_D[%d] = %d\n", delta, deltaSwingTableIdx_TUP_D[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = deltaSwingTableIdx_TUP_D[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = deltaSwingTableIdx_TUP_D[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is higher and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_D] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; default: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TUP_A[%d] = %d\n", delta, deltaSwingTableIdx_TUP_A[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = deltaSwingTableIdx_TUP_A[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = deltaSwingTableIdx_TUP_A[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is higher and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; } } if (pDM_Odm->SupportICType & (ODM_RTL8703B | ODM_RTL8723D)) { /*Save XtalOffset from Xtal table*/ pRFCalibrateInfo->XtalOffsetLast = pRFCalibrateInfo->XtalOffset; /*recording last Xtal offset*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("[Xtal] deltaSwingTableXtal_UP[%d] = %d\n", delta, deltaSwingTableXtal_UP[delta])); pRFCalibrateInfo->XtalOffset = deltaSwingTableXtal_UP[delta]; if (pRFCalibrateInfo->XtalOffsetLast == pRFCalibrateInfo->XtalOffset) XtalOffsetEanble = 0; else XtalOffsetEanble = 1; } } else { for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { pRFCalibrateInfo->DeltaPowerIndexLast[p] = pRFCalibrateInfo->DeltaPowerIndex[p]; /*recording poer index offset*/ switch (p) { case ODM_RF_PATH_B: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TDOWN_B[%d] = %d\n", delta, deltaSwingTableIdx_TDOWN_B[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = -1 * deltaSwingTableIdx_TDOWN_B[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = -1 * deltaSwingTableIdx_TDOWN_B[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is lower and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; case ODM_RF_PATH_C: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TDOWN_C[%d] = %d\n", delta, deltaSwingTableIdx_TDOWN_C[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = -1 * deltaSwingTableIdx_TDOWN_C[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = -1 * deltaSwingTableIdx_TDOWN_C[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is lower and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_C] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; case ODM_RF_PATH_D: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TDOWN_D[%d] = %d\n", delta, deltaSwingTableIdx_TDOWN_D[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = -1 * deltaSwingTableIdx_TDOWN_D[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = -1 * deltaSwingTableIdx_TDOWN_D[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is lower and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_D] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; default: ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("deltaSwingTableIdx_TDOWN_A[%d] = %d\n", delta, deltaSwingTableIdx_TDOWN_A[delta])); pRFCalibrateInfo->DeltaPowerIndex[p] = -1 * deltaSwingTableIdx_TDOWN_A[delta]; pRFCalibrateInfo->Absolute_OFDMSwingIdx[p] = -1 * deltaSwingTableIdx_TDOWN_A[delta]; /*Record delta swing for mix mode power tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("******Temp is lower and pRFCalibrateInfo->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", pRFCalibrateInfo->Absolute_OFDMSwingIdx[p])); break; } } if (pDM_Odm->SupportICType & (ODM_RTL8703B | ODM_RTL8723D)) { /*Save XtalOffset from Xtal table*/ pRFCalibrateInfo->XtalOffsetLast = pRFCalibrateInfo->XtalOffset; /*recording last Xtal offset*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("[Xtal] deltaSwingTableXtal_DOWN[%d] = %d\n", delta, deltaSwingTableXtal_DOWN[delta])); pRFCalibrateInfo->XtalOffset = deltaSwingTableXtal_DOWN[delta]; if (pRFCalibrateInfo->XtalOffsetLast == pRFCalibrateInfo->XtalOffset) XtalOffsetEanble = 0; else XtalOffsetEanble = 1; } } for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("\n\n=========================== [Path-%d] Calculating PowerIndexOffset===========================\n", p)); if (pRFCalibrateInfo->DeltaPowerIndex[p] == pRFCalibrateInfo->DeltaPowerIndexLast[p]) /*If Thermal value changes but lookup table value still the same*/ pRFCalibrateInfo->PowerIndexOffset[p] = 0; else pRFCalibrateInfo->PowerIndexOffset[p] = pRFCalibrateInfo->DeltaPowerIndex[p] - pRFCalibrateInfo->DeltaPowerIndexLast[p]; /*Power Index Diff between 2 times Power Tracking*/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("[Path-%d] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n", p, pRFCalibrateInfo->PowerIndexOffset[p], pRFCalibrateInfo->DeltaPowerIndex[p], pRFCalibrateInfo->DeltaPowerIndexLast[p])); pRFCalibrateInfo->OFDM_index[p] = pRFCalibrateInfo->BbSwingIdxOfdmBase[p] + pRFCalibrateInfo->PowerIndexOffset[p]; pRFCalibrateInfo->CCK_index = pRFCalibrateInfo->BbSwingIdxCckBase + pRFCalibrateInfo->PowerIndexOffset[p]; pRFCalibrateInfo->BbSwingIdxCck = pRFCalibrateInfo->CCK_index; pRFCalibrateInfo->BbSwingIdxOfdm[p] = pRFCalibrateInfo->OFDM_index[p]; /*************Print BB Swing Base and Index Offset*************/ ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", pRFCalibrateInfo->BbSwingIdxCck, pRFCalibrateInfo->BbSwingIdxCckBase, pRFCalibrateInfo->PowerIndexOffset[p])); ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("The 'OFDM' final index(%d) = BaseIndex[%d](%d) + PowerIndexOffset(%d)\n", pRFCalibrateInfo->BbSwingIdxOfdm[p], p, pRFCalibrateInfo->BbSwingIdxOfdmBase[p], pRFCalibrateInfo->PowerIndexOffset[p])); /*4 7.1 Handle boundary conditions of index.*/ if (pRFCalibrateInfo->OFDM_index[p] > c.SwingTableSize_OFDM-1) pRFCalibrateInfo->OFDM_index[p] = c.SwingTableSize_OFDM-1; else if (pRFCalibrateInfo->OFDM_index[p] <= OFDM_min_index) pRFCalibrateInfo->OFDM_index[p] = OFDM_min_index; } ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("\n\n========================================================================================================\n")); if (pRFCalibrateInfo->CCK_index > c.SwingTableSize_CCK-1) pRFCalibrateInfo->CCK_index = c.SwingTableSize_CCK-1; else if (pRFCalibrateInfo->CCK_index <= 0) pRFCalibrateInfo->CCK_index = 0; } else { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pRFCalibrateInfo->ThermalValue: %d\n", pRFCalibrateInfo->TxPowerTrackControl, ThermalValue, pRFCalibrateInfo->ThermalValue)); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) pRFCalibrateInfo->PowerIndexOffset[p] = 0; } ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n", pRFCalibrateInfo->CCK_index, pRFCalibrateInfo->BbSwingIdxCckBase)); /*Print Swing base & current*/ for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%d]: %d\n", pRFCalibrateInfo->OFDM_index[p], p, pRFCalibrateInfo->BbSwingIdxOfdmBase[p])); } if ((pDM_Odm->SupportICType & ODM_RTL8814A)) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("PowerTrackingType=%d\n", PowerTrackingType)); if (PowerTrackingType == 0) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX_MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0); } else if (PowerTrackingType == 1) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX(2G) TSSI(5G) MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_2G_TSSI_5G_MODE, p, 0); } else if (PowerTrackingType == 2) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX(5G) TSSI(2G)MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_5G_TSSI_2G_MODE, p, 0); } else if (PowerTrackingType == 3) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking TSSI MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, TSSI_MODE, p, 0); } pRFCalibrateInfo->ThermalValue = ThermalValue; /*Record last Power Tracking Thermal Value*/ } else if ((pRFCalibrateInfo->PowerIndexOffset[ODM_RF_PATH_A] != 0 || pRFCalibrateInfo->PowerIndexOffset[ODM_RF_PATH_B] != 0 || pRFCalibrateInfo->PowerIndexOffset[ODM_RF_PATH_C] != 0 || pRFCalibrateInfo->PowerIndexOffset[ODM_RF_PATH_D] != 0) && pRFCalibrateInfo->TxPowerTrackControl && (pHalData->EEPROMThermalMeter != 0xff)) { //4 7.2 Configure the Swing Table to adjust Tx Power. pRFCalibrateInfo->bTxPowerChanged = TRUE; /*Always TRUE after Tx Power is adjusted by power tracking.*/ // // 2012/04/23 MH According to Luke's suggestion, we can not write BB digital // to increase TX power. Otherwise, EVM will be bad. // // 2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. if (ThermalValue > pRFCalibrateInfo->ThermalValue) { for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Temperature Increasing(%d): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", p, pRFCalibrateInfo->PowerIndexOffset[p], delta, ThermalValue, pHalData->EEPROMThermalMeter, pRFCalibrateInfo->ThermalValue)); } } else if (ThermalValue < pRFCalibrateInfo->ThermalValue) { /*Low temperature*/ for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Temperature Decreasing(%d): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", p, pRFCalibrateInfo->PowerIndexOffset[p], delta, ThermalValue, pHalData->EEPROMThermalMeter, pRFCalibrateInfo->ThermalValue)); } } #if !(DM_ODM_SUPPORT_TYPE & ODM_AP) if (ThermalValue > pHalData->EEPROMThermalMeter) #else if (ThermalValue > pDM_Odm->priv->pmib->dot11RFEntry.ther) #endif { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Temperature(%d) higher than PG value(%d)\n", ThermalValue, pHalData->EEPROMThermalMeter)); if (pDM_Odm->SupportICType == ODM_RTL8188E || pDM_Odm->SupportICType == ODM_RTL8192E || pDM_Odm->SupportICType == ODM_RTL8821 || pDM_Odm->SupportICType == ODM_RTL8812 || pDM_Odm->SupportICType == ODM_RTL8723B || pDM_Odm->SupportICType == ODM_RTL8814A || pDM_Odm->SupportICType == ODM_RTL8703B || pDM_Odm->SupportICType == ODM_RTL8188F || pDM_Odm->SupportICType == ODM_RTL8822B || pDM_Odm->SupportICType == ODM_RTL8723D) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX_MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, 0); } else { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking BBSWING_MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, BBSWING, p, Indexforchannel); } } else { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Temperature(%d) lower than PG value(%d)\n", ThermalValue, pHalData->EEPROMThermalMeter)); if (pDM_Odm->SupportICType == ODM_RTL8188E || pDM_Odm->SupportICType == ODM_RTL8192E || pDM_Odm->SupportICType == ODM_RTL8821 || pDM_Odm->SupportICType == ODM_RTL8812 || pDM_Odm->SupportICType == ODM_RTL8723B || pDM_Odm->SupportICType == ODM_RTL8814A || pDM_Odm->SupportICType == ODM_RTL8703B || pDM_Odm->SupportICType == ODM_RTL8188F || pDM_Odm->SupportICType == ODM_RTL8822B || pDM_Odm->SupportICType == ODM_RTL8723D) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking MIX_MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, MIX_MODE, p, Indexforchannel); } else { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter POWER Tracking BBSWING_MODE**********\n")); for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) (*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, BBSWING, p, Indexforchannel); } } pRFCalibrateInfo->BbSwingIdxCckBase = pRFCalibrateInfo->BbSwingIdxCck; /*Record last time Power Tracking result as base.*/ for (p = ODM_RF_PATH_A; p < c.RfPathCount; p++) pRFCalibrateInfo->BbSwingIdxOfdmBase[p] = pRFCalibrateInfo->BbSwingIdxOfdm[p]; ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("pRFCalibrateInfo->ThermalValue = %d ThermalValue= %d\n", pRFCalibrateInfo->ThermalValue, ThermalValue)); pRFCalibrateInfo->ThermalValue = ThermalValue; /*Record last Power Tracking Thermal Value*/ } if (pDM_Odm->SupportICType == ODM_RTL8703B || pDM_Odm->SupportICType == ODM_RTL8723D) { if (XtalOffsetEanble != 0 && pRFCalibrateInfo->TxPowerTrackControl && (pHalData->EEPROMThermalMeter != 0xff)) { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********Enter Xtal Tracking**********\n")); #if !(DM_ODM_SUPPORT_TYPE & ODM_AP) if (ThermalValue > pHalData->EEPROMThermalMeter) { #else if (ThermalValue > pDM_Odm->priv->pmib->dot11RFEntry.ther) { #endif ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Temperature(%d) higher than PG value(%d)\n", ThermalValue, pHalData->EEPROMThermalMeter)); (*c.ODM_TxXtalTrackSetXtal)(pDM_Odm); } else { ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("Temperature(%d) lower than PG value(%d)\n", ThermalValue, pHalData->EEPROMThermalMeter)); (*c.ODM_TxXtalTrackSetXtal)(pDM_Odm); } } ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("**********End Xtal Tracking**********\n")); } #if !(DM_ODM_SUPPORT_TYPE & ODM_AP) if (!IS_HARDWARE_TYPE_8723B(Adapter)) { /*Delta temperature is equal to or larger than 20 centigrade (When threshold is 8).*/ if (delta_IQK >= c.Threshold_IQK) { pRFCalibrateInfo->ThermalValue_IQK = ThermalValue; ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("delta_IQK(%d) >= Threshold_IQK(%d)\n", delta_IQK, c.Threshold_IQK)); if (!pRFCalibrateInfo->bIQKInProgress) (*c.DoIQK)(pDM_Odm, delta_IQK, ThermalValue, 8); } } if (pRFCalibrateInfo->DpkThermal[ODM_RF_PATH_A] != 0) { if (diff_DPK[ODM_RF_PATH_A] >= c.Threshold_DPK) { ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x1); ODM_SetBBReg(pDM_Odm, 0xcc4, BIT14|BIT13|BIT12|BIT11|BIT10, (diff_DPK[ODM_RF_PATH_A] / c.Threshold_DPK)); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x0); } else if ((diff_DPK[ODM_RF_PATH_A] <= -1 * c.Threshold_DPK)) { s4Byte value = 0x20 + (diff_DPK[ODM_RF_PATH_A] / c.Threshold_DPK); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x1); ODM_SetBBReg(pDM_Odm, 0xcc4, BIT14|BIT13|BIT12|BIT11|BIT10, value); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x0); } else { ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x1); ODM_SetBBReg(pDM_Odm, 0xcc4, BIT14|BIT13|BIT12|BIT11|BIT10, 0); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x0); } } if (pRFCalibrateInfo->DpkThermal[ODM_RF_PATH_B] != 0) { if (diff_DPK[ODM_RF_PATH_B] >= c.Threshold_DPK) { ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x1); ODM_SetBBReg(pDM_Odm, 0xec4, BIT14|BIT13|BIT12|BIT11|BIT10, (diff_DPK[ODM_RF_PATH_B] / c.Threshold_DPK)); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x0); } else if ((diff_DPK[ODM_RF_PATH_B] <= -1 * c.Threshold_DPK)) { s4Byte value = 0x20 + (diff_DPK[ODM_RF_PATH_B] / c.Threshold_DPK); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x1); ODM_SetBBReg(pDM_Odm, 0xec4, BIT14|BIT13|BIT12|BIT11|BIT10, value); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x0); } else { ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x1); ODM_SetBBReg(pDM_Odm, 0xec4, BIT14|BIT13|BIT12|BIT11|BIT10, 0); ODM_SetBBReg(pDM_Odm, 0x82c, BIT(31), 0x0); } } #endif ODM_RT_TRACE(pDM_Odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD, ("<===ODM_TXPowerTrackingCallback_ThermalMeter\n")); pRFCalibrateInfo->TXPowercount = 0; } //3============================================================ //3 IQ Calibration //3============================================================ VOID ODM_ResetIQKResult( IN PDM_ODM_T pDM_Odm ) { return; } #if !(DM_ODM_SUPPORT_TYPE & ODM_AP) u1Byte ODM_GetRightChnlPlaceforIQK(u1Byte chnl) { u1Byte channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,149,151,153,155,157,159,161,163,165}; u1Byte place = chnl; if(chnl > 14) { for(place = 14; placeAdapter; #if (DM_ODM_SUPPORT_TYPE == ODM_WIN) if (*pDM_Odm->pIsFcsModeEnable) return; #endif if (pDM_Odm->bLinked) { if ((*pDM_Odm->pChannel != pDM_Odm->preChannel) && (!*pDM_Odm->pbScanInProcess)) { pDM_Odm->preChannel = *pDM_Odm->pChannel; pDM_Odm->LinkedInterval = 0; } if (pDM_Odm->LinkedInterval < 3) pDM_Odm->LinkedInterval++; if (pDM_Odm->LinkedInterval == 2) { PHY_IQCalibrate(Adapter, FALSE); } } else pDM_Odm->LinkedInterval = 0; } void phydm_rf_init(IN PDM_ODM_T pDM_Odm) { odm_TXPowerTrackingInit(pDM_Odm); #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN|ODM_CE)) ODM_ClearTxPowerTrackingState(pDM_Odm); #endif #if (DM_ODM_SUPPORT_TYPE & (ODM_AP)) #if (RTL8814A_SUPPORT == 1) if (pDM_Odm->SupportICType & ODM_RTL8814A) PHY_IQCalibrate_8814A_Init(pDM_Odm); #endif #endif } void phydm_rf_watchdog(IN PDM_ODM_T pDM_Odm) { #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN|ODM_CE)) ODM_TXPowerTrackingCheck(pDM_Odm); if (pDM_Odm->SupportICType & ODM_IC_11AC_SERIES) odm_IQCalibrate(pDM_Odm); #endif }