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