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
odm_SetCrystalCap(void * pDM_VOID,u8 CrystalCap)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
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
odm_GetDefaultCrytaltalCap(void * pDM_VOID)40 static u8 odm_GetDefaultCrytaltalCap(void *pDM_VOID)
41 {
42 PDM_ODM_T pDM_Odm = (PDM_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
odm_SetATCStatus(void * pDM_VOID,bool ATCStatus)50 static void odm_SetATCStatus(void *pDM_VOID, bool ATCStatus)
51 {
52 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
53 PCFO_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
odm_GetATCStatus(void * pDM_VOID)67 static bool odm_GetATCStatus(void *pDM_VOID)
68 {
69 bool ATCStatus;
70 PDM_ODM_T pDM_Odm = (PDM_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
ODM_CfoTrackingReset(void * pDM_VOID)80 void ODM_CfoTrackingReset(void *pDM_VOID)
81 {
82 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
83 PCFO_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
ODM_CfoTrackingInit(void * pDM_VOID)92 void ODM_CfoTrackingInit(void *pDM_VOID)
93 {
94 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
95 PCFO_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
ODM_CfoTracking(void * pDM_VOID)119 void ODM_CfoTracking(void *pDM_VOID)
120 {
121 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
122 PCFO_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
ODM_ParsingCFO(void * pDM_VOID,void * pPktinfo_VOID,s8 * pcfotail)298 void ODM_ParsingCFO(void *pDM_VOID, void *pPktinfo_VOID, s8 *pcfotail)
299 {
300 PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
301 struct odm_packet_info *pPktinfo = pPktinfo_VOID;
302 PCFO_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