1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * 4 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 5 * 6 ******************************************************************************/ 7 8 #include "odm_precomp.h" 9 10 static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap) 11 { 12 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 13 PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; 14 bool bEEPROMCheck; 15 struct adapter *Adapter = pDM_Odm->Adapter; 16 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); 17 18 bEEPROMCheck = pHalData->EEPROMVersion >= 0x01; 19 20 if (pCfoTrack->CrystalCap == CrystalCap) 21 return; 22 23 pCfoTrack->CrystalCap = CrystalCap; 24 25 /* 0x2C[23:18] = 0x2C[17:12] = CrystalCap */ 26 CrystalCap = CrystalCap & 0x3F; 27 PHY_SetBBReg( 28 pDM_Odm->Adapter, 29 REG_MAC_PHY_CTRL, 30 0x00FFF000, 31 (CrystalCap | (CrystalCap << 6)) 32 ); 33 34 ODM_RT_TRACE( 35 pDM_Odm, 36 ODM_COMP_CFO_TRACKING, 37 ODM_DBG_LOUD, 38 ( 39 "odm_SetCrystalCap(): CrystalCap = 0x%x\n", 40 CrystalCap 41 ) 42 ); 43 } 44 45 static u8 odm_GetDefaultCrytaltalCap(void *pDM_VOID) 46 { 47 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 48 u8 CrystalCap = 0x20; 49 50 struct adapter *Adapter = pDM_Odm->Adapter; 51 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); 52 53 CrystalCap = pHalData->CrystalCap; 54 55 CrystalCap = CrystalCap & 0x3f; 56 57 return CrystalCap; 58 } 59 60 static void odm_SetATCStatus(void *pDM_VOID, bool ATCStatus) 61 { 62 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 63 PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; 64 65 if (pCfoTrack->bATCStatus == ATCStatus) 66 return; 67 68 PHY_SetBBReg( 69 pDM_Odm->Adapter, 70 ODM_REG(BB_ATC, pDM_Odm), 71 ODM_BIT(BB_ATC, pDM_Odm), 72 ATCStatus 73 ); 74 pCfoTrack->bATCStatus = ATCStatus; 75 } 76 77 static bool odm_GetATCStatus(void *pDM_VOID) 78 { 79 bool ATCStatus; 80 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 81 82 ATCStatus = (bool)PHY_QueryBBReg( 83 pDM_Odm->Adapter, 84 ODM_REG(BB_ATC, pDM_Odm), 85 ODM_BIT(BB_ATC, pDM_Odm) 86 ); 87 return ATCStatus; 88 } 89 90 void ODM_CfoTrackingReset(void *pDM_VOID) 91 { 92 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 93 PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; 94 95 pCfoTrack->DefXCap = odm_GetDefaultCrytaltalCap(pDM_Odm); 96 pCfoTrack->bAdjust = true; 97 98 odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap); 99 odm_SetATCStatus(pDM_Odm, true); 100 } 101 102 void ODM_CfoTrackingInit(void *pDM_VOID) 103 { 104 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 105 PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; 106 107 pCfoTrack->DefXCap = 108 pCfoTrack->CrystalCap = odm_GetDefaultCrytaltalCap(pDM_Odm); 109 pCfoTrack->bATCStatus = odm_GetATCStatus(pDM_Odm); 110 pCfoTrack->bAdjust = true; 111 ODM_RT_TRACE( 112 pDM_Odm, 113 ODM_COMP_CFO_TRACKING, 114 ODM_DBG_LOUD, 115 ("ODM_CfoTracking_init() =========>\n") 116 ); 117 ODM_RT_TRACE( 118 pDM_Odm, 119 ODM_COMP_CFO_TRACKING, 120 ODM_DBG_LOUD, 121 ( 122 "ODM_CfoTracking_init(): bATCStatus = %d, CrystalCap = 0x%x\n", 123 pCfoTrack->bATCStatus, 124 pCfoTrack->DefXCap 125 ) 126 ); 127 } 128 129 void ODM_CfoTracking(void *pDM_VOID) 130 { 131 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 132 PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; 133 int CFO_kHz_A, CFO_kHz_B, CFO_ave = 0; 134 int CFO_ave_diff; 135 int CrystalCap = (int)pCfoTrack->CrystalCap; 136 u8 Adjust_Xtal = 1; 137 138 /* 4 Support ability */ 139 if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING)) { 140 ODM_RT_TRACE( 141 pDM_Odm, 142 ODM_COMP_CFO_TRACKING, 143 ODM_DBG_LOUD, 144 ("ODM_CfoTracking(): Return: SupportAbility ODM_BB_CFO_TRACKING is disabled\n") 145 ); 146 return; 147 } 148 149 ODM_RT_TRACE( 150 pDM_Odm, 151 ODM_COMP_CFO_TRACKING, 152 ODM_DBG_LOUD, 153 ("ODM_CfoTracking() =========>\n") 154 ); 155 156 if (!pDM_Odm->bLinked || !pDM_Odm->bOneEntryOnly) { 157 /* 4 No link or more than one entry */ 158 ODM_CfoTrackingReset(pDM_Odm); 159 ODM_RT_TRACE( 160 pDM_Odm, 161 ODM_COMP_CFO_TRACKING, 162 ODM_DBG_LOUD, 163 ( 164 "ODM_CfoTracking(): Reset: bLinked = %d, bOneEntryOnly = %d\n", 165 pDM_Odm->bLinked, 166 pDM_Odm->bOneEntryOnly 167 ) 168 ); 169 } else { 170 /* 3 1. CFO Tracking */ 171 /* 4 1.1 No new packet */ 172 if (pCfoTrack->packetCount == pCfoTrack->packetCount_pre) { 173 ODM_RT_TRACE( 174 pDM_Odm, 175 ODM_COMP_CFO_TRACKING, 176 ODM_DBG_LOUD, 177 ( 178 "ODM_CfoTracking(): packet counter doesn't change\n" 179 ) 180 ); 181 return; 182 } 183 pCfoTrack->packetCount_pre = pCfoTrack->packetCount; 184 185 /* 4 1.2 Calculate CFO */ 186 CFO_kHz_A = (int)(pCfoTrack->CFO_tail[0] * 3125) / 1280; 187 CFO_kHz_B = (int)(pCfoTrack->CFO_tail[1] * 3125) / 1280; 188 189 if (pDM_Odm->RFType < ODM_2T2R) 190 CFO_ave = CFO_kHz_A; 191 else 192 CFO_ave = (int)(CFO_kHz_A + CFO_kHz_B) >> 1; 193 ODM_RT_TRACE( 194 pDM_Odm, 195 ODM_COMP_CFO_TRACKING, 196 ODM_DBG_LOUD, 197 ( 198 "ODM_CfoTracking(): CFO_kHz_A = %dkHz, CFO_kHz_B = %dkHz, CFO_ave = %dkHz\n", 199 CFO_kHz_A, 200 CFO_kHz_B, 201 CFO_ave 202 ) 203 ); 204 205 /* 4 1.3 Avoid abnormal large CFO */ 206 CFO_ave_diff = 207 (pCfoTrack->CFO_ave_pre >= CFO_ave) ? 208 (pCfoTrack->CFO_ave_pre-CFO_ave) : 209 (CFO_ave-pCfoTrack->CFO_ave_pre); 210 211 if ( 212 CFO_ave_diff > 20 && 213 pCfoTrack->largeCFOHit == 0 && 214 !pCfoTrack->bAdjust 215 ) { 216 ODM_RT_TRACE(pDM_Odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking(): first large CFO hit\n")); 217 pCfoTrack->largeCFOHit = 1; 218 return; 219 } else 220 pCfoTrack->largeCFOHit = 0; 221 pCfoTrack->CFO_ave_pre = CFO_ave; 222 223 /* 4 1.4 Dynamic Xtal threshold */ 224 if (pCfoTrack->bAdjust == false) { 225 if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH)) 226 pCfoTrack->bAdjust = true; 227 } else { 228 if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW)) 229 pCfoTrack->bAdjust = false; 230 } 231 232 /* 4 1.5 BT case: Disable CFO tracking */ 233 if (pDM_Odm->bBtEnabled) { 234 pCfoTrack->bAdjust = false; 235 odm_SetCrystalCap(pDM_Odm, pCfoTrack->DefXCap); 236 ODM_RT_TRACE( 237 pDM_Odm, 238 ODM_COMP_CFO_TRACKING, 239 ODM_DBG_LOUD, 240 ("ODM_CfoTracking(): Disable CFO tracking for BT!!\n") 241 ); 242 } 243 244 /* 4 1.6 Big jump */ 245 if (pCfoTrack->bAdjust) { 246 if (CFO_ave > CFO_TH_XTAL_LOW) 247 Adjust_Xtal = Adjust_Xtal+((CFO_ave-CFO_TH_XTAL_LOW)>>2); 248 else if (CFO_ave < (-CFO_TH_XTAL_LOW)) 249 Adjust_Xtal = Adjust_Xtal+((CFO_TH_XTAL_LOW-CFO_ave)>>2); 250 251 ODM_RT_TRACE( 252 pDM_Odm, 253 ODM_COMP_CFO_TRACKING, 254 ODM_DBG_LOUD, 255 ( 256 "ODM_CfoTracking(): Crystal cap offset = %d\n", 257 Adjust_Xtal 258 ) 259 ); 260 } 261 262 /* 4 1.7 Adjust Crystal Cap. */ 263 if (pCfoTrack->bAdjust) { 264 if (CFO_ave > CFO_TH_XTAL_LOW) 265 CrystalCap = CrystalCap + Adjust_Xtal; 266 else if (CFO_ave < (-CFO_TH_XTAL_LOW)) 267 CrystalCap = CrystalCap - Adjust_Xtal; 268 269 if (CrystalCap > 0x3f) 270 CrystalCap = 0x3f; 271 else if (CrystalCap < 0) 272 CrystalCap = 0; 273 274 odm_SetCrystalCap(pDM_Odm, (u8)CrystalCap); 275 } 276 ODM_RT_TRACE( 277 pDM_Odm, 278 ODM_COMP_CFO_TRACKING, 279 ODM_DBG_LOUD, 280 ( 281 "ODM_CfoTracking(): Crystal cap = 0x%x, Default Crystal cap = 0x%x\n", 282 pCfoTrack->CrystalCap, 283 pCfoTrack->DefXCap 284 ) 285 ); 286 287 /* 3 2. Dynamic ATC switch */ 288 if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) { 289 odm_SetATCStatus(pDM_Odm, false); 290 ODM_RT_TRACE( 291 pDM_Odm, 292 ODM_COMP_CFO_TRACKING, 293 ODM_DBG_LOUD, 294 ("ODM_CfoTracking(): Disable ATC!!\n") 295 ); 296 } else { 297 odm_SetATCStatus(pDM_Odm, true); 298 ODM_RT_TRACE( 299 pDM_Odm, 300 ODM_COMP_CFO_TRACKING, 301 ODM_DBG_LOUD, 302 ("ODM_CfoTracking(): Enable ATC!!\n") 303 ); 304 } 305 } 306 } 307 308 void ODM_ParsingCFO(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail) 309 { 310 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; 311 struct odm_packet_info *pPktinfo = (struct odm_packet_info *)pPktinfo_VOID; 312 PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; 313 u8 i; 314 315 if (!(pDM_Odm->SupportAbility & ODM_BB_CFO_TRACKING)) 316 return; 317 318 if (pPktinfo->station_id != 0) { 319 /* 3 Update CFO report for path-A & path-B */ 320 /* Only paht-A and path-B have CFO tail and short CFO */ 321 for (i = ODM_RF_PATH_A; i <= ODM_RF_PATH_B; i++) 322 pCfoTrack->CFO_tail[i] = (int)pcfotail[i]; 323 324 /* 3 Update packet counter */ 325 if (pCfoTrack->packetCount == 0xffffffff) 326 pCfoTrack->packetCount = 0; 327 else 328 pCfoTrack->packetCount++; 329 } 330 } 331