GNU Linux-libre 4.19.314-gnu1
[releases.git] / drivers / staging / rtl8723bs / hal / odm_CfoTracking.c
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 }